Retire shade

Change-Id: I6742309f6454417485742d53fd24dc1b66a7538b
Signed-off-by: Stephen Finucane <stephenfin@redhat.com>
Depends-on: https://review.opendev.org/c/openstack/project-config/+/961522
This commit is contained in:
Stephen Finucane committed 2025-09-17 18:07:54 +01:00
1 parent b9dc7d04cc
commit dbf80ad2d8
341 files changed
+7 -51514

No files matched your search

-7
View File
@@ -1,7 +0,0 @@
[run]
branch = True
source = shade
omit = shade/tests/*
[report]
ignore_errors = True
-54
View File
@@ -1,54 +0,0 @@
*.py[cod]
# C extensions
*.so
# Packages
.eggs
*.egg
*.egg-info
dist
build
eggs
parts
bin
var
sdist
develop-eggs
.installed.cfg
lib
lib64
# Installer logs
pip-log.txt
# Unit test / coverage reports
.coverage
cover
.tox
nosetests.xml
.testrepository
.stestr
# Translations
*.mo
# Mr Developer
.mr.developer.cfg
.project
.pydevproject
# Complexity
output/*.html
output/*/index.html
# Sphinx
doc/build
# pbr generates these
AUTHORS
ChangeLog
# Editors
*~
.*.swp
-3
View File
@@ -1,3 +0,0 @@
[DEFAULT]
test_path=./shade/tests/unit
top_dir=./
-210
View File
@@ -1,210 +0,0 @@
- job:
name: shade-tox-py38-tips
parent: openstack-tox-py38
description: |
Run tox python 38 unittests against master of important libs
vars:
tox_install_siblings: true
zuul_work_dir: src/opendev.org/openstack/shade
# shade in required-projects so that os-client-config and keystoneauth
# can add the job as well
required-projects:
- openstack/shade
- openstack/keystoneauth
- openstack/openstacksdk
- openstack/os-client-config
- project-template:
name: shade-tox-tips
check:
jobs:
- shade-tox-py38-tips
gate:
jobs:
- shade-tox-py38-tips
- job:
name: shade-functional-devstack-base
parent: devstack-tox-functional-consumer
description: |
Base job for shade devstack-based functional tests
post-run: playbooks/devstack/post.yaml
required-projects:
# These jobs will DTRT when shade triggers them, but we want to make
# sure stable branches of shade never get cloned by other people,
# since stable branches of shade are, well, not actually things.
- name: openstack/shade
override-checkout: master
- name: openstack/heat
- name: openstack/swift
timeout: 9000
vars:
devstack_local_conf:
post-config:
$CINDER_CONF:
DEFAULT:
osapi_max_limit: 6
devstack_services:
ceilometer-acentral: false
ceilometer-acompute: false
ceilometer-alarm-evaluator: false
ceilometer-alarm-notifier: false
ceilometer-anotification: false
ceilometer-api: false
ceilometer-collector: false
s-account: true
s-container: true
s-object: true
s-proxy: true
devstack_plugins:
heat: https://opendev.org/openstack/heat
tox_environment:
# Do we really need to set this? It's cargo culted
PYTHONUNBUFFERED: 'true'
# Is there a way we can query the localconf variable to get these
# rather than setting them explicitly?
SHADE_HAS_DESIGNATE: 0
SHADE_HAS_HEAT: 1
SHADE_HAS_MAGNUM: 0
SHADE_HAS_NEUTRON: 1
SHADE_HAS_SWIFT: 1
tox_install_siblings: false
tox_envlist: functional
zuul_work_dir: src/opendev.org/openstack/shade
- job:
name: shade-functional-devstack-legacy
parent: shade-functional-devstack-base
description: |
Run shade functional tests against a legacy devstack
# TODO(mordred): This does not seem to work
voting: false
vars:
devstack_localrc:
ENABLE_IDENTITY_V2: true
FLAT_INTERFACE: br_flat
PUBLIC_INTERFACE: br_pub
tox_environment:
SHADE_USE_KEYSTONE_V2: 1
SHADE_HAS_NEUTRON: 0
override-checkout: stable/newton
- job:
name: shade-functional-devstack
parent: shade-functional-devstack-base
description: |
Run shade functional tests against a master devstack
vars:
devstack_localrc:
Q_SERVICE_PLUGIN_CLASSES: qos
Q_ML2_PLUGIN_EXT_DRIVERS: qos,port_security
tox_environment:
SHADE_TOX_PYTHON: python3
- job:
name: shade-functional-devstack-python3
parent: shade-functional-devstack
description: |
Run shade functional tests using python3 against a master devstack
- job:
name: shade-functional-devstack-tips-python3
parent: shade-functional-devstack
description: |
Run shade functional tests with tips of library dependencies using
python3 against a master devstack.
required-projects:
- name: openstack/keystoneauth
- name: openstack/openstacksdk
- name: openstack/os-client-config
vars:
tox_install_siblings: true
tox_environment:
SHADE_TOX_PYTHON: python3
- job:
name: shade-functional-devstack-magnum
parent: shade-functional-devstack
description: |
Run shade functional tests against a master devstack with magnum
required-projects:
- openstack/magnum
- openstack/python-magnumclient
vars:
devstack_plugins:
magnum: https://opendev.org/openstack/magnum
devstack_localrc:
MAGNUM_GUEST_IMAGE_URL: https://tarballs.openstack.org/magnum/images/fedora-atomic-f23-dib.qcow2
MAGNUM_IMAGE_NAME: fedora-atomic-f23-dib
devstack_services:
s-account: false
s-container: false
s-object: false
s-proxy: false
tox_environment:
SHADE_HAS_SWIFT: 0
SHADE_HAS_MAGNUM: 1
voting: false
- job:
name: shade-ansible-functional-devstack
parent: shade-functional-devstack
description: |
Run shade ansible functional tests against a master devstack
using released version of ansible.
vars:
tox_envlist: ansible
- job:
name: shade-ansible-stable-2.5-functional-devstack
parent: shade-ansible-functional-devstack
description: |
Run shade ansible functional tests against a master devstack
using git devel branch version of ansible.
branches: ^(devel|master)$
required-projects:
- name: github.com/ansible/ansible
override-checkout: stable-2.5
- name: openstack/shade
override-checkout: master
- name: openstack/devstack
override-checkout: master
vars:
# test-matrix grabs branch from the zuul branch setting. If the job
# is triggered by ansible, that branch will be stable-2.5 which doesn't
# make sense to devstack. Override so that we run the right thing.
test_matrix_branch: master
tox_install_siblings: true
- project-template:
name: shade-functional-tips
check:
jobs:
- shade-functional-devstack-tips-python3
gate:
jobs:
- shade-functional-devstack-tips-python3
- project:
templates:
- check-requirements
- openstack-lower-constraints-jobs
- openstack-python-jobs
- openstack-python3-victoria-jobs
- publish-openstack-docs-pti
- release-notes-jobs-python3
- shade-functional-tips
- shade-tox-tips
check:
jobs:
- bifrost-integration-tinyipa:
voting: false
- shade-ansible-stable-2.5-functional-devstack:
voting: false
- shade-ansible-functional-devstack
- shade-functional-devstack-magnum
- shade-functional-devstack-python3
gate:
jobs:
- shade-ansible-functional-devstack
- shade-functional-devstack-python3
-43
View File
@@ -1,43 +0,0 @@
.. _contributing:
=====================
Contributing to shade
=====================
If you're interested in contributing to the shade project,
the following will help get you started.
Contributor License Agreement
-----------------------------
.. index::
single: license; agreement
In order to contribute to the shade project, you need to have
signed OpenStack's contributor's agreement.
.. seealso::
* https://wiki.openstack.org/wiki/How_To_Contribute
Project Hosting Details
-------------------------
Project Documentation
https://docs.openstack.org/shade/latest/
Bug tracker
https://storyboard.openstack.org/#!/project/openstack/shade
Mailing list (prefix subjects with ``[shade]`` for faster responses)
http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-discuss
Code Hosting
https://opendev.org/openstack/shade
Code Review
https://review.opendev.org/#/q/status:open+project:openstack/shade,n,z
Please read `GerritWorkflow`_ before sending your first patch for review.
.. _GerritWorkflow: https://wiki.openstack.org/wiki/GerritWorkflow
-49
View File
@@ -1,49 +0,0 @@
shade Style Commandments
========================
Read the OpenStack Style Commandments
https://docs.openstack.org/hacking/latest/
Indentation
-----------
PEP-8 allows for 'visual' indentation. Do not use it. Visual indentation looks
like this:
.. code-block:: python
return_value = self.some_method(arg1, arg1,
arg3, arg4)
Visual indentation makes refactoring the code base unneccesarily hard.
Instead of visual indentation, use this:
.. code-block:: python
return_value = self.some_method(
arg1, arg1, arg3, arg4)
That way, if some_method ever needs to be renamed, the only line that needs
to be touched is the line with some_method. Additionaly, if you need to
line break at the top of a block, please indent the continuation line
an additional 4 spaces, like this:
.. code-block:: python
for val in self.some_method(
arg1, arg1, arg3, arg4):
self.do_something_awesome()
Neither of these are 'mandated' by PEP-8. However, they are prevailing styles
within this code base.
Unit Tests
----------
Unit tests should be virtually instant. If a unit test takes more than 1 second
to run, it is a bad unit test. Honestly, 1 second is too slow.
All unit test classes should subclass `shade.tests.unit.base.BaseTestCase`. The
base TestCase class takes care of properly creating `OpenStackCloud` objects
in a way that protects against local environment.
-175
View File
@@ -1,175 +0,0 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
-6
View File
@@ -1,6 +0,0 @@
include AUTHORS
include ChangeLog
exclude .gitignore
exclude .gitreview
global-exclude *.pyc
+7 -92
View File
@@ -1,92 +1,7 @@
Introduction
============
.. warning::
shade has been superceded by `openstacksdk`_ and no longer takes new
features. The existing code will continue to be maintained indefinitely
for bugfixes as necessary, but improvements will be deferred to
`openstacksdk`_. Please update your applications to use `openstacksdk`_
directly.
shade is a simple client library for interacting with OpenStack clouds. The
key word here is *simple*. Clouds can do many many many things - but there are
probably only about 10 of them that most people care about with any
regularity. If you want to do complicated things, you should probably use
the lower level client libraries - or even the REST API directly. However,
if what you want is to be able to write an application that talks to clouds
no matter what crazy choices the deployer has made in an attempt to be
more hipster than their self-entitled narcissist peers, then shade is for you.
shade started its life as some code inside of ansible. ansible has 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 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.
.. _usage_example:
Example
=======
Sometimes an example is nice.
#. Create a ``clouds.yml`` file::
clouds:
mordred:
region_name: RegionOne
auth:
username: 'mordred'
password: XXXXXXX
project_name: 'shade'
auth_url: 'https://montytaylor-sjc.openstack.blueboxgrid.com:5001/v2.0'
Please note: *os-client-config* will look for a file called ``clouds.yaml``
in the following locations:
* Current Directory
* ``~/.config/openstack``
* ``/etc/openstack``
More information at https://pypi.org/project/os-client-config
#. Create a server with *shade*, configured with the ``clouds.yml`` file::
import shade
# Initialize and turn on debug logging
shade.simple_logging(debug=True)
# Initialize cloud
# Cloud configs are read with os-client-config
cloud = shade.openstack_cloud(cloud='mordred')
# Upload an image to the cloud
image = cloud.create_image(
'ubuntu-trusty', filename='ubuntu-trusty.qcow2', wait=True)
# Find a flavor with at least 512M of RAM
flavor = cloud.get_flavor_by_ram(512)
# 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)
Links
=====
* `Issue Tracker <https://storyboard.openstack.org/#!/project/760>`_
* `Code Review <https://review.openstack.org/#/q/status:open+project:openstack/shade,n,z>`_
* `Documentation <https://docs.openstack.org/shade/latest/>`_
* `Source <https://opendev.org/openstack/shade>`_
* `PyPI <https://pypi.org/project/shade/>`_
* `Mailing list <http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack>`_
* `Release notes <https://docs.openstack.org/releasenotes/shade>`_
* `Contributing <https://docs.openstack.org/shade/latest/contributor/index.html>`_
.. _openstacksdk: https://docs.openstack.org/openstacksdk/latest/user/
This project is no longer maintained.
The contents of this repository are still available in the Git
source code management system. To see the contents of this
repository before it reached its end of life, please check out the
previous commit with "git checkout HEAD^1".
For any further questions, please email
openstack-discuss@lists.openstack.org.
-8
View File
@@ -1,8 +0,0 @@
# This is a cross-platform list tracking distribution packages needed by tests;
# see http://docs.openstack.org/infra/bindep/ for additional information.
build-essential [platform:dpkg]
python-dev [platform:dpkg]
python-devel [platform:rpm]
libffi-dev [platform:dpkg]
libffi-devel [platform:rpm]
-54
View File
@@ -1,54 +0,0 @@
# Install and configure **shade** library in devstack
#
# To enable shade in devstack add an entry to local.conf that looks like
#
# [[local|localrc]]
# enable_plugin shade https://opendev.org/openstack/shade
function preinstall_shade {
:
}
function install_shade {
if use_library_from_git "shade"; then
# don't clone, it'll be done by the plugin install
setup_dev_lib "shade"
else
pip_install "shade"
fi
}
function configure_shade {
:
}
function initialize_shade {
:
}
function unstack_shade {
:
}
function clean_shade {
:
}
# This is the main for plugin.sh
if [[ "$1" == "stack" && "$2" == "pre-install" ]]; then
preinstall_shade
elif [[ "$1" == "stack" && "$2" == "install" ]]; then
install_shade
elif [[ "$1" == "stack" && "$2" == "post-config" ]]; then
configure_shade
elif [[ "$1" == "stack" && "$2" == "extra" ]]; then
initialize_shade
fi
if [[ "$1" == "unstack" ]]; then
unstack_shade
fi
if [[ "$1" == "clean" ]]; then
clean_shade
fi
-6
View File
@@ -1,6 +0,0 @@
# The order of packages is significant, because pip processes them in the order
# of appearance. Changing the order has an impact on the overall integration
# process, which may cause wedges in the gate later.
sphinx>=2.0.0,!=2.1.0 # BSD
openstackdocstheme>=2.2.1 # Apache-2.0
reno>=3.1.0 # Apache-2.0
-46
View File
@@ -1,46 +0,0 @@
import os
import sys
sys.path.insert(0, os.path.abspath('../..'))
extensions = [
'sphinx.ext.autodoc',
'openstackdocstheme',
'reno.sphinxext'
]
# openstackdocstheme options
openstackdocs_repo_name = 'openstack/shade'
openstackdocs_auto_name = False
openstackdocs_use_storyboard = True
html_theme = 'openstackdocs'
# The suffix of source filenames.
source_suffix = '.rst'
# The master toctree document.
master_doc = 'index'
# General information about the project.
project = u'shade'
copyright = u'2014 Hewlett-Packard Development Company, L.P.'
# If true, '()' will be appended to :func: etc. cross-reference text.
add_function_parentheses = True
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
add_module_names = True
# Output file base name for HTML help builder.
htmlhelp_basename = '%sdoc' % project
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, documentclass
# [howto/manual]).
latex_documents = [
('index',
'%s.tex' % project,
u'%s Documentation' % project,
u'Monty Taylor', 'manual'),
]
-116
View File
@@ -1,116 +0,0 @@
********************************
Shade 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 shade API at least *attempted* to display some form of consistency.
Thus, these coding standards/guidelines were developed. Note that not
all of shade 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 Shade developers to follow.
Release Notes
=============
Shade uses `reno <https://docs.openstack.org/reno/latest/>`_ 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
other significant changes to the code base that we should draw attention
to for the user base.
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.
API Methods
===========
- 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()`.
- 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.
- Deleting a resource should return True if the delete succeeded, or False
if the resource was not found.
Exceptions
==========
All underlying client exceptions must be captured and converted to an
`OpenStackCloudException` or one of its derivatives.
REST Calls
============
All interactions with the cloud should be done with direct REST using
the appropriate `keystoneauth1.adapter.Adapter`. See Glance and Swift
calls for examples.
Returned Resources
==================
Complex objects returned to the caller must be a `munch.Munch` type. The
`shade._adapter.Adapter` class makes resources into `munch.Munch`.
All objects should be normalized. It is shade's purpose in life to make
OpenStack consistent for end users, and this means not trusting the clouds
to return consistent objects. There should be a normalize function in
`shade/_normalize.py` that is applied to objects before returning them to
the user. See :doc:`../user/model` for further details on object model
requirements.
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 shade. For instance, nothing in shade exposes the legacy OpenStack
concept of "tenant" to a user, but instead uses "project" even if the
cloud uses tenant.
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
Neutron or Nova, code it to be handled by either.
- 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.
Tests
=====
- New API methods *must* have unit tests!
- New unit tests should only mock at the REST layer using `requests_mock`.
Any mocking of shade itself or of legacy client libraries should be
considered legacy and to be avoided.
- Functional tests should be added, when possible.
- In functional tests, always use unique names (for resources that have this
attribute) and use it for clean up (see next point).
- In functional tests, always define cleanup functions to delete data added
by your test, should something go wrong. Data removal should be wrapped in
a try except block and try to delete as many entries added by the test as
possible.
-1
View File
@@ -1 +0,0 @@
.. include:: ../../../CONTRIBUTING.rst
-9
View File
@@ -1,9 +0,0 @@
=========================
Shade Contributor Guide
=========================
.. toctree::
:maxdepth: 2
contributing
coding
-31
View File
@@ -1,31 +0,0 @@
.. shade documentation master file, created by
sphinx-quickstart on Tue Jul 9 22:26:36 2013.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
=================================
Welcome to shade's documentation!
=================================
Contents:
.. toctree::
:maxdepth: 2
install/index
user/index
contributor/index
.. releasenotes contains a lot of sections, toctree with maxdepth 1 is used.
.. toctree::
:maxdepth: 1
releasenotes/index
.. include:: ../../README.rst
Indices and tables
==================
* :ref:`genindex`
* :ref:`search`
-12
View File
@@ -1,12 +0,0 @@
============
Installation
============
At the command line::
$ pip install shade
Or, if you have virtualenv wrapper installed::
$ mkvirtualenv shade
$ pip install shade
-5
View File
@@ -1,5 +0,0 @@
=============
Release Notes
=============
.. release-notes::
@@ -1,13 +0,0 @@
import shade
# Initialize and turn on debug logging
shade.simple_logging(debug=True)
for cloud_name, region_name in [
('my-vexxhost', 'ca-ymq-1'),
('my-citycloud', 'Buf1'),
('my-internap', 'ams01')]:
# Initialize cloud
cloud = shade.openstack_cloud(cloud=cloud_name, region_name=region_name)
for server in cloud.search_servers('my-server'):
cloud.delete_server(server, wait=True, delete_ips=True)
@@ -1,22 +0,0 @@
import shade
# Initialize and turn on debug logging
shade.simple_logging(debug=True)
for cloud_name, region_name, image, flavor_id in [
('my-vexxhost', 'ca-ymq-1', 'Ubuntu 16.04.1 LTS [2017-03-03]',
'5cf64088-893b-46b5-9bb1-ee020277635d'),
('my-citycloud', 'Buf1', 'Ubuntu 16.04 Xenial Xerus',
'0dab10b5-42a2-438e-be7b-505741a7ffcc'),
('my-internap', 'ams01', 'Ubuntu 16.04 LTS (Xenial Xerus)',
'A1.4')]:
# Initialize cloud
cloud = shade.openstack_cloud(cloud=cloud_name, region_name=region_name)
# Boot a server, wait for it to boot, and then do whatever is needed
# to get a public ip for it.
server = cloud.create_server(
'my-server', image=image, flavor=dict(id=flavor_id),
wait=True, auto_ip=True)
# Delete it - this is a demo
cloud.delete_server(server, wait=True, delete_ips=True)
@@ -1,25 +0,0 @@
import shade
# Initialize and turn on debug logging
shade.simple_logging(debug=True)
for cloud_name, region_name, image, flavor in [
('my-vexxhost', 'ca-ymq-1',
'Ubuntu 16.04.1 LTS [2017-03-03]', 'v1-standard-4'),
('my-citycloud', 'Buf1',
'Ubuntu 16.04 Xenial Xerus', '4C-4GB-100GB'),
('my-internap', 'ams01',
'Ubuntu 16.04 LTS (Xenial Xerus)', 'A1.4')]:
# Initialize cloud
cloud = shade.openstack_cloud(cloud=cloud_name, region_name=region_name)
cloud.delete_server('my-server', wait=True, delete_ips=True)
# Boot a server, wait for it to boot, and then do whatever is needed
# to get a public ip for it.
server = cloud.create_server(
'my-server', image=image, flavor=flavor, wait=True, auto_ip=True)
print(server.name)
print(server['name'])
cloud.pprint(server)
# Delete it - this is a demo
cloud.delete_server(server, wait=True, delete_ips=True)
@@ -1,6 +0,0 @@
import shade
shade.simple_logging(debug=True)
cloud = shade.openstack_cloud(
cloud='my-vexxhost', region_name='ca-ymq-1')
cloud.get_image('Ubuntu 16.04.1 LTS [2017-03-03]')
@@ -1,7 +0,0 @@
import shade
shade.simple_logging()
cloud = shade.openstack_cloud(cloud='fuga', region_name='cystack')
cloud.pprint([
image for image in cloud.list_images()
if 'ubuntu' in image.name.lower()])
@@ -1,6 +0,0 @@
import shade
shade.simple_logging(http_debug=True)
cloud = shade.openstack_cloud(
cloud='my-vexxhost', region_name='ca-ymq-1')
cloud.get_image('Ubuntu 16.04.1 LTS [2017-03-03]')
@@ -1,7 +0,0 @@
import shade
shade.simple_logging(debug=True)
cloud = shade.openstack_cloud(cloud='ovh', region_name='SBG1')
image = cloud.get_image('Ubuntu 16.10')
print(image.name)
print(image['name'])
@@ -1,7 +0,0 @@
import shade
shade.simple_logging()
cloud = shade.openstack_cloud(cloud='fuga', region_name='cystack')
image = cloud.get_image(
'Ubuntu 16.04 LTS - Xenial Xerus - 64-bit - Fuga Cloud Based Image')
cloud.pprint(image)
@@ -1,23 +0,0 @@
import shade
shade.simple_logging(debug=True)
cloud = shade.openstack_cloud(cloud='my-citycloud', region_name='Buf1')
try:
server = cloud.create_server(
'my-server', image='Ubuntu 16.04 Xenial Xerus',
flavor=dict(id='0dab10b5-42a2-438e-be7b-505741a7ffcc'),
wait=True, auto_ip=True)
print("\n\nFull Server\n\n")
cloud.pprint(server)
print("\n\nTurn Detailed Off\n\n")
cloud.pprint(cloud.get_server('my-server', detailed=False))
print("\n\nBare Server\n\n")
cloud.pprint(cloud.get_server('my-server', bare=True))
finally:
# Delete it - this is a demo
cloud.delete_server(server, wait=True, delete_ips=True)
@@ -1,5 +0,0 @@
import shade
shade.simple_logging(debug=True)
cloud = shade.openstack_cloud(cloud='rax', region_name='DFW')
print(cloud.has_service('network'))
@@ -1,6 +0,0 @@
import shade
shade.simple_logging(debug=True)
cloud = shade.openstack_cloud(cloud='kiss', region_name='region1')
print(cloud.has_service('network'))
print(cloud.has_service('container-orchestration'))
-8
View File
@@ -1,8 +0,0 @@
import shade
shade.simple_logging()
cloud = shade.openstack_cloud(
cloud='fuga', region_name='cystack', strict=True)
image = cloud.get_image(
'Ubuntu 16.04 LTS - Xenial Xerus - 64-bit - Fuga Cloud Based Image')
cloud.pprint(image)
@@ -1,10 +0,0 @@
import shade
shade.simple_logging(debug=True)
cloud = shade.openstack_cloud(cloud='ovh', region_name='SBG1')
cloud.create_object(
container='my-container', name='my-object',
filename='/home/mordred/briarcliff.sh3d',
segment_size=1000000)
cloud.delete_object('my-container', 'my-object')
cloud.delete_container('my-container')
-10
View File
@@ -1,10 +0,0 @@
import shade
shade.simple_logging(debug=True)
cloud = shade.openstack_cloud(cloud='ovh', region_name='SBG1')
cloud.create_object(
container='my-container', name='my-object',
filename='/home/mordred/briarcliff.sh3d',
segment_size=1000000)
cloud.delete_object('my-container', 'my-object')
cloud.delete_container('my-container')
-6
View File
@@ -1,6 +0,0 @@
import shade
shade.simple_logging(http_debug=True)
cloud = shade.openstack_cloud(
cloud='datacentred', app_name='AmazingApp', app_version='1.0')
cloud.list_networks()
-19
View File
@@ -1,19 +0,0 @@
==================
Shade User Guide
==================
.. toctree::
:maxdepth: 2
usage
logging
model
microversions
Presentations
=============
.. toctree::
:maxdepth: 1
multi-cloud-demo
-93
View File
@@ -1,93 +0,0 @@
=======
Logging
=======
`shade` uses `Python Logging`_. As `shade` is a library, it does not
configure logging handlers automatically, expecting instead for that to be
the purview of the consuming application.
Simple Usage
------------
For consumers who just want to get a basic logging setup without thinking
about it too deeply, there is a helper method. If used, it should be called
before any other `shade` functionality.
.. code-block:: python
import shade
shade.simple_logging()
`shade.simple_logging` takes two optional boolean arguments:
debug
Turns on debug logging.
http_debug
Turns on debug logging as well as debug logging of the underlying HTTP calls.
`shade.simple_logging` also sets up a few other loggers and squelches some
warnings or log messages that are otherwise uninteresting or unactionable by
a `shade` user.
Advanced Usage
--------------
`shade` logs to a set of different named loggers.
Most of the logging is set up to log to the root `shade` logger. There are
additional sub-loggers that are used at times, primarily so that a user can
decide to turn on or off a specific type of logging. They are listed below.
shade.task_manager
`shade` uses a Task Manager to perform remote calls. The `shade.task_manager`
logger emits messages at the start and end of each Task announging what
it is going to run and then what it ran and how long it took. Logging
`shade.task_manager` is a good way to get a trace of external actions shade
is taking without full `HTTP Tracing`_.
shade.request_ids
The `shade.request_ids` logger emits a log line at the end of each HTTP
interaction with the OpenStack Request ID associated with the interaction.
This can be be useful for tracking action taken on the server-side if one
does not want `HTTP Tracing`_.
shade.iterate_timeout
When `shade` needs to poll a resource, it does so in a loop that waits
between iterations and ultimately timesout. The `shade.iterate_timeout`
logger emits messages for each iteration indicating it is waiting and for
how long. These can be useful to see for long running tasks so that one
can know things are not stuck, but can also be noisy.
shade.http
`shade` will sometimes log additional information about HTTP interactions
to the `shade.http` logger. This can be verbose, as it sometimes logs
entire response bodies.
shade.fnmatch
`shade` will try to use `fnmatch`_ on given `name_or_id` arguments. It's a
best effort attempt, so pattern misses are logged to `shade.fnmatch`. A user
may not be intending to use an fnmatch pattern - such as if they are trying
to find an image named ``Fedora 24 [official]``, so these messages are
logged separately.
.. _fnmatch: https://pymotw.com/2/fnmatch/
HTTP Tracing
------------
HTTP Interactions are handled by `keystoneauth`. If you want to enable HTTP
tracing while using `shade` and are not using `shade.simple_logging`,
set the log level of the `keystoneauth` logger to `DEBUG`.
Python Logging
--------------
Python logging is a standard feature of Python and is documented fully in the
Python Documentation, which varies by version of Python.
For more information on Python Logging for Python v2, see
https://docs.python.org/2/library/logging.html.
For more information on Python Logging for Python v3, see
https://docs.python.org/3/library/logging.html.
-75
View File
@@ -1,75 +0,0 @@
=============
Microversions
=============
As shade rolls out support for consuming microversions, it will do so on a
call by call basis as needed. Just like with major versions, shade should have
logic to handle each microversion for a given REST call it makes, with the
following rules in mind:
* If an activity shade performs can be done differently or more efficiently
with a new microversion, the support should be added to shade.
* shade should always attempt to use the latest microversion it is aware of
for a given call, unless a microversion removes important data.
* Microversion selection should under no circumstances be exposed to the user,
except in the case of missing feature error messages.
* If a feature is only exposed for a given microversion and cannot be simulated
for older clouds without that microversion, it is ok to add it to shade but
a clear error message should be given to the user that the given feature is
not available on their cloud. (A message such as "This cloud only supports
a maximum microversion of XXX for service YYY and this feature only exists
on clouds with microversion ZZZ. Please contact your cloud provider for
information about when this feature might be available")
* When adding a feature to shade that only exists behind a new microversion,
every effort should be made to figure out how to provide the same
functionality if at all possible, even if doing so is inefficient. If an
inefficient workaround is employed, a warning should be provided to the
user. (the user's workaround to skip the inefficient behavior would be to
stop using that shade API call)
* If shade is aware of logic for more than one microversion, it should always
attempt to use the latest version available for the service for that call.
* Objects returned from shade should always go through normalization and thus
should always conform to shade's documented data model and should never look
different to the shade user regardless of the microversion used for the REST
call.
* If a microversion adds new fields to an object, those fields should be
added to shade's data model contract for that object and the data should
either be filled in by performing additional REST calls if the data is
available that way, or the field should have a default value of None which
the user can be expected to test for when attempting to use the new value.
* If a microversion removes fields from an object that are part of shade's
existing data model contract, care should be taken to not use the new
microversion for that call unless forced to by lack of availablity of the
old microversion on the cloud in question. In the case where an old
microversion is no longer available, care must be taken to either find the
data from another source and fill it in, or to put a value of None into the
field and document for the user that on some clouds the value may not exist.
* If a microversion removes a field and the outcome is particularly intractable
and impossible to work around without fundamentally breaking shade's users,
an issue should be raised with the service team in question. Hopefully a
resolution can be found during the period while clouds still have the old
microversion.
* As new calls or objects are added to shade, it is important to check in with
the service team in question on the expected stability of the object. If
there are known changes expected in the future, even if they may be a few
years off, shade should take care to not add committments to its data model
for those fields/features. It is ok for shade to not have something.
..note::
shade does not currently have any sort of "experimental" opt-in API that
would allow a shade to expose things to a user that may not be supportable
under shade's normal compatibility contract. If a conflict arises in the
future where there is a strong desire for a feature but also a lack of
certainty about its stability over time, an experimental API may want to
be explored ... but concrete use cases should arise before such a thing
is started.
-533
View File
@@ -1,533 +0,0 @@
==========
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.
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.
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.
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.
Location
--------
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,
it should be considered correct.
Some resources do not carry ownership information with them. For those, the
project information will be filled in from the project the user currently
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=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,
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())
-811
View File
@@ -1,811 +0,0 @@
================
Multi-Cloud Demo
================
This document contains a presentation in `presentty`_ format. If you want to
walk through it like a presentation, install `presentty` and run:
.. code:: bash
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.
.. _presentty: https://pypi.org/project/presentty
Using Multiple OpenStack Clouds Easily with Shade
=================================================
Who am I?
=========
Monty Taylor
* OpenStack Infra Core
* irc: mordred
* twitter: @e_monty
What are we going to talk about?
================================
`shade`
* a task and end-user oriented Python library
* abstracts deployment differences
* designed for multi-cloud
* simple to use
* massive scale
* optional advanced features to handle 20k servers a day
* Initial logic/design extracted from nodepool
* Librified to re-use in Ansible
shade is Free Software
======================
* https://opendev.org/openstack/shade
* openstack-discuss@lists.openstack.org
* #openstack-shade on freenode
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!
Complete Example
================
.. code:: python
import shade
# Initialize and turn on debug logging
shade.simple_logging(debug=True)
for cloud_name, region_name in [
('my-vexxhost', 'ca-ymq-1'),
('my-citycloud', 'Buf1'),
('my-internap', 'ams01')]:
# Initialize cloud
cloud = shade.openstack_cloud(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)
# Find a flavor with at least 512M of RAM
flavor = cloud.get_flavor_by_ram(512)
# 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)
Let's Take a Few Steps Back
===========================
Multi-cloud is easy, but you need to know a few things.
* Terminology
* Config
* Shade API
Cloud Terminology
=================
Let's define a few terms, so that we can use them with ease:
* `cloud` - logically related collection of services
* `region` - completely independent subset of a given cloud
* `patron` - human who has an account
* `user` - account on a cloud
* `project` - logical collection of cloud resources
* `domain` - collection of users and projects
Cloud Terminology Relationships
===============================
* A `cloud` has one or more `regions`
* A `patron` has one or more `users`
* A `patron` has one or more `projects`
* A `cloud` has one or more `domains`
* In a `cloud` with one `domain` it is named "default"
* Each `patron` may have their own `domain`
* Each `user` is in one `domain`
* Each `project` is in one `domain`
* 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.
* A `cloud` has a `service catalog`
* The `service catalog` is returned in the `token`
* The `service catalog` lists `endpoint` for each `service` in each `region`
* A `region` is completely autonomous
Users, Projects and Domains
===========================
In clouds with multiple domains, project and user names are
only unique within a region.
* Names require `domain` information for uniqueness. IDs do not.
* Providing `domain` information when not needed is fine.
* `project_name` requires `project_domain_name` or `project_domain_id`
* `project_id` does not
* `username` requires `user_domain_name` or `user_domain_id`
* `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:
* Configure authentication per `cloud`
* 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`.
`clouds.yaml` can be in your homedir: `~/.config/openstack/clouds.yaml`
or system-wide: `/etc/openstack/clouds.yaml`.
Information in your homedir, if it exists, takes precedence.
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.
* Linux: `~/.config/openstack`
* OSX: `~/Library/Application Support/openstack`
* Windows: `C:\\Users\\USERNAME\\AppData\\Local\\OpenStack\\openstack`
`SITE_CONFIG_DIR` is different on Linux, OSX and Windows.
* Linux: `/etc/openstack`
* OSX: `/Library/Application Support/openstack`
* Windows: `C:\\ProgramData\\OpenStack\\openstack`
Config Terminology
==================
For multi-cloud, think of two types:
* `profile` - Facts about the `cloud` that are true for everyone
* `cloud` - Information specific to a given `user`
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
* `OS_CLOUD` and `OS_REGION_NAME` are default values for
`cloud` and `region_name`
TOO MUCH TALKING - NOT ENOUGH CODE
==================================
basic clouds.yaml for the example code
======================================
Simple example of a clouds.yaml
* Config for a named `cloud` "my-citycloud"
* Reference a well-known "named" profile: `citycloud`
* `os-client-config` has a built-in list of profiles at
https://docs.openstack.org/os-client-config/latest/user/vendor-support.html
* Vendor profiles contain various advanced config
* `cloud` name can match `profile` name (using different names for clarity)
.. code:: yaml
clouds:
my-citycloud:
profile: citycloud
auth:
username: mordred
project_id: 65222a4d09ea4c68934fa1028c77f394
user_domain_id: d0919bd5e8d74e49adf0e145807ffc38
project_domain_id: d0919bd5e8d74e49adf0e145807ffc38
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`
* Optional - I actually keep mine in my `clouds.yaml`
.. code:: yaml
clouds:
my-citycloud:
auth:
password: XXXXXXXX
more clouds.yaml
================
More information can be provided.
* Use v3 of the `identity` API - even if others are present
* Use `https://image-ca-ymq-1.vexxhost.net/v2` for `image` API
instead of what's in the catalog
.. code:: yaml
my-vexxhost:
identity_api_version: 3
image_endpoint_override: https://image-ca-ymq-1.vexxhost.net/v2
profile: vexxhost
auth:
user_domain_id: default
project_domain_id: default
project_name: d8af8a8f-a573-48e6-898a-af333b970a2d
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
* Each one are labeled here so choices can be made
* Any of the settings can be specific to a `region` if needed
* `region` settings override `cloud` settings
* `cloud` does not support `floating-ips`
.. code:: yaml
my-internap:
auth:
auth_url: https://identity.api.cloud.iweb.com
username: api-55f9a00fb2619
project_name: inap-17037
identity_api_version: 3
floating_ip_source: None
regions:
- name: ams01
values:
networks:
- name: inap-17037-WAN1654
routes_externally: true
default_interface: true
- name: inap-17037-LAN3631
routes_externally: false
Complete Example Again
======================
.. code:: python
import shade
# Initialize and turn on debug logging
shade.simple_logging(debug=True)
for cloud_name, region_name in [
('my-vexxhost', 'ca-ymq-1'),
('my-citycloud', 'Buf1'),
('my-internap', 'ams01')]:
# Initialize cloud
cloud = shade.openstack_cloud(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)
# Find a flavor with at least 512M of RAM
flavor = cloud.get_flavor_by_ram(512)
# 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)
Step By Step
============
Import the library
==================
.. code:: python
import shade
Logging
=======
* `shade` uses standard python logging
* Special `shade.request_ids` logger for API request IDs
* `simple_logging` does easy defaults
* Squelches some meaningless warnings
* `debug`
* Logs shade loggers at debug level
* Includes `shade.request_ids` debug logging
* `http_debug` Implies `debug`, turns on HTTP tracing
.. code:: python
# Initialize and turn on debug logging
shade.simple_logging(debug=True)
Example with Debug Logging
==========================
* doc/source/examples/debug-logging.py
.. code:: python
import shade
shade.simple_logging(debug=True)
cloud = shade.openstack_cloud(
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
.. code:: python
import shade
shade.simple_logging(http_debug=True)
cloud = shade.openstack_cloud(
cloud='my-vexxhost', region_name='ca-ymq-1')
cloud.get_image('Ubuntu 16.04.1 LTS [2017-03-03]')
Cloud Regions
=============
* `cloud` constructor needs `cloud` and `region_name`
* `shade.openstack_cloud` is a helper factory function
.. code:: python
for cloud_name, region_name in [
('my-vexxhost', 'ca-ymq-1'),
('my-citycloud', 'Buf1'),
('my-internap', 'ams01')]:
# Initialize cloud
cloud = shade.openstack_cloud(cloud=cloud_name, region_name=region_name)
Upload an Image
===============
* Picks the correct upload mechanism
* **SUGGESTION** Always upload your own base images
.. code:: python
# Upload an image to the cloud
image = cloud.create_image(
'devuan-jessie', filename='devuan-jessie.qcow2', wait=True)
Always Upload an Image
======================
Ok. You don't have to. But, for multi-cloud...
* Images with same content are named different on different clouds
* Images with same name on different clouds can have different content
* Upload your own to all clouds, both problems go away
* 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
* `get_flavor_by_ram` finds the smallest matching flavor
.. code:: python
# Find a flavor with at least 512M of RAM
flavor = cloud.get_flavor_by_ram(512)
Create a server
===============
* my-vexxhost
* Boot server
* Wait for `status==ACTIVE`
* my-internap
* Boot server on network `inap-17037-WAN1654`
* Wait for `status==ACTIVE`
* my-citycloud
* Boot server
* Wait for `status==ACTIVE`
* Find the `port` for the `fixed_ip` for `server`
* Create `floating-ip` on that `port`
* Wait for `floating-ip` to attach
.. code:: python
# 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)
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
.. code:: python
import shade
# Initialize and turn on debug logging
shade.simple_logging(debug=True)
for cloud_name, region_name, image, flavor in [
('my-vexxhost', 'ca-ymq-1',
'Ubuntu 16.04.1 LTS [2017-03-03]', 'v1-standard-4'),
('my-citycloud', 'Buf1',
'Ubuntu 16.04 Xenial Xerus', '4C-4GB-100GB'),
('my-internap', 'ams01',
'Ubuntu 16.04 LTS (Xenial Xerus)', 'A1.4')]:
# Initialize cloud
cloud = shade.openstack_cloud(cloud=cloud_name, region_name=region_name)
# Boot a server, wait for it to boot, and then do whatever is needed
# to get a public ip for it.
server = cloud.create_server(
'my-server', image=image, flavor=flavor, wait=True, auto_ip=True)
print(server.name)
print(server['name'])
cloud.pprint(server)
# 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
.. code:: python
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
.. code:: python
import shade
# Initialize and turn on debug logging
shade.simple_logging(debug=True)
for cloud_name, region_name, image, flavor_id in [
('my-vexxhost', 'ca-ymq-1', 'Ubuntu 16.04.1 LTS [2017-03-03]',
'5cf64088-893b-46b5-9bb1-ee020277635d'),
('my-citycloud', 'Buf1', 'Ubuntu 16.04 Xenial Xerus',
'0dab10b5-42a2-438e-be7b-505741a7ffcc'),
('my-internap', 'ams01', 'Ubuntu 16.04 LTS (Xenial Xerus)',
'A1.4')]:
# Initialize cloud
cloud = shade.openstack_cloud(cloud=cloud_name, region_name=region_name)
# Boot a server, wait for it to boot, and then do whatever is needed
# to get a public ip for it.
server = cloud.create_server(
'my-server', image=image, flavor=dict(id=flavor_id),
wait=True, auto_ip=True)
# Delete it - this is a demo
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
.. code:: python
import shade
shade.simple_logging(debug=True)
cloud = shade.openstack_cloud(cloud='zetta', region_name='no-osl1')
image = cloud.get_image('Ubuntu 14.04 (AMD64) [Local Storage]')
print(image.name)
print(image['name'])
API Organized by Logical Resource
=================================
* list_servers
* search_servers
* get_server
* create_server
* delete_server
* update_server
For other things, it's still {verb}_{noun}
* attach_volume
* wait_for_server
* add_auto_ip
Cleanup Script
==============
* Sometimes my examples had bugs
* doc/source/examples/cleanup-servers.py
.. code:: python
import shade
# Initialize and turn on debug logging
shade.simple_logging(debug=True)
for cloud_name, region_name in [
('my-vexxhost', 'ca-ymq-1'),
('my-citycloud', 'Buf1'),
('my-internap', 'ams01')]:
# Initialize cloud
cloud = shade.openstack_cloud(cloud=cloud_name, region_name=region_name)
for server in cloud.search_servers('my-server'):
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
.. code:: python
import shade
shade.simple_logging()
cloud = shade.openstack_cloud(cloud='fuga', region_name='cystack')
image = cloud.get_image(
'Ubuntu 16.04 LTS - Xenial Xerus - 64-bit - Fuga Cloud Based Image')
cloud.pprint(image)
Strict Normalized Results
=========================
* Return only the declared model
* doc/source/examples/strict-mode.py
.. code:: python
import shade
shade.simple_logging()
cloud = shade.openstack_cloud(
cloud='fuga', region_name='cystack', strict=True)
image = cloud.get_image(
'Ubuntu 16.04 LTS - Xenial Xerus - 64-bit - Fuga Cloud Based Image')
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
.. code:: python
import shade
shade.simple_logging()
cloud = shade.openstack_cloud(cloud='fuga', region_name='cystack')
cloud.pprint([
image for image in cloud.list_images()
if 'ubuntu' in image.name.lower()])
Added / Modified Information
============================
* Servers need more extra help
* Fetch addresses dict from neutron
* Figure out which IPs are good
* `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
.. code:: python
import shade
shade.simple_logging(debug=True)
cloud = shade.openstack_cloud(cloud='my-citycloud', region_name='Buf1')
try:
server = cloud.create_server(
'my-server', image='Ubuntu 16.04 Xenial Xerus',
flavor=dict(id='0dab10b5-42a2-438e-be7b-505741a7ffcc'),
wait=True, auto_ip=True)
print("\n\nFull Server\n\n")
cloud.pprint(server)
print("\n\nTurn Detailed Off\n\n")
cloud.pprint(cloud.get_server('my-server', detailed=False))
print("\n\nBare Server\n\n")
cloud.pprint(cloud.get_server('my-server', bare=True))
finally:
# Delete it - this is a demo
cloud.delete_server(server, wait=True, delete_ips=True)
Exceptions
==========
* All shade exceptions are subclasses of `OpenStackCloudException`
* Direct REST calls throw `OpenStackCloudHTTPError`
* `OpenStackCloudHTTPError` subclasses `OpenStackCloudException`
and `requests.exceptions.HTTPError`
* `OpenStackCloudURINotFound` for 404
* `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
.. code:: python
import shade
shade.simple_logging(http_debug=True)
cloud = shade.openstack_cloud(
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
* multi-threaded
* doc/source/examples/upload-object.py
.. code:: python
import shade
shade.simple_logging(debug=True)
cloud = shade.openstack_cloud(cloud='ovh', region_name='SBG1')
cloud.create_object(
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
.. code:: python
import shade
shade.simple_logging(debug=True)
cloud = shade.openstack_cloud(cloud='ovh', region_name='SBG1')
cloud.create_object(
container='my-container', name='my-object',
filename='/home/mordred/briarcliff.sh3d',
segment_size=1000000)
cloud.delete_object('my-container', 'my-object')
cloud.delete_container('my-container')
Service Conditionals
====================
.. code:: python
import shade
shade.simple_logging(debug=True)
cloud = shade.openstack_cloud(cloud='kiss', region_name='region1')
print(cloud.has_service('network'))
print(cloud.has_service('container-orchestration'))
Service Conditional Overrides
=============================
* Sometimes clouds are weird and figuring that out won't work
.. code:: python
import shade
shade.simple_logging(debug=True)
cloud = shade.openstack_cloud(cloud='rax', region_name='DFW')
print(cloud.has_service('network'))
.. code:: yaml
clouds:
rax:
profile: rackspace
auth:
username: mordred
project_id: 245018
# 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)
-21
View File
@@ -1,21 +0,0 @@
=====
Usage
=====
To use shade in a project:
.. code-block:: python
import shade
For a simple example, see :ref:`usage_example`.
.. note::
API methods that return a description of an OpenStack resource (e.g.,
server instance, image, volume, etc.) do so using a `munch.Munch` object
from the `Munch library <https://github.com/Infinidat/munch>`_. `Munch`
objects can be accessed using either dictionary or object notation
(e.g., ``server.id``, ``image.name`` and ``server['id']``, ``image['name']``)
.. autoclass:: shade.OpenStackCloud
:members:
-14
View File
@@ -1,14 +0,0 @@
neutron router-gateway-clear router1
neutron router-interface-delete router1
for subnet in private-subnet ipv6-private-subnet ; do
neutron router-interface-delete router1 $subnet
subnet_id=$(neutron subnet-show $subnet -f value -c id)
neutron port-list | grep $subnet_id | awk '{print $2}' | xargs -n1 neutron port-delete
neutron subnet-delete $subnet
done
neutron router-delete router1
neutron net-delete private
# Make the public network directly consumable
neutron subnet-update public-subnet --enable-dhcp=True
neutron net-update public --shared=True
-31
View File
@@ -1,31 +0,0 @@
#!/bin/bash
# Copyright (c) 2017 Red Hat, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
for lib in \
python-keystoneclient \
os-client-config \
keystoneauth
do
egg=$(echo $lib | tr '-' '_' | sed 's/python-//')
if [ -d /opt/stack/new/$lib ] ; then
tip_location="git+file:///opt/stack/new/$lib#egg=$egg"
echo "$(which pip) install -U -e $tip_location"
pip uninstall -y $lib
pip install -U -e $tip_location
else
echo "$lib not found in /opt/stack/new/$lib"
fi
done
-70
View File
@@ -1,70 +0,0 @@
#!/bin/bash
#############################################################################
# run-ansible-tests.sh
#
# Script used to setup a tox environment for running Ansible. This is meant
# to be called by tox (via tox.ini). To run the Ansible tests, use:
#
# tox -e ansible [TAG ...]
# or
# tox -e ansible -- -c cloudX [TAG ...]
#
# USAGE:
# run-ansible-tests.sh -e ENVDIR [-c CLOUD] [TAG ...]
#
# PARAMETERS:
# -e ENVDIR Directory of the tox environment to use for testing.
# -c CLOUD Name of the cloud to use for testing.
# Defaults to "devstack-admin".
# [TAG ...] Optional list of space-separated tags to control which
# modules are tested.
#
# EXAMPLES:
# # Run all Ansible tests
# run-ansible-tests.sh -e ansible
#
# # Run auth, keypair, and network tests against cloudX
# run-ansible-tests.sh -e ansible -c cloudX auth keypair network
#############################################################################
CLOUD="devstack-admin"
ENVDIR=
while getopts "c:de:" opt
do
case $opt in
c) CLOUD=${OPTARG} ;;
e) ENVDIR=${OPTARG} ;;
?) echo "Invalid option: -${OPTARG}"
exit 1;;
esac
done
if [ -z ${ENVDIR} ]
then
echo "Option -e is required"
exit 1
fi
shift $((OPTIND-1))
TAGS=$( echo "$*" | tr ' ' , )
# Run the shade Ansible tests
tag_opt=""
if [ ! -z ${TAGS} ]
then
tag_opt="--tags ${TAGS}"
fi
# Until we have a module that lets us determine the image we want from
# within a playbook, we have to find the image here and pass it in.
# We use the openstack client instead of nova client since it can use clouds.yaml.
IMAGE=`openstack --os-cloud=${CLOUD} image list -f value -c Name | grep cirros | grep -v -e ramdisk -e kernel`
if [ $? -ne 0 ]
then
echo "Failed to find Cirros image"
exit 1
fi
ansible-playbook -vvv ./shade/tests/ansible/run.yml -e "cloud=${CLOUD} image=${IMAGE}" ${tag_opt}
-43
View File
@@ -1,43 +0,0 @@
appdirs==1.4.3
certifi==2018.1.18
chardet==3.0.4
coverage==4.0
decorator==4.2.1
deprecation==2.0
dogpile.cache==0.6.5
extras==1.0.0
fixtures==3.0.0
future==0.16.0
idna==2.6
iso8601==0.1.12
jmespath==0.9.3
jsonpatch==1.21
jsonpointer==2.0
keystoneauth1==3.8.0
linecache2==1.0.0
mock==2.0.0
mox3==0.20.0
munch==2.2.0
netifaces==0.10.6
openstacksdk==0.15.0
os-client-config==1.28.0
os-service-types==1.2.0
oslotest==3.2.0
packaging==17.1
pbr==2.0.0
pyparsing==2.2.0
python-mimeparse==1.6.0
python-subunit==1.0.0
PyYAML==3.12
requests-mock==1.2.0
requests==2.18.4
requestsexceptions==1.4.0
six==1.11.0
stestr==1.0.0
stevedore==1.28.0
testrepository==0.0.18
testscenarios==0.4
testtools==2.2.0
traceback2==1.4.0
unittest2==1.1.0
urllib3==1.22
-10
View File
@@ -1,10 +0,0 @@
- hosts: all
tasks:
- name: Set shade libraries to master branch before functional tests
command: git checkout master
args:
chdir: "src/opendev.org/openstack/{{ item }}"
with_items:
- keystoneauth
- os-client-config
-4
View File
@@ -1,4 +0,0 @@
- hosts: all
roles:
- fetch-tox-output
- fetch-subunit-output
@@ -1,4 +0,0 @@
---
features:
- Added a new property, 'current_user_id' which contains
the id of the currently authenticated user from the token.
@@ -1,4 +0,0 @@
---
features:
- All get and search functions can now take a jmespath expression in their
filters parameter.
@@ -1,4 +0,0 @@
---
features:
- Add a list_flavor_access method to list all
the projects/tenants allowed to access a given flavor.
@@ -1,6 +0,0 @@
---
features:
- Added get_server_console method to fetch the console
log from a Server. On clouds that do not expose this
feature, a debug line will be logged and an empty
string will be returned.
@@ -1,9 +0,0 @@
---
features:
- Added flag "show_all" to list_images. The behavior of
Glance v2 to only show shared images if they have been
accepted by the user can be confusing, and the only way
to change it is to use search_images(filters=dict(member_status='all'))
which isn't terribly obvious. "show_all=True" will set
that flag, as well as disabling the filtering of images
in "deleted" state.
@@ -1,9 +0,0 @@
---
features:
- |
The networking API v2 specification, which is implemented by OpenStack
Neutron, features an optional routes parameter - when updating a router
(PUT requests). Static routes are crucial for routers to handle traffic
from subnets not directly connected to a router. The routes parameter has
now been added to the OpenStackCloud.update_router method as a list of
dictionaries with destination and nexthop parameters.
@@ -1,3 +0,0 @@
---
features:
- Add description parameter to create_user, available on Keystone v3
@@ -1,4 +0,0 @@
---
features:
- Add support for Designate recordsets resources, with the
usual methods (search/list/get/create/update/delete).
@@ -1,4 +0,0 @@
---
features:
- Add support for Designate zones resources, with the
usual methods (search/list/get/create/update/delete).
@@ -1,7 +0,0 @@
---
features:
- |
Add tags support when creating a stack, as specified by the openstack
orchestration api at [1]
[1]https://developer.openstack.org/api-ref/orchestration/v1/#create-stack
@@ -1,4 +0,0 @@
---
features:
- Add support for host aggregates and host aggregate
membership.
@@ -1,7 +0,0 @@
---
features:
- Add support for Magnum baymodels, with the
usual methods (search/list/get/create/update/delete). Due to upcoming
rename in Magnum from baymodel to cluster_template, the shade
functionality uses the term cluster_template. However, baymodel aliases
are provided for each api call.
@@ -1,3 +0,0 @@
---
features:
- Add support for listing Magnum services.
@@ -1,3 +0,0 @@
---
features:
- Adds support to create and delete server groups.
@@ -1,3 +0,0 @@
---
features:
- Add update_server method to update name or description of a server.
@@ -1,6 +0,0 @@
---
features:
- Add the ability to update a keystone service information. This feature is
not available on keystone v2.0. The new function, update_service(), allows
the user to update description, name of service, service type, and enabled
status.
@@ -1,5 +0,0 @@
---
features:
- Added methods for making new cloud connections
based on the current OpenStackCloud. This should enable working
more easily across projects or user accounts.
@@ -1,5 +0,0 @@
---
upgrade:
- Cluster Templates have data model and normalization
now. As a result, the detail parameter is now ignored
and detailed records are always returned.
@@ -1,4 +0,0 @@
---
features:
- Added ``group`` parameter to create_server to allow
booting a server into a specific server group.
@@ -1,10 +0,0 @@
---
prelude: >
Fixed a bug where a project was always enabled upon update, unless
``enabled=False`` is passed explicitly.
fixes:
- |
[`bug 2001080 <https://storyboard.openstack.org/#!/story/2001080>`_]
Project update will only update the enabled field of projects when
``enabled=True`` or ``enabled=False`` is passed explicitly. The previous
behavior had ``enabled=True`` as the default.
@@ -1,4 +0,0 @@
---
fixes:
- Fixed caching the volume list when volumes are in
use.
@@ -1,8 +0,0 @@
---
upgrade:
- |
The ``attach_volume`` method now always returns a ``volume_attachment``
object. Previously, ``attach_volume`` would return a ``volume`` object if
it was called with ``wait=True`` and a ``volume_attachment`` object
otherwise.
@@ -1,4 +0,0 @@
---
features:
- Add support for Cinder volume backup resources, with the
usual methods (search/list/get/create/delete).
@@ -1,3 +0,0 @@
---
fixes:
- Fixed the volume normalization function when used with cinder v2.
@@ -1,6 +0,0 @@
---
features:
- If shade has to create objects in swift to upload an
image, it will now delete those objects upon successful
image creation as they are no longer needed. They will
also be deleted on fatal import errors.
@@ -1,3 +0,0 @@
---
features:
- Add new APIs, OperatorCloud.get_compute_quotas(), OperatorCloud.set_compute_quotas() and OperatorCloud.delete_compute_quotas() to manage nova quotas for projects and users
@@ -1,9 +0,0 @@
---
features:
- get_compute_usage now has a default value for the start
parameter of 2010-07-06. That was the date the OpenStack
project started. It's completely impossible for someone
to have Nova usage data that goes back further in time.
Also, both the start and end date parameters now also
accept strings which will be parsed and timezones will
be properly converted to UTC which is what Nova expects.
@@ -1,4 +0,0 @@
---
features:
- Adds ability to add a config setting to clouds.yaml to
disable fetching extra_specs from flavors.
@@ -1,4 +0,0 @@
---
fixes:
- The create_stack() call was fixed to call the correct iterator
method and to return the updated stack object when waiting.
@@ -1,6 +0,0 @@
---
fixes:
- The create_server() API call would not use the supplied 'network'
parameter if the 'nics' parameter was also supplied, even though it would
be an empty list. It now uses 'network' if 'nics' is not supplied or if
it is an empty list.
@@ -1,3 +0,0 @@
---
fixes:
- The returned data from a create_service() call was not being normalized.
@@ -1,8 +0,0 @@
---
features:
- Explicit data model contracts are now defined for
Flavors, Images, Security Groups, Security Group Rules,
and Servers.
- Resources with data model contracts are now being returned with
'location' attribute. The location carries cloud name, region
name and information about the project that owns the resource.
@@ -1,5 +0,0 @@
---
features:
- Added new method, delete_autocreated_image_objects
that can be used to delete any leaked objects shade
may have created on behalf of the user.
@@ -1,18 +0,0 @@
---
fixes:
- Delete swift objects uploaded in service of uploading images
at the time that the corresponding image is deleted. On some clouds,
image uploads are accomplished by uploading the image to swift and
then running a task-import. As shade does this action on behalf of the
user, it is not reasonable to assume that the user would then be aware
of or manage the swift objects shade created, which led to an ongoing
leak of swift objects.
- Upload swift Large Objects as Static Large Objects by default. Shade
automatically uploads objects as Large Objects when they are over a
segment_size threshold. It had been doing this as Dynamic Large Objects,
which sound great, but which have the downside of not deleting their
sub-segments when the primary object is deleted. Since nothing in the
shade interface exposes that the object was segmented, the user would not
know they would also need to find and delete the segments. Instead, we
now upload as Static Large Objects which behave as expected and delete
segments when the object is deleted.
@@ -1,5 +0,0 @@
---
fixes:
- The delete_object() method was not returning True/False,
similar to other delete methods. It is now consistent with
the other delete APIs.
@@ -1,5 +0,0 @@
---
fixes:
- The delete_project() API now conforms to our standard of returning True
when the delete succeeds, or False when the project was not found. It
would previously raise an expection if the project was not found.
@@ -1,4 +0,0 @@
---
features:
- Added name_or_id parameter to domain operations, allowing
an admin to update/delete/get by domain name.
@@ -1,8 +0,0 @@
---
features:
- Added support for dual stack networks where the IPv4 subnet and the
IPv6 subnet have opposite public/private qualities. It is now possible
to add configuration to clouds.yaml that will indicate that a network
is public for v6 and private for v4, which is otherwise very difficult
to correctly infer while setting server attributes like private_v4,
public_v4 and public_v6.
@@ -1,4 +0,0 @@
---
features:
- Add new method, 'endpoint_for' which will return the
raw endpoint for a given service from the current catalog.
@@ -1,6 +0,0 @@
---
fixes:
- delete_image used to fail with an AttributeError if an invalid image
name or id was passed, rather than returning False which was the
intent. This is worthy of note because it's a behavior change, but the
previous behavior was a bug.
@@ -1,3 +0,0 @@
---
features:
- Add new APIs, OpenStackCloud.set_server_metadata() and OpenStackCloud.delete_server_metadata() to manage metadata of existing nova compute instances
@@ -1,4 +0,0 @@
---
fixes:
- When creating a new server, the timeout was not being passed through to
floating IP creation, which could also timeout.
@@ -1,6 +0,0 @@
---
issues:
- Fixed an issue where nodepool could cause config_drive
to be passed explicitly as None, which was getting directly
passed through to the JSON. Also fix the same logic for key_name
and scheduler_hints while we're in there.
@@ -1,6 +0,0 @@
---
issues:
- Fixed the logic in delete_ips and added regression
tests to cover it. The old logic was incorrectly looking
for floating ips using port syntax. It was also not
swallowing errors when it should.
@@ -1,3 +0,0 @@
---
fixes:
- Fix for list_networks() ignoring any filters.
@@ -1,5 +0,0 @@
---
fixes:
- Added missing dependency on futures library for python 2.
The depend was missed in testing due to it having been listed
in test-requirements already.
@@ -1,4 +0,0 @@
---
issues:
- Images in the cloud with a string property named "properties"
caused image normalization to bomb.
@@ -1,7 +0,0 @@
---
fixes:
- Fixed an issue where shade could report a floating IP being attached
to a server erroneously due to only matching on fixed ip. Changed the
lookup to match on port ids. This adds an API call in the case where
the workaround is needed because of a bug in the cloud, but in most
cases it should have no difference.
@@ -1,3 +0,0 @@
---
fixes:
- Fix for update_domain() where 'name' was not updatable.
@@ -1,6 +0,0 @@
---
fixes:
- Fixed magnum service_type. shade was using it as 'container'
but the correct type is 'container-infra'. It's possible that on
old clouds with magnum shade may now do the wrong thing. If that
occurs, please file a bug.
@@ -1,7 +0,0 @@
---
features:
- Flavors will always contain an 'extra_specs' attribute. Client cruft,
such as 'links', 'HUMAN_ID', etc. has been removed.
fixes:
- Setting and unsetting flavor extra specs now works. This had
been broken since the 1.2.0 release.
@@ -1,5 +0,0 @@
---
features:
- name_or_id parameters to search/get methods now support
filename-like globbing. This means search_servers('nb0*')
will return all servers whose names start with 'nb0'.
@@ -1,3 +0,0 @@
---
features:
- Allow to retrieve the limits of a specific project
@@ -1,3 +0,0 @@
---
features:
- Allow to retrieve the usage of a specific project
Loaded 100 of 341 files, more files were not shown because too many files have changed in this diff. Show more