Addapted flame to openstacksdk and shade.
Flame needed pemanent adjustments to mathe the changes in the python-openstackclients. We now use openstacksdk or shade which will handle themselves the compatibility. We also made flame modular so that any-one can add features by implementing there own flame managers and adding their modules to the `openstack_flame` entry point. This new flame version is also fully compatible with python 3. Change-Id: I586a165b5022031963f504874bd50e1b11fe0d27
This commit is contained in:
parent
2cc573d049
commit
e798119841
6
.gitignore
vendored
6
.gitignore
vendored
@ -1,4 +1,5 @@
|
||||
*.py[cod]
|
||||
.venv
|
||||
|
||||
# C extensions
|
||||
*.so
|
||||
@ -23,6 +24,7 @@ pip-log.txt
|
||||
|
||||
# Unit test / coverage reports
|
||||
.coverage
|
||||
cover
|
||||
.tox
|
||||
nosetests.xml
|
||||
.testrepository
|
||||
@ -48,4 +50,6 @@ ChangeLog
|
||||
|
||||
# Editors
|
||||
*~
|
||||
.*.swp
|
||||
.*.swp
|
||||
.idea
|
||||
.vscode
|
||||
|
28
CONTRIBUTING.rst
Normal file
28
CONTRIBUTING.rst
Normal file
@ -0,0 +1,28 @@
|
||||
When developping on flameclient, do not forget to check code quality with the
|
||||
`./checkcode` command, and then check you did not brake anything by running
|
||||
`python -m unittest discover -v`.
|
||||
|
||||
To create flame modules you need to create a module with a class which
|
||||
inheritates from `flameclient.resources.ResourceManager`
|
||||
|
||||
You need to implement the `api_resources` property and the `get_hot_resources()`
|
||||
method (read their docstring for more information).
|
||||
If you want you can also implement the `add_arguments(parser=None)` method to
|
||||
add your own module's command line arguments.
|
||||
You can also implement the `post_process()`,
|
||||
`post_process_hot_resources(resources)`, `post_process_heat_template(template)` and/or
|
||||
`post_process_adoption_data(adoption_data)` methods to perform
|
||||
post processing after the generator's `extract_data` method was called
|
||||
(read their docstring for more information). This allows you to modify results
|
||||
before rendering the template.
|
||||
These post processing methods are not threaded and are executed in order of the
|
||||
managers' `post_priority` attribute (defaults to 100).
|
||||
|
||||
Then, you need to add in your package's `setup.py` or `setup.cfg` an
|
||||
'openstack_flame' entry point pointing to the module file where your subclass
|
||||
of `flameclient.resources.ResourceManager` is defined.
|
||||
|
||||
Once your package installed, flame will automatically discover all
|
||||
'openstack_flame' entry points to load the corresponding modules, and all
|
||||
loaded modules having a `flameclient.resources.ResourceManager` subclass will
|
||||
have this subclass detected and added tho the list of managers.
|
21
LICENSE
21
LICENSE
@ -1,21 +0,0 @@
|
||||
This software is released under the MIT License.
|
||||
|
||||
Copyright (c) 2014 Cloudwatt
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
170
README.rst
170
README.rst
@ -32,64 +32,154 @@ Then just run:
|
||||
Usage
|
||||
-----
|
||||
|
||||
usage: flame [-h] [--username USERNAME] [--password PASSWORD]
|
||||
[--project PROJECT] [--region REGION] [--auth_url AUTH_URL]
|
||||
[--os-auth-token OS_AUTH_TOKEN] [--insecure]
|
||||
[--os-cert <certification>] [--os-key <key>]
|
||||
[--endpoint_type ENDPOINT_TYPE] [--exclude-servers]
|
||||
[--exclude-volumes] [--exclude-keypairs] [--generate-stack-data]
|
||||
[--extract-ports] [--exclude-secgroup]
|
||||
To use the CLI of flame::
|
||||
|
||||
usage: flame [-h] [--debug] [--generate-stack-data] [--include-constraints]
|
||||
[--no-threads] [--prefetch] [--exclude-keypairs]
|
||||
[--extract-ports] [--exclude-secgroups] [--exclude-servers]
|
||||
[--exclude-volumes] [--os-cloud <name>] [--os-auth-type <name>]
|
||||
[--os-auth-url OS_AUTH_URL] [--os-system-scope OS_SYSTEM_SCOPE]
|
||||
[--os-domain-id OS_DOMAIN_ID] [--os-domain-name OS_DOMAIN_NAME]
|
||||
[--os-project-id OS_PROJECT_ID]
|
||||
[--os-project-name OS_PROJECT_NAME]
|
||||
[--os-project-domain-id OS_PROJECT_DOMAIN_ID]
|
||||
[--os-project-domain-name OS_PROJECT_DOMAIN_NAME]
|
||||
[--os-trust-id OS_TRUST_ID]
|
||||
[--os-default-domain-id OS_DEFAULT_DOMAIN_ID]
|
||||
[--os-default-domain-name OS_DEFAULT_DOMAIN_NAME]
|
||||
[--os-user-id OS_USER_ID] [--os-username OS_USERNAME]
|
||||
[--os-user-domain-id OS_USER_DOMAIN_ID]
|
||||
[--os-user-domain-name OS_USER_DOMAIN_NAME]
|
||||
[--os-password OS_PASSWORD] [--insecure]
|
||||
[--os-cacert <ca-certificate>] [--os-cert <certificate>]
|
||||
[--os-key <key>] [--timeout <seconds>] [--collect-timing]
|
||||
[--os-service-type <name>] [--os-service-name <name>]
|
||||
[--os-interface <name>] [--os-region-name <name>]
|
||||
[--os-endpoint-override <name>] [--os-api-version <name>]
|
||||
|
||||
Heat template and data file generator
|
||||
|
||||
optional arguments:
|
||||
-h, --help show this help message and exit
|
||||
--username USERNAME A user name with access to the project. Defaults to
|
||||
env[OS_USERNAME]
|
||||
--password PASSWORD The user's password. Defaults to env[OS_PASSWORD]
|
||||
--project PROJECT Name of project. Defaults to env[OS_TENANT_NAME]
|
||||
--region REGION Name of region. Defaults to env[OS_REGION_NAME]
|
||||
--auth_url AUTH_URL Authentication URL. Defaults to env[OS_AUTH_URL].
|
||||
--os-auth-token OS_AUTH_TOKEN
|
||||
User's auth token. Defaults to env[OS_AUTH_TOKEN].
|
||||
--os-cert <certificate>
|
||||
Path to user's certificate needed to establish
|
||||
two-way SSL connection with the identity service.
|
||||
Defaults to env[OS_CERT].
|
||||
--os-key <key> Path to the user's certificate private key.
|
||||
Defaults to env[OS_KEY].
|
||||
--insecure Explicitly allow clients to perform"insecure" SSL
|
||||
(https) requests. The server's certificate will not be
|
||||
verified against any certificate authorities. This
|
||||
option should be used with caution.
|
||||
--endpoint_type ENDPOINT_TYPE
|
||||
Defaults to env[OS_ENDPOINT_TYPE] or publicURL
|
||||
--exclude-servers Do not export in template server resources
|
||||
--exclude-volumes Do not export in template volume resources
|
||||
--exclude-keypairs Do not export in template key pair resources
|
||||
--debug set debuging log level
|
||||
--generate-stack-data
|
||||
In addition to template, generate Heat stack data
|
||||
file.
|
||||
--include-constraints
|
||||
Export in template custom constraints
|
||||
--no-threads Deactivate threads for api calls, (usefull for (i)pdb
|
||||
debugging.
|
||||
--prefetch Prefetch all API calls (works only without --no-
|
||||
threads
|
||||
--exclude-keypairs Do not export in template key pair resources
|
||||
--extract-ports Export the tenant network ports
|
||||
--exclude-secgroups Do not export in template security group resources
|
||||
--exclude-servers Do not export in template server resources
|
||||
--exclude-volumes Do not export in template volume resources
|
||||
--os-cloud <name> Named cloud to connect to
|
||||
--os-auth-type <name>, --os-auth-plugin <name>
|
||||
Authentication type to use
|
||||
|
||||
Authentication Options:
|
||||
Options specific to the password plugin.
|
||||
|
||||
--os-auth-url OS_AUTH_URL
|
||||
Authentication URL
|
||||
--os-system-scope OS_SYSTEM_SCOPE
|
||||
Scope for system operations
|
||||
--os-domain-id OS_DOMAIN_ID
|
||||
Domain ID to scope to
|
||||
--os-domain-name OS_DOMAIN_NAME
|
||||
Domain name to scope to
|
||||
--os-project-id OS_PROJECT_ID, --os-tenant-id OS_PROJECT_ID
|
||||
Project ID to scope to
|
||||
--os-project-name OS_PROJECT_NAME, --os-tenant-name OS_PROJECT_NAME
|
||||
Project name to scope to
|
||||
--os-project-domain-id OS_PROJECT_DOMAIN_ID
|
||||
Domain ID containing project
|
||||
--os-project-domain-name OS_PROJECT_DOMAIN_NAME
|
||||
Domain name containing project
|
||||
--os-trust-id OS_TRUST_ID
|
||||
Trust ID
|
||||
--os-default-domain-id OS_DEFAULT_DOMAIN_ID
|
||||
Optional domain ID to use with v3 and v2 parameters.
|
||||
It will be used for both the user and project domain
|
||||
in v3 and ignored in v2 authentication.
|
||||
--os-default-domain-name OS_DEFAULT_DOMAIN_NAME
|
||||
Optional domain name to use with v3 API and v2
|
||||
parameters. It will be used for both the user and
|
||||
project domain in v3 and ignored in v2 authentication.
|
||||
--os-user-id OS_USER_ID
|
||||
User id
|
||||
--os-username OS_USERNAME, --os-user-name OS_USERNAME
|
||||
Username
|
||||
--os-user-domain-id OS_USER_DOMAIN_ID
|
||||
User's domain id
|
||||
--os-user-domain-name OS_USER_DOMAIN_NAME
|
||||
User's domain name
|
||||
--os-password OS_PASSWORD
|
||||
User's password
|
||||
|
||||
API Connection Options:
|
||||
Options controlling the HTTP API Connections
|
||||
|
||||
--insecure Explicitly allow client to perform "insecure" TLS
|
||||
(https) requests. The server's certificate will not be
|
||||
verified against any certificate authorities. This
|
||||
option should be used with caution.
|
||||
--os-cacert <ca-certificate>
|
||||
Specify a CA bundle file to use in verifying a TLS
|
||||
(https) server certificate. Defaults to
|
||||
env[OS_CACERT].
|
||||
--os-cert <certificate>
|
||||
Defaults to env[OS_CERT].
|
||||
--os-key <key> Defaults to env[OS_KEY].
|
||||
--timeout <seconds> Set request timeout (in seconds).
|
||||
--collect-timing Collect per-API call timing information.
|
||||
|
||||
Service Options:
|
||||
Options controlling the specialization of the API Connection from
|
||||
information found in the catalog
|
||||
|
||||
--os-service-type <name>
|
||||
Service type to request from the catalog
|
||||
--os-service-name <name>
|
||||
Service name to request from the catalog
|
||||
--os-interface <name>
|
||||
API Interface to use [public, internal, admin]
|
||||
--os-region-name <name>
|
||||
Region of the cloud to use
|
||||
--os-endpoint-override <name>
|
||||
Endpoint to use instead of the endpoint in the catalog
|
||||
--os-api-version <name>
|
||||
Which version of the service API to use
|
||||
|
||||
Usage example
|
||||
-------------
|
||||
|
||||
To use Flame you can provide yours OpenStack credentials as arguments :
|
||||
|
||||
$ flame --username user --password password --project project
|
||||
--auth_url http://<Keystone_host>:5000/v2.0
|
||||
To use Flame you can provide yours OpenStack credentials as arguments ::
|
||||
|
||||
$ flame --os-username 'user_name' \
|
||||
--os-password 'password' \
|
||||
--os-project-name 'project_name' \
|
||||
--os-auth-url 'http://<Keystone_host>:5000/v2.0'
|
||||
|
||||
Or you can source your OpenStack RC file and use Flame without arguments.
|
||||
|
||||
To establish a two-way SSL connection with the identity service :
|
||||
To establish a two-way SSL connection with the identity service ::
|
||||
|
||||
$flame --username arezmerita --os-auth-token keystonetoken \
|
||||
--project project-arezmerita --auth_url http://<Keystone_host>:5000/v2.0
|
||||
--os-cert <path/to/certificate> --os-key <path/to/key>
|
||||
$flame --os-username 'user_name' \
|
||||
--os-password 'password' \
|
||||
--os-project-name 'project_name' \
|
||||
--os-auth_url http://<Keystone_host>:5000/v2.0 \
|
||||
--os-cert <path/to/certificate> \
|
||||
--os-key <path/to/key>
|
||||
|
||||
Flame can be used with either a login and password pair or a keystone
|
||||
token by exporting the OS_AUTH_TOKEN variable (the token is obtained
|
||||
with keystone token-get).
|
||||
token by exporting the OS_AUTH_TOKEN variable and the `--os-auth-type 'token'`
|
||||
parameter (the token is obtained with keystone token-get )::
|
||||
|
||||
$ flame --os-auth-type 'token' \
|
||||
--os-token 'token_id' \
|
||||
--os-auth-url 'http://<Keystone_host>:5000/v2.0'
|
||||
|
||||
|
12
check_code
Executable file
12
check_code
Executable file
@ -0,0 +1,12 @@
|
||||
#!/usr/bin/env bash
|
||||
CURDIR=$(pwd)
|
||||
SELFDIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
|
||||
|
||||
cd $SELFDIR
|
||||
python -m flake8 flameclient
|
||||
if [[ $1 = '-v' ]]; then
|
||||
python -m pylint --rcfile=pylintrc --reports=yes flameclient
|
||||
else
|
||||
python -m pylint --rcfile=pylintrc flameclient
|
||||
fi
|
||||
cd $CURDIR
|
4
dev-requirements.txt
Normal file
4
dev-requirements.txt
Normal file
@ -0,0 +1,4 @@
|
||||
bpython==0.17.1
|
||||
ipython==5.8.0
|
||||
ipdb==0.11
|
||||
q==2.6
|
@ -72,4 +72,4 @@ latex_documents = [
|
||||
]
|
||||
|
||||
# Example configuration for intersphinx: refer to the Python standard library.
|
||||
#intersphinx_mapping = {'http://docs.python.org/': None}
|
||||
#intersphinx_mapping = {'http://docs.python.org/': None}
|
||||
|
@ -9,4 +9,5 @@ At the command line::
|
||||
Or, if you have virtualenvwrapper installed::
|
||||
|
||||
$ mkvirtualenv python-flameclient
|
||||
$ pip install python-flameclient
|
||||
$ pip install python-flameclient
|
||||
|
||||
|
@ -14,5 +14,3 @@ free IP addresses of a pool, for example, with a pool starting at 10.0.0.2 :
|
||||
When this stack is imported in Heat, the DHCP server IP is set to the lowest
|
||||
free IP address of its pool. Depending on the VM creation order, the DHCP
|
||||
address can either collide with vm1's or vm2's IP.
|
||||
|
||||
|
||||
|
@ -8,45 +8,125 @@ To use install flame in a project::
|
||||
|
||||
To use the CLI of flame::
|
||||
|
||||
usage: flame [-h] [--username USERNAME] [--password PASSWORD]
|
||||
[--project PROJECT] [--region REGION] [--auth_url AUTH_URL]
|
||||
[--os-auth-token OS_AUTH_TOKEN] [--insecure]
|
||||
[--os-cert <certification>] [--os-key <key>]
|
||||
[--endpoint_type ENDPOINT_TYPE] [--exclude-servers]
|
||||
[--exclude-volumes] [--exclude-keypairs] [--generate-stack-data]
|
||||
[--extract-ports]
|
||||
usage: flame [-h] [--debug] [--generate-stack-data] [--include-constraints]
|
||||
[--no-threads] [--prefetch] [--exclude-keypairs]
|
||||
[--extract-ports] [--exclude-secgroups] [--exclude-servers]
|
||||
[--exclude-volumes] [--os-cloud <name>] [--os-auth-type <name>]
|
||||
[--os-auth-url OS_AUTH_URL] [--os-system-scope OS_SYSTEM_SCOPE]
|
||||
[--os-domain-id OS_DOMAIN_ID] [--os-domain-name OS_DOMAIN_NAME]
|
||||
[--os-project-id OS_PROJECT_ID]
|
||||
[--os-project-name OS_PROJECT_NAME]
|
||||
[--os-project-domain-id OS_PROJECT_DOMAIN_ID]
|
||||
[--os-project-domain-name OS_PROJECT_DOMAIN_NAME]
|
||||
[--os-trust-id OS_TRUST_ID]
|
||||
[--os-default-domain-id OS_DEFAULT_DOMAIN_ID]
|
||||
[--os-default-domain-name OS_DEFAULT_DOMAIN_NAME]
|
||||
[--os-user-id OS_USER_ID] [--os-username OS_USERNAME]
|
||||
[--os-user-domain-id OS_USER_DOMAIN_ID]
|
||||
[--os-user-domain-name OS_USER_DOMAIN_NAME]
|
||||
[--os-password OS_PASSWORD] [--insecure]
|
||||
[--os-cacert <ca-certificate>] [--os-cert <certificate>]
|
||||
[--os-key <key>] [--timeout <seconds>] [--collect-timing]
|
||||
[--os-service-type <name>] [--os-service-name <name>]
|
||||
[--os-interface <name>] [--os-region-name <name>]
|
||||
[--os-endpoint-override <name>] [--os-api-version <name>]
|
||||
|
||||
Heat template and data file generator
|
||||
|
||||
optional arguments:
|
||||
-h, --help show this help message and exit
|
||||
--username USERNAME A user name with access to the project. Defaults to
|
||||
env[OS_USERNAME]
|
||||
--password PASSWORD The user's password. Defaults to env[OS_PASSWORD]
|
||||
--project PROJECT Name of project. Defaults to env[OS_TENANT_NAME]
|
||||
--region REGION Name of region. Defaults to env[OS_REGION_NAME]
|
||||
--auth_url AUTH_URL Authentication URL. Defaults to env[OS_AUTH_URL].
|
||||
--os-auth-token OS_AUTH_TOKEN
|
||||
User's auth token. Defaults to env[OS_AUTH_TOKEN].
|
||||
--os-cert <certificate>
|
||||
Path to user's certificate needed to establish
|
||||
two-way SSL connection with the identity service.
|
||||
Defaults to env[OS_CERT].
|
||||
--os-key <key> Path to the user's certificate private key.
|
||||
Defaults to env[OS_KEY].
|
||||
--insecure Explicitly allow clients to perform"insecure" SSL
|
||||
(https) requests. The server's certificate will not be
|
||||
verified against any certificate authorities. This
|
||||
option should be used with caution.
|
||||
--endpoint_type ENDPOINT_TYPE
|
||||
Defaults to env[OS_ENDPOINT_TYPE] or publicURL
|
||||
--exclude-servers Do not export in template server resources
|
||||
--exclude-volumes Do not export in template volume resources
|
||||
--exclude-keypairs Do not export in template key pair resources
|
||||
--debug set debuging log level
|
||||
--generate-stack-data
|
||||
In addition to template, generate Heat stack data
|
||||
file.
|
||||
--include-constraints
|
||||
Export in template custom constraints
|
||||
--no-threads Deactivate threads for api calls, (usefull for (i)pdb
|
||||
debugging.
|
||||
--prefetch Prefetch all API calls (works only without --no-
|
||||
threads
|
||||
--exclude-keypairs Do not export in template key pair resources
|
||||
--extract-ports Export the tenant network ports
|
||||
--exclude-secgroups Do not export in template security group resources
|
||||
--exclude-servers Do not export in template server resources
|
||||
--exclude-volumes Do not export in template volume resources
|
||||
--os-cloud <name> Named cloud to connect to
|
||||
--os-auth-type <name>, --os-auth-plugin <name>
|
||||
Authentication type to use
|
||||
|
||||
Authentication Options:
|
||||
Options specific to the password plugin.
|
||||
|
||||
--os-auth-url OS_AUTH_URL
|
||||
Authentication URL
|
||||
--os-system-scope OS_SYSTEM_SCOPE
|
||||
Scope for system operations
|
||||
--os-domain-id OS_DOMAIN_ID
|
||||
Domain ID to scope to
|
||||
--os-domain-name OS_DOMAIN_NAME
|
||||
Domain name to scope to
|
||||
--os-project-id OS_PROJECT_ID, --os-tenant-id OS_PROJECT_ID
|
||||
Project ID to scope to
|
||||
--os-project-name OS_PROJECT_NAME, --os-tenant-name OS_PROJECT_NAME
|
||||
Project name to scope to
|
||||
--os-project-domain-id OS_PROJECT_DOMAIN_ID
|
||||
Domain ID containing project
|
||||
--os-project-domain-name OS_PROJECT_DOMAIN_NAME
|
||||
Domain name containing project
|
||||
--os-trust-id OS_TRUST_ID
|
||||
Trust ID
|
||||
--os-default-domain-id OS_DEFAULT_DOMAIN_ID
|
||||
Optional domain ID to use with v3 and v2 parameters.
|
||||
It will be used for both the user and project domain
|
||||
in v3 and ignored in v2 authentication.
|
||||
--os-default-domain-name OS_DEFAULT_DOMAIN_NAME
|
||||
Optional domain name to use with v3 API and v2
|
||||
parameters. It will be used for both the user and
|
||||
project domain in v3 and ignored in v2 authentication.
|
||||
--os-user-id OS_USER_ID
|
||||
User id
|
||||
--os-username OS_USERNAME, --os-user-name OS_USERNAME
|
||||
Username
|
||||
--os-user-domain-id OS_USER_DOMAIN_ID
|
||||
User's domain id
|
||||
--os-user-domain-name OS_USER_DOMAIN_NAME
|
||||
User's domain name
|
||||
--os-password OS_PASSWORD
|
||||
User's password
|
||||
|
||||
API Connection Options:
|
||||
Options controlling the HTTP API Connections
|
||||
|
||||
--insecure Explicitly allow client to perform "insecure" TLS
|
||||
(https) requests. The server's certificate will not be
|
||||
verified against any certificate authorities. This
|
||||
option should be used with caution.
|
||||
--os-cacert <ca-certificate>
|
||||
Specify a CA bundle file to use in verifying a TLS
|
||||
(https) server certificate. Defaults to
|
||||
env[OS_CACERT].
|
||||
--os-cert <certificate>
|
||||
Defaults to env[OS_CERT].
|
||||
--os-key <key> Defaults to env[OS_KEY].
|
||||
--timeout <seconds> Set request timeout (in seconds).
|
||||
--collect-timing Collect per-API call timing information.
|
||||
|
||||
Service Options:
|
||||
Options controlling the specialization of the API Connection from
|
||||
information found in the catalog
|
||||
|
||||
--os-service-type <name>
|
||||
Service type to request from the catalog
|
||||
--os-service-name <name>
|
||||
Service name to request from the catalog
|
||||
--os-interface <name>
|
||||
API Interface to use [public, internal, admin]
|
||||
--os-region-name <name>
|
||||
Region of the cloud to use
|
||||
--os-endpoint-override <name>
|
||||
Endpoint to use instead of the endpoint in the catalog
|
||||
--os-api-version <name>
|
||||
Which version of the service API to use
|
||||
|
||||
|
||||
Example
|
||||
@ -54,21 +134,28 @@ Example
|
||||
|
||||
To use Flame you can provide yours OpenStack credentials as arguments::
|
||||
|
||||
$ flame --username arezmerita --password password \
|
||||
--project project-arezmerita --auth_url https://example.com/v2.0/
|
||||
$ flame --os-username 'user_name' \
|
||||
--os-password 'password' \
|
||||
--os-project-name 'project_name' \
|
||||
--os-auth-url 'http://<Keystone_host>:5000/v2.0'
|
||||
|
||||
Or a token and a tenant::
|
||||
|
||||
$ flame --username arezmerita --os-auth-token keystonetoken \
|
||||
--project project-arezmerita --auth_url https://example.com/v2.0/
|
||||
$ flame --os-auth-type 'token' \
|
||||
--os-token 'token_id' \
|
||||
--os-auth-url 'http://<Keystone_host>:5000/v2.0'
|
||||
|
||||
To establish a two-way SSL connection with the identity service ::
|
||||
|
||||
$flame --username arezmerita --os-auth-token keystonetoken \
|
||||
--project project-arezmerita --auth_url https://example.com/v2.0/
|
||||
--os-cert <path/to/certificate> --os-key <path/to/key>
|
||||
$flame --os-username 'user_name' \
|
||||
--os-password 'password' \
|
||||
--os-project-name 'project_name' \
|
||||
--os-auth_url http://<Keystone_host>:5000/v2.0 \
|
||||
--os-cert <path/to/certificate> \
|
||||
--os-key <path/to/key>
|
||||
|
||||
Or you can source your OpenStack RC file and use Flame without arguments::
|
||||
|
||||
$ source credential.rc
|
||||
$ flame
|
||||
|
||||
|
21
flameclient/LICENSE.txt
Normal file
21
flameclient/LICENSE.txt
Normal file
@ -0,0 +1,21 @@
|
||||
This software is released under the MIT License.
|
||||
|
||||
Copyright (c) 2018 Orange Cloud for Business / Cloudwatt
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
@ -1,20 +1,30 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# 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
|
||||
# This software is released under the MIT License.
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
# Copyright (c) 2018 Orange Cloud for Business / Cloudwatt
|
||||
#
|
||||
# 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.
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
import pbr.version
|
||||
|
||||
try:
|
||||
__version__ = pbr.version.VersionInfo('flameclient').version_string()
|
||||
except Exception:
|
||||
except Exception: # pylint: disable=W0703
|
||||
__version__ = 'unknown'
|
||||
|
@ -1,47 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# This software is released under the MIT License.
|
||||
#
|
||||
# Copyright (c) 2014 Cloudwatt
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
from flameclient.flame import TemplateGenerator # noqa
|
||||
|
||||
|
||||
class Client(object):
|
||||
def __init__(self, username, password, tenant_name, auth_url, auth_token,
|
||||
**kwargs):
|
||||
self.template_generator = TemplateGenerator(username, password,
|
||||
tenant_name, auth_url,
|
||||
auth_token,
|
||||
**kwargs)
|
||||
|
||||
def generate(self, exclude_servers, exclude_volumes, exclude_keypairs,
|
||||
generate_stack_data, extract_ports=False,
|
||||
exclude_secgroups=False):
|
||||
self.template_generator.extract_vm_details(exclude_servers,
|
||||
exclude_volumes,
|
||||
exclude_keypairs,
|
||||
generate_stack_data,
|
||||
extract_ports,
|
||||
exclude_secgroups
|
||||
)
|
||||
self.template_generator.extract_data()
|
||||
return self.template_generator.heat_template_and_data()
|
@ -2,7 +2,7 @@
|
||||
|
||||
# This software is released under the MIT License.
|
||||
#
|
||||
# Copyright (c) 2014 Cloudwatt
|
||||
# Copyright (c) 2018 Orange Cloud for Business / Cloudwatt
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
@ -22,95 +22,59 @@
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import argparse
|
||||
import os
|
||||
|
||||
from flameclient import client
|
||||
from flameclient import flame
|
||||
|
||||
|
||||
def main(args=None):
|
||||
desc = "Heat template and data file generator"
|
||||
parser = argparse.ArgumentParser(description=desc)
|
||||
parser.add_argument("--username", type=str,
|
||||
default=os.environ.get("OS_USERNAME"),
|
||||
help="A user name with access to the project. "
|
||||
"Defaults to env[OS_USERNAME]")
|
||||
parser.add_argument("--password", type=str,
|
||||
default=os.environ.get("OS_PASSWORD"),
|
||||
help="The user's password. "
|
||||
"Defaults to env[OS_PASSWORD]")
|
||||
parser.add_argument("--project", type=str,
|
||||
default=os.environ.get("OS_TENANT_NAME"),
|
||||
help="Name of project. "
|
||||
"Defaults to env[OS_TENANT_NAME]")
|
||||
parser.add_argument("--region",
|
||||
default=os.environ.get("OS_REGION_NAME"),
|
||||
help="Name of region. "
|
||||
"Defaults to env[OS_REGION_NAME]")
|
||||
parser.add_argument("--auth_url", type=str,
|
||||
default=os.environ.get("OS_AUTH_URL"),
|
||||
help="Authentication URL. "
|
||||
"Defaults to env[OS_AUTH_URL].")
|
||||
parser.add_argument("--os-auth-token", type=str,
|
||||
default=os.environ.get("OS_AUTH_TOKEN"),
|
||||
help="User's auth token. "
|
||||
"Defaults to env[OS_AUTH_TOKEN].")
|
||||
parser.add_argument('--insecure', action='store_true', default=False,
|
||||
help="Explicitly allow clients to perform"
|
||||
"\"insecure\" SSL (https) requests. The "
|
||||
"server's certificate will not be verified "
|
||||
"against any certificate authorities. This "
|
||||
"option should be used with caution.")
|
||||
parser.add_argument("--endpoint_type", type=str,
|
||||
default=os.environ.get("OS_ENDPOINT_TYPE",
|
||||
"publicURL"),
|
||||
help="Defaults to env[OS_ENDPOINT_TYPE] or publicURL")
|
||||
parser.add_argument("--os-cert", type=str, metavar='<certificate>',
|
||||
default=os.environ.get("OS_CERT"),
|
||||
help="User's certificate. "
|
||||
"Defaults to env[OS_CERT].")
|
||||
parser.add_argument("--os-key", type=str, metavar='<key>',
|
||||
default=os.environ.get("OS_KEY"),
|
||||
help="User's key. "
|
||||
"Defaults to env[OS_KEY].")
|
||||
parser.add_argument('--exclude-servers', action='store_true',
|
||||
default=False,
|
||||
help="Do not export in template server resources")
|
||||
parser.add_argument('--exclude-volumes', action='store_true',
|
||||
default=False,
|
||||
help="Do not export in template volume resources")
|
||||
parser.add_argument('--exclude-keypairs', action='store_true',
|
||||
default=False,
|
||||
help="Do not export in template key pair resources")
|
||||
parser.add_argument('--generate-stack-data', action='store_true',
|
||||
default=False,
|
||||
help="In addition to template, generate Heat "
|
||||
"stack data file.")
|
||||
parser.add_argument('--extract-ports', action='store_true',
|
||||
default=False,
|
||||
help="Export the tenant network ports")
|
||||
parser.add_argument('--exclude-secgroups', action='store_true',
|
||||
default=False,
|
||||
help="Do not export in template "
|
||||
"security group resources")
|
||||
def main():
|
||||
"""Flame heat template generation
|
||||
|
||||
args = parser.parse_args()
|
||||
flame = client.Client(args.username, args.password,
|
||||
args.project, args.auth_url,
|
||||
args.os_auth_token,
|
||||
cert=args.os_cert, key=args.os_key,
|
||||
region_name=args.region,
|
||||
endpoint_type=args.endpoint_type,
|
||||
insecure=args.insecure)
|
||||
template = flame.template_generator
|
||||
template.extract_vm_details(args.exclude_servers,
|
||||
args.exclude_volumes,
|
||||
args.exclude_keypairs,
|
||||
args.generate_stack_data,
|
||||
args.extract_ports,
|
||||
args.exclude_secgroups)
|
||||
template.extract_data()
|
||||
print("### Heat Template ###")
|
||||
print(template.heat_template_and_data())
|
||||
Flame can be used with a shade or openstack sdk instance, and options can
|
||||
be passed as option kwargs.
|
||||
|
||||
ex:
|
||||
|
||||
from flameclient.session import get_shade
|
||||
from flameclient import flame
|
||||
|
||||
auth_kwargs = {
|
||||
'auth_type': u'password',
|
||||
'auth_url': 'https://your_cloud_identity_url/v2.0',
|
||||
'interface': 'public',
|
||||
'password': 'YourPassword',
|
||||
'project_id': 'YourProjectID',
|
||||
'project_name': 'YourProjectName',
|
||||
'region_name': 'region_one',
|
||||
'username': 'YourUserName'
|
||||
}
|
||||
|
||||
cloud = get_shade(**auth_kwargs)
|
||||
|
||||
Or instead of kwargs if you want to use environment variables:
|
||||
|
||||
cloud = get_shade(load_envvars=True)
|
||||
|
||||
Then:
|
||||
|
||||
generator = flame.TemplateGenerator(
|
||||
connection=cloud,
|
||||
options=dict(
|
||||
include_constraint=True,
|
||||
extract_ports=True,
|
||||
generate_adoption_data=True,
|
||||
no_threads=True)
|
||||
)
|
||||
|
||||
generator.extract_data()
|
||||
print(generator.heat_template_and_data())
|
||||
|
||||
Passing a shade or openstack sdk instance and option kwargs allows you to
|
||||
integrate shade in other projects.
|
||||
|
||||
"""
|
||||
template_generator = flame.TemplateGenerator()
|
||||
template_generator.extract_data()
|
||||
template_generator.output_template_and_data()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
32
flameclient/collections_abc.py
Normal file
32
flameclient/collections_abc.py
Normal file
@ -0,0 +1,32 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# This software is released under the MIT License.
|
||||
#
|
||||
# Copyright (c) 2018 Orange Cloud for Business / Cloudwatt
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
try:
|
||||
# This is not handled by six.moves yet:
|
||||
# https://github.com/benjaminp/six/issues/155
|
||||
from collections.abc import * # noqa pylint: disable=W0401,W0614
|
||||
from collections.abc import __all__ # noqa
|
||||
except ImportError:
|
||||
from _abcoll import * # noqa pylint: disable=W0401,W0614
|
||||
from _abcoll import __all__ # noqa
|
1028
flameclient/flame.py
1028
flameclient/flame.py
File diff suppressed because it is too large
Load Diff
98
flameclient/logs.py
Normal file
98
flameclient/logs.py
Normal file
@ -0,0 +1,98 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# This software is released under the MIT License.
|
||||
#
|
||||
# Copyright (c) 2018 Orange Cloud for Business / Cloudwatt
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
import logging
|
||||
from logging.config import dictConfig
|
||||
import sys
|
||||
|
||||
|
||||
COLOR_LOGS = sys.stdout.isatty()
|
||||
|
||||
|
||||
class CWColorFormatter(logging.Formatter):
|
||||
"""Special Formatter adding color to logs.
|
||||
|
||||
color is not added if settings.DEBUG is True to prevent syslog cluttering
|
||||
when in production.
|
||||
|
||||
This Formatter is just Candy for developers.
|
||||
"""
|
||||
LEVEL_COLORS = {
|
||||
logging.NOTSET: '\033[01;0m', # Reset color
|
||||
logging.DEBUG: '\033[00;32m', # GREEN
|
||||
logging.INFO: '\033[00;36m', # CYAN
|
||||
# Where did this one go?:
|
||||
# logging.AUDIT: '\033[01;36m', # BOLD CYAN
|
||||
logging.WARN: '\033[01;33m', # BOLD YELLOW
|
||||
logging.ERROR: '\033[01;31m', # BOLD RED
|
||||
logging.CRITICAL: '\033[01;31m', # BOLD RED
|
||||
}
|
||||
|
||||
reset_color = '\033[01;0m'
|
||||
|
||||
def format(self, record):
|
||||
if COLOR_LOGS:
|
||||
record.reset_color = self.reset_color
|
||||
record.color = self.LEVEL_COLORS[record.levelno]
|
||||
else:
|
||||
# We do not want colors in production because syslog does not
|
||||
# handle them.
|
||||
record.reset_color = ''
|
||||
record.color = ''
|
||||
return super(CWColorFormatter, self).format(record)
|
||||
|
||||
|
||||
LOGGING_CONFIG = {
|
||||
'version': 1,
|
||||
'disable_existing_loggers': False,
|
||||
'formatters': {
|
||||
'standard': {
|
||||
'()': CWColorFormatter,
|
||||
'format': '%(color)s%(levelname)s: %(pathname)s %(funcName)s %(lineno)d:%(reset_color)s %(message)s' # noqa
|
||||
},
|
||||
},
|
||||
'handlers': {
|
||||
'default': {
|
||||
'level': 'DEBUG',
|
||||
'formatter': 'standard',
|
||||
'class': 'logging.StreamHandler',
|
||||
},
|
||||
},
|
||||
'loggers': {
|
||||
'': {
|
||||
'handlers': ['default'],
|
||||
'level': 'INFO',
|
||||
'propagate': True
|
||||
},
|
||||
'flameclient': {
|
||||
'handlers': ['default'],
|
||||
# This can be overriden in the config's logging section
|
||||
'level': 'INFO',
|
||||
'propagate': False
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
dictConfig(LOGGING_CONFIG)
|
@ -1,228 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# This software is released under the MIT License.
|
||||
#
|
||||
# Copyright (c) 2014 Cloudwatt
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
from cinderclient.v1 import client as cinder_client
|
||||
from keystoneclient.v2_0 import client as keystone_client
|
||||
from neutronclient.v2_0 import client as neutron_client
|
||||
from novaclient import client as nova_client
|
||||
|
||||
|
||||
class KeystoneManager(object):
|
||||
"""Manages Keystone queries."""
|
||||
_client = None
|
||||
|
||||
def __init__(self, username, password, project, auth_url, insecure,
|
||||
endpoint_type='publicURL', cert=None, key=None,
|
||||
region_name=None, auth_token=None):
|
||||
self.username = username
|
||||
self.password = password
|
||||
self.project = project
|
||||
self.auth_url = auth_url
|
||||
self.cert = cert
|
||||
self.key = key
|
||||
self.insecure = insecure
|
||||
self.region_name = region_name
|
||||
self.endpoint_type = endpoint_type
|
||||
self.auth_token = auth_token
|
||||
|
||||
def authenticate(self):
|
||||
self.client().authenticate()
|
||||
self.auth_token = self.client().auth_token
|
||||
|
||||
def client(self):
|
||||
if not self._client:
|
||||
self._client = keystone_client.Client(
|
||||
username=self.username,
|
||||
password=self.password,
|
||||
tenant_name=self.project,
|
||||
auth_url=self.auth_url,
|
||||
cert=self.cert,
|
||||
key=self.key,
|
||||
region_name=self.region_name,
|
||||
insecure=self.insecure,
|
||||
endpoint_type=self.endpoint_type,
|
||||
token=self.auth_token)
|
||||
return self._client
|
||||
|
||||
def set_client(self, client):
|
||||
self._client = client
|
||||
|
||||
def get_token(self):
|
||||
return self.client().auth_token
|
||||
|
||||
def get_endpoint(self, service_type, endpoint_type="publicURL"):
|
||||
catalog = self.client().service_catalog.get_endpoints()
|
||||
return catalog[service_type][0][endpoint_type]
|
||||
|
||||
def get_project_id(self):
|
||||
return self.client().project_id
|
||||
|
||||
|
||||
class NeutronManager(object):
|
||||
_client = None
|
||||
_project_id = None
|
||||
|
||||
def __init__(self, keystone_mgr):
|
||||
self.keystone_mgr = keystone_mgr
|
||||
|
||||
def client(self):
|
||||
if not self._client:
|
||||
# Create the client
|
||||
self._client = neutron_client.Client(
|
||||
auth_url=self.keystone_mgr.auth_url,
|
||||
insecure=self.keystone_mgr.insecure,
|
||||
endpoint_url=self.keystone_mgr.get_endpoint('network'),
|
||||
token=self.keystone_mgr.auth_token)
|
||||
if not self._project_id:
|
||||
self._project_id = self.keystone_mgr.get_project_id()
|
||||
return self._client
|
||||
|
||||
def set_client(self, client):
|
||||
self._client = client
|
||||
|
||||
def set_project_id(self, project_id):
|
||||
self._project_id = project_id
|
||||
|
||||
def router_list(self):
|
||||
return filter(self._owned_resource,
|
||||
self.client().list_routers()['routers'])
|
||||
|
||||
def router_interfaces_list(self, router):
|
||||
return self._client.list_ports(device_id=router['id'])['ports']
|
||||
|
||||
def port_list(self):
|
||||
return self.client().list_ports()['ports']
|
||||
|
||||
def network_list(self):
|
||||
return filter(self._owned_resource,
|
||||
self.client().list_networks()['networks'])
|
||||
|
||||
def secgroup_list(self):
|
||||
return filter(self._owned_resource,
|
||||
self.client().list_security_groups()['security_groups'])
|
||||
|
||||
def floatingip_list(self):
|
||||
return filter(self._owned_resource,
|
||||
self.client().list_floatingips()['floatingips'])
|
||||
|
||||
def subnet_list(self):
|
||||
return filter(self._owned_resource,
|
||||
self.client().list_subnets()['subnets'])
|
||||
|
||||
def _owned_resource(self, res):
|
||||
# Only considering resources owned by project
|
||||
return res['tenant_id'] == self._project_id
|
||||
|
||||
|
||||
class NovaManager(object):
|
||||
"""Manage nova resources."""
|
||||
_client = None
|
||||
|
||||
def __init__(self, keystone_mgr):
|
||||
self.keystone_mgr = keystone_mgr
|
||||
|
||||
def client(self):
|
||||
if not self._client:
|
||||
self._client = nova_client.Client(
|
||||
'2',
|
||||
self.keystone_mgr.username,
|
||||
self.keystone_mgr.auth_token,
|
||||
self.keystone_mgr.project,
|
||||
self.keystone_mgr.auth_url,
|
||||
region_name=self.keystone_mgr.region_name,
|
||||
insecure=self.keystone_mgr.insecure,
|
||||
endpoint_type=self.keystone_mgr.endpoint_type,
|
||||
auth_token=self.keystone_mgr.auth_token
|
||||
)
|
||||
return self._client
|
||||
|
||||
def set_client(self, client):
|
||||
self._client = client
|
||||
|
||||
def server_list(self):
|
||||
return self.client().servers.list()
|
||||
|
||||
def floating_ip_list(self):
|
||||
return self.client().floating_ips.list()
|
||||
|
||||
def flavor_list(self):
|
||||
return self.client().flavors.list()
|
||||
|
||||
def flavor_get(self, id):
|
||||
return self.client().flavors.get(id)
|
||||
|
||||
def keypair_list(self):
|
||||
return self.client().keypairs.list()
|
||||
|
||||
def keypair_show(self, keypair):
|
||||
return self.client().keypairs.get(keypair)
|
||||
|
||||
def server_security_group_list(self, server):
|
||||
return self.client().servers.list_security_group(server)
|
||||
|
||||
def servergroup_list(self):
|
||||
return self.client().server_groups.list(True)
|
||||
|
||||
|
||||
class CinderManager(object):
|
||||
"""Manage Cinder resources."""
|
||||
_client = None
|
||||
|
||||
def __init__(self, keystone_mgr):
|
||||
self.keystone_mgr = keystone_mgr
|
||||
self.defined = True
|
||||
|
||||
def client(self):
|
||||
if self.defined and not self._client:
|
||||
try:
|
||||
cinder_url = self.keystone_mgr.get_endpoint("volumev2")
|
||||
except KeyError:
|
||||
cinder_url = self.keystone_mgr.get_endpoint("volume")
|
||||
client = cinder_client.Client(
|
||||
self.keystone_mgr.username,
|
||||
self.keystone_mgr.auth_token,
|
||||
project_id=self.keystone_mgr.project,
|
||||
auth_url=cinder_url,
|
||||
http_log_debug=True,
|
||||
insecure=self.keystone_mgr.insecure
|
||||
)
|
||||
client.client.auth_token = self.keystone_mgr.auth_token
|
||||
client.client.management_url = cinder_url
|
||||
self._client = client
|
||||
return self._client
|
||||
|
||||
def set_client(self, client):
|
||||
self._client = client
|
||||
|
||||
def volume_list(self):
|
||||
volumes = []
|
||||
client = self.client()
|
||||
if client:
|
||||
for vol in client.volumes.list():
|
||||
volumes.append(client.volumes.get(vol.id))
|
||||
return volumes
|
||||
|
||||
def snapshot_list(self):
|
||||
client = self.client()
|
||||
return client.volume_snapshots.list() if client else []
|
574
flameclient/resources/__init__.py
Normal file
574
flameclient/resources/__init__.py
Normal file
@ -0,0 +1,574 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# This software is released under the MIT License.
|
||||
#
|
||||
# Copyright (c) 2018 Orange Cloud for Business / Cloudwatt
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
import abc
|
||||
import logging
|
||||
|
||||
import six
|
||||
from six.moves import UserDict
|
||||
|
||||
from flameclient.utils import camel_to_snake
|
||||
from flameclient.utils import ClassProperty
|
||||
from flameclient.utils import clean_dict
|
||||
from flameclient.utils import load_resource_entry_points
|
||||
from flameclient.utils import load_resource_modules
|
||||
from flameclient.utils import munchify
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class BaseHotResource(object):
|
||||
"""Describes a heat resource from parameters
|
||||
|
||||
:param ResourceManager manager:
|
||||
A ResourceManager instance.
|
||||
This instance is necessary to have access to the manager's
|
||||
openstack.connection.Connection instance
|
||||
|
||||
:param string type: The name of the openstack resource type.
|
||||
e.g.: "OS::Nova::Server" etc...
|
||||
|
||||
:param string id: The openstack resource id.
|
||||
|
||||
:param dict properties: The openstack resource properties.
|
||||
|
||||
"""
|
||||
|
||||
id = None
|
||||
manager = None
|
||||
parameters = None
|
||||
properties = None
|
||||
type = None
|
||||
|
||||
def __init__(self, manager, name, type=None, id=None, properties=None): # noqa pylint: disable=W0622
|
||||
if not isinstance(manager, ResourceManager):
|
||||
raise TypeError(
|
||||
"manager needs to be a flameclient.resources.ResourceManager "
|
||||
"instance. Received '%s' (%s) instead" % (
|
||||
manager, self.__type(manager)
|
||||
)
|
||||
)
|
||||
self.manager = manager
|
||||
self.name = name
|
||||
if type:
|
||||
self.type = type
|
||||
self.id = id
|
||||
self.status = 'COMPLETE'
|
||||
self.properties = properties or {}
|
||||
self.parameters = {}
|
||||
|
||||
@staticmethod
|
||||
def __type(*args, **kwargs):
|
||||
"""Needed to call the builtin type function when overriden"""
|
||||
return type(*args, **kwargs)
|
||||
|
||||
@property
|
||||
def connection(self):
|
||||
return self.manager.connection
|
||||
|
||||
@property
|
||||
def conn(self):
|
||||
return self.connection
|
||||
|
||||
@property
|
||||
def cloud(self):
|
||||
return self.manager.cloud
|
||||
|
||||
@property
|
||||
def generator(self):
|
||||
return self.manager.generator
|
||||
|
||||
@property
|
||||
def managers(self):
|
||||
return self.generator.managers
|
||||
|
||||
@property
|
||||
def api(self):
|
||||
return self.generator.api
|
||||
|
||||
@property
|
||||
def options(self):
|
||||
return self.generator.options
|
||||
|
||||
@property
|
||||
def kwargs(self):
|
||||
return self.manager.kwargs
|
||||
|
||||
def add_parameter(
|
||||
self, name, description, parameter_type='string', constraints=None,
|
||||
default=None
|
||||
):
|
||||
data = {
|
||||
'type': parameter_type,
|
||||
'description': description,
|
||||
}
|
||||
|
||||
if constraints and self.options.include_constraints:
|
||||
data['constraints'] = constraints
|
||||
if default:
|
||||
data['default'] = default
|
||||
|
||||
self.parameters[name] = data
|
||||
|
||||
@property
|
||||
def clean_properties(self):
|
||||
return clean_dict(self.properties)
|
||||
|
||||
@property
|
||||
def template_resource(self):
|
||||
return {
|
||||
self.name: {
|
||||
'type': self.type,
|
||||
'properties': self.clean_properties
|
||||
}
|
||||
}
|
||||
|
||||
@property
|
||||
def clean_parameters(self):
|
||||
return clean_dict(self.parameters)
|
||||
|
||||
@property
|
||||
def template_parameter(self):
|
||||
return self.parameters
|
||||
|
||||
@property
|
||||
def stack_resource(self):
|
||||
if self.id is None:
|
||||
return {}
|
||||
return {
|
||||
self.name: {
|
||||
'status': self.status,
|
||||
'name': self.name,
|
||||
'resource_data': {},
|
||||
'resource_id': self.id,
|
||||
'action': 'CREATE',
|
||||
'type': self.type,
|
||||
'metadata': {}
|
||||
}
|
||||
}
|
||||
|
||||
def generator_memoize(self, method, *args, **kwargs):
|
||||
return self.manager.generator_memoize(method, *args, **kwargs)
|
||||
|
||||
|
||||
@six.add_metaclass(abc.ABCMeta)
|
||||
class TypedHotResource(BaseHotResource):
|
||||
"""Describes a heat resource from parameters with predefined type
|
||||
|
||||
:param ResourceManager manager:
|
||||
A ResourceManager instance.
|
||||
This instance is necessary to have access to the manager's
|
||||
openstack.connection.Connection instance
|
||||
|
||||
:param string id: The openstack resource id.
|
||||
|
||||
:param dict properties: The openstack resource properties.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, manager, name, id=None, properties=None): # noqa pylint: disable=W0622
|
||||
super(TypedHotResource, self).__init__(
|
||||
manager, name, type=None, id=id, properties=properties
|
||||
)
|
||||
|
||||
@abc.abstractproperty
|
||||
def type(self): # pylint: disable=E0202
|
||||
"""The resource type
|
||||
|
||||
You need to set this property on subclasses.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
@six.add_metaclass(abc.ABCMeta)
|
||||
class AdvancedHotResource(TypedHotResource, UserDict):
|
||||
"""Describes a heat resource from openstack.resource.Resource instance
|
||||
|
||||
These advanced resources mays also have resources.
|
||||
|
||||
property_keys are properties to automatically extract from the resource.
|
||||
|
||||
:param ResourceManager manager:
|
||||
A ResourceManager instance.
|
||||
This instance is necessary to have access to the manager's
|
||||
openstack.connection.Connection instance
|
||||
|
||||
:param string name: The name of the openstack resource.
|
||||
e.g.: "My_server".
|
||||
|
||||
:param openstack.resource.Resource data:
|
||||
An `openstack.resource.Resource` instance or a munch.Munch instance
|
||||
representing the openstack resource returned by an openstack client or
|
||||
returned by an `openstack.connection.Connection` instance's API call
|
||||
method, or returned by a `shade.openstackcloud.OpenStackCloud`
|
||||
instance's API call method.
|
||||
|
||||
:param dict properties: The openstack resource properties.
|
||||
|
||||
When subclassing this class, the `property_keys` tuple represents
|
||||
property keys which will be automatically extracted from the resource,
|
||||
allowing you to not pass any properties.
|
||||
|
||||
Since we inheritate from UserDict, we have a direct access to `self.data`.
|
||||
More info here:
|
||||
https://docs.python.org/3/library/collections.html#userdict-objects
|
||||
The only difference is that we use a munch instead of dict for `self.data`
|
||||
This means we can access `self.data[key]` with `self[key]` (UserDict) and
|
||||
via `self.data.key` (munch).
|
||||
"""
|
||||
|
||||
property_keys = ()
|
||||
data = None
|
||||
|
||||
def __init__(self, manager, name, data, properties=None):
|
||||
|
||||
data = munchify(data)
|
||||
|
||||
final_properties = {}
|
||||
# Automatically get properties from self.property_keys
|
||||
for key in self.property_keys:
|
||||
final_properties[key] = data[key]
|
||||
# Override properties:
|
||||
if properties:
|
||||
final_properties.update(properties)
|
||||
|
||||
super(AdvancedHotResource, self).__init__(
|
||||
manager, name, id=data.get('id'),
|
||||
properties=final_properties
|
||||
)
|
||||
self.data = data
|
||||
|
||||
|
||||
@six.add_metaclass(abc.ABCMeta)
|
||||
class ResourceManager(object):
|
||||
"""Resource manager to list specific openstack resources
|
||||
|
||||
:param flameclient.flame.TemplateGenerator generator:
|
||||
A `flameclient.flame.TemplateGenerator` instance.
|
||||
|
||||
:param argparse.Namespace options:
|
||||
argparse options.
|
||||
|
||||
args and kwargs are extra parameters which each resource can access in case
|
||||
of developer needs.
|
||||
|
||||
This class needs to be subclassed. Every subclass which is imported will be
|
||||
discovered by `resources.get_manager_classes()`
|
||||
"""
|
||||
|
||||
generator = None
|
||||
args = ()
|
||||
kwargs = None
|
||||
|
||||
def __init__(self, generator, *args, **kwargs):
|
||||
self.generator = generator
|
||||
self.args = args
|
||||
self.kwargs = kwargs or {}
|
||||
|
||||
@ClassProperty
|
||||
def name(cls):
|
||||
"""The resource manager name
|
||||
|
||||
You need to set this property on subclasses if the automatic naming
|
||||
does not work.
|
||||
|
||||
ex.: If this class is calles FooBarsManager, this property will return
|
||||
'foo_bars'
|
||||
"""
|
||||
return camel_to_snake(cls.__name__).rstrip('_manager')
|
||||
|
||||
@ClassProperty
|
||||
def singular_name(cls):
|
||||
"""The resource manager singular name
|
||||
|
||||
You need to set this property on subclasses if the automatic naming
|
||||
does not work.
|
||||
|
||||
Override this if the singular of self.name does not consist in
|
||||
in removing the trailing 's'.
|
||||
"""
|
||||
return cls.name.rstrip('s')
|
||||
|
||||
@property
|
||||
def options(self):
|
||||
return self.generator.options
|
||||
|
||||
@property
|
||||
def connection(self):
|
||||
return self.generator.connection
|
||||
|
||||
@property
|
||||
def conn(self):
|
||||
"""Give a short name access"""
|
||||
return self.connection
|
||||
|
||||
@property
|
||||
def cloud(self):
|
||||
return self.generator.cloud
|
||||
|
||||
@property
|
||||
def managers(self):
|
||||
return self.generator.managers
|
||||
|
||||
@classmethod
|
||||
def add_arguments(cls, parser):
|
||||
"""Add parser argparse.ArgumentParser arguments
|
||||
|
||||
Use this method in your subclasses if you want to add any specific
|
||||
argparse arguments. These arguments will then be available on
|
||||
`self.options`.
|
||||
|
||||
:param argparse.ArgumentParser parser: An argparse.ArgumentParser
|
||||
instance
|
||||
|
||||
:returns: An argparse.ArgumentParser parser instance
|
||||
"""
|
||||
return parser
|
||||
|
||||
@abc.abstractproperty
|
||||
def api_resources(self):
|
||||
"""Implement this property to return api resources
|
||||
|
||||
This property will be automatically set as an attribute on
|
||||
`generator.api` and `self.api` with `self.name`.
|
||||
|
||||
e.g.: if this class has `self.name` set to 'routers', the
|
||||
`self.generator.api.routers` attribute and `self.api.routers`
|
||||
attribute will return the results of this property.
|
||||
|
||||
Consider using the `utils.memoized_property` decorator on the
|
||||
property. This is because this property should be computed only once
|
||||
It's the reason why it's a property and not a method.
|
||||
Also consider using self.generator_memoize on API calls.
|
||||
|
||||
This property should return a Munch instance generated by
|
||||
`utils.data_list_to_dict` on a list of `openstack.resource.Resource`
|
||||
instances in order to be consistent with all managers
|
||||
the result has to be in the following form:
|
||||
|
||||
Munch(
|
||||
{
|
||||
'some_id': Munch({}),
|
||||
'other_id': Munch{},
|
||||
}
|
||||
)
|
||||
|
||||
The `get_resource_name` expects to find a `.enum` attribute on
|
||||
each munch value. You will need to override `get_resource_name` if
|
||||
you have a different data format.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def get_api_resources(self):
|
||||
return self.api_resources
|
||||
|
||||
@property
|
||||
def api(self):
|
||||
"""Direct access to all managers' api resources
|
||||
|
||||
e.g.: if there is a FooManager (with FooManager.name = 'foo'),
|
||||
`self.api.foo` will give access to `FooManager.api_resources`
|
||||
if the current instance and a FooManager instance are in a ManagerList
|
||||
on a TemplateGenerator.
|
||||
|
||||
This allows access to each manager's api resources from any other
|
||||
manager.
|
||||
|
||||
For this to work it implies that TemplateGenerator.api is a
|
||||
DirectManagerApiResourceAccess instance.
|
||||
"""
|
||||
return self.generator.api
|
||||
|
||||
@abc.abstractmethod
|
||||
def get_hot_resources(self):
|
||||
"""Implement this method to return resources
|
||||
|
||||
You need to take into account `self.options.no_threads` and not use
|
||||
threads (e.g.: `concurrent.futures`, threading module, etc...) when it
|
||||
is True.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def get_resource_num(self, resource_id):
|
||||
return self.api_resources[resource_id].enum
|
||||
|
||||
def get_resource_name(self, resource_id):
|
||||
return '%s_%d' % (
|
||||
self.singular_name, self.get_resource_num(resource_id)
|
||||
)
|
||||
|
||||
def generator_memoize(self, method, *args, **kwargs):
|
||||
return self.generator.generator_memoize(method, *args, **kwargs)
|
||||
|
||||
@ClassProperty
|
||||
def post_priority(cls):
|
||||
return 100
|
||||
|
||||
def post_process(self):
|
||||
"""This method is called after get_hot_resources of all managers
|
||||
|
||||
Use this method to perform actions after processing.
|
||||
|
||||
This method will be called on all managers sorted by the order of
|
||||
their self.post_priority number.
|
||||
"""
|
||||
pass
|
||||
|
||||
def post_process_hot_resources(self, resources): # pylint: disable=R0201
|
||||
"""This method is called after get_hot_resources of all managers
|
||||
|
||||
Use this method to perform post processing resources modifications.
|
||||
|
||||
:param list resources: the self.generator.resources attribute after
|
||||
all managers' `get_hot_resources` methods have
|
||||
been called.
|
||||
:returns: A modified resources list (or a new resources list).
|
||||
A resources list is a list containing resources returned by
|
||||
each manager's `get_hot_resources` method.
|
||||
|
||||
This method will be called on all managers sorted by the order of
|
||||
their self.post_priority number.
|
||||
This allows you to modify the list aof resources returned by managers.
|
||||
"""
|
||||
return resources
|
||||
|
||||
def post_process_heat_template(self, template): # pylint: disable=R0201
|
||||
"""This method is called after get_hot_resources of all managers
|
||||
|
||||
Use this method to perform post processing template modifications.
|
||||
|
||||
:param dict template: the self.generator.template attribute after
|
||||
all managers' `get_hot_resources` methods have
|
||||
been called.
|
||||
:returns: The template dictionary which the generator will use to
|
||||
render the flame template. If ou need to create a blank
|
||||
template use `self.generator.get_new_template()` to
|
||||
initialise it.
|
||||
|
||||
|
||||
You need to return a heat template (in python dictionary format)
|
||||
This method will be called on all managers sorted by the order of
|
||||
their self.post_priority number.
|
||||
"""
|
||||
return template
|
||||
|
||||
def post_process_adoption_data(self, adoption_data): # noqa pylint: disable=R0201
|
||||
"""This method is called after get_hot_resources of all managers
|
||||
|
||||
Use this method to perform post processing adoption_data modifications.
|
||||
|
||||
:param dict adoption_data: the self.generator.adoption_data attribute
|
||||
after all managers' `get_hot_resources`
|
||||
methods have been called.
|
||||
:returns: The adoption_data dictionary which the generator will use to
|
||||
render the flame adoption data. If ou need to create a blank
|
||||
template use `self.generator.get_new_adoption_data()` to
|
||||
initialise it.
|
||||
|
||||
This method will be called on all managers sorted by the order of
|
||||
their self.post_priority number.
|
||||
"""
|
||||
return adoption_data
|
||||
|
||||
|
||||
class ManagerList(list):
|
||||
|
||||
def __getattr__(self, name):
|
||||
for manager in self:
|
||||
if manager.name == name:
|
||||
return manager
|
||||
raise AttributeError(
|
||||
"'%s' has no '%s' manager" % (
|
||||
self.__name__, name
|
||||
)
|
||||
)
|
||||
|
||||
def __setattr__(self, name, value):
|
||||
if isinstance(value, ResourceManager):
|
||||
if name != value.name:
|
||||
raise ValueError(
|
||||
"'%s'.name != '%s'" % (value, name)
|
||||
)
|
||||
self.append(value)
|
||||
raise TypeError(
|
||||
"'%s' '%s' has to be a ResourceManager instance instead of %s" % (
|
||||
value, name, type(value)
|
||||
)
|
||||
)
|
||||
|
||||
def __delattr__(self, name):
|
||||
for num, manager in enumerate(self):
|
||||
if manager.name == name:
|
||||
self.pop(num)
|
||||
raise AttributeError(
|
||||
"'%s' has no '%s' manager" % (
|
||||
self.__name__, name
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
class DirectManagerApiResourceAccess(object):
|
||||
"""Give direct access to a manager's api_resources attribute
|
||||
|
||||
|
||||
This needs to be set as the 'api' attribute on the TemplateGenerator
|
||||
class.
|
||||
"""
|
||||
|
||||
instance = None
|
||||
owner = None
|
||||
|
||||
def __get__(self, instance, owner):
|
||||
if instance:
|
||||
self.instance = instance
|
||||
self.owner = owner
|
||||
return self
|
||||
|
||||
def __getattr__(self, name):
|
||||
if self.instance:
|
||||
for manager in self.instance.managers:
|
||||
if manager.name == name:
|
||||
return manager.api_resources
|
||||
raise AttributeError(
|
||||
"'%s' has no '%s' manager in self.managers" % (
|
||||
self.owner.__name__, name
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def get_manager_classes():
|
||||
"""List all subclasses of ResourceManager
|
||||
|
||||
if any loaded python module contains a ResourceManager subclass, it will be
|
||||
discovered.
|
||||
Make sure to load any module containing the subclass if you want it to be
|
||||
discoverable.
|
||||
You can use `utils.load_resource_modules(dirname) or
|
||||
`utils.load_resource_entry_points(name='openstack_flame')` to load modules
|
||||
containing ResourceManager subclasses before using this method.
|
||||
"""
|
||||
load_resource_modules(__file__)
|
||||
load_resource_entry_points()
|
||||
return ResourceManager.__subclasses__()
|
54
flameclient/resources/flavors.py
Normal file
54
flameclient/resources/flavors.py
Normal file
@ -0,0 +1,54 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# This software is released under the MIT License.
|
||||
#
|
||||
# Copyright (c) 2018 Orange Cloud for Business / Cloudwatt
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
from flameclient import resources as base_resources
|
||||
from flameclient.utils import data_list_to_dict
|
||||
from flameclient.utils import memoized_property
|
||||
|
||||
|
||||
class FlavorsManager(base_resources.ResourceManager):
|
||||
"""Used only to provide api resources. Heat does not create flavors."""
|
||||
|
||||
@staticmethod
|
||||
def add_resource_flavor(resource):
|
||||
data = resource.data
|
||||
manager = resource.manager
|
||||
flavor_parameter_name = "%s_flavor" % resource.name
|
||||
description = "Flavor to use for %s %s" % (
|
||||
manager.singular_name, resource.name
|
||||
)
|
||||
default = data.flavor['id']
|
||||
resource.add_parameter(
|
||||
flavor_parameter_name, description, default=default
|
||||
)
|
||||
resource.properties['flavor'] = {'get_param': flavor_parameter_name}
|
||||
|
||||
@memoized_property
|
||||
def api_resources(self):
|
||||
return data_list_to_dict(
|
||||
self.generator_memoize(self.conn.compute.flavors)
|
||||
)
|
||||
|
||||
def get_hot_resources(self):
|
||||
return []
|
71
flameclient/resources/floatingips.py
Normal file
71
flameclient/resources/floatingips.py
Normal file
@ -0,0 +1,71 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# This software is released under the MIT License.
|
||||
#
|
||||
# Copyright (c) 2018 Orange Cloud for Business / Cloudwatt
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
import six
|
||||
|
||||
from flameclient import resources as base_resources
|
||||
from flameclient.utils import data_list_to_dict
|
||||
from flameclient.utils import memoized_property
|
||||
|
||||
|
||||
class FloatingIP(base_resources.AdvancedHotResource):
|
||||
type = 'OS::Neutron::FloatingIP'
|
||||
|
||||
def __init__(self, manager, name, floating_ip, properties=None):
|
||||
super(FloatingIP, self).__init__(
|
||||
manager, name, floating_ip, properties
|
||||
)
|
||||
net_param_name = "external_network_for_%s" % self.name
|
||||
self.properties['floating_network_id'] = {'get_param': net_param_name}
|
||||
description = "Network to allocate floating IP from"
|
||||
constraints = [{'custom_constraint': "neutron.network"}]
|
||||
default = self.data['floating_network_id']
|
||||
self.add_parameter(net_param_name, description,
|
||||
constraints=constraints,
|
||||
default=default)
|
||||
|
||||
@property
|
||||
def association(self):
|
||||
return self.managers.ports.get_fip_association(self) \
|
||||
or self.managers.servers.get_fip_association(self)
|
||||
|
||||
|
||||
class FloatingIpsManager(base_resources.ResourceManager):
|
||||
|
||||
@memoized_property
|
||||
def api_resources(self):
|
||||
return data_list_to_dict(
|
||||
self.generator_memoize(self.conn.network.ips)
|
||||
)
|
||||
|
||||
def get_hot_resources(self):
|
||||
floating_ips = [
|
||||
FloatingIP(self, self.get_resource_name(fip_id), floating_ip)
|
||||
for fip_id, floating_ip in six.iteritems(self.api.floating_ips)
|
||||
]
|
||||
floating_ip_associations = [
|
||||
fip.association for fip in floating_ips
|
||||
if fip.association
|
||||
]
|
||||
return floating_ips + floating_ip_associations
|
58
flameclient/resources/images.py
Normal file
58
flameclient/resources/images.py
Normal file
@ -0,0 +1,58 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# This software is released under the MIT License.
|
||||
#
|
||||
# Copyright (c) 2018 Orange Cloud for Business / Cloudwatt
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
from flameclient import resources as base_resources
|
||||
from flameclient.utils import data_list_to_dict
|
||||
from flameclient.utils import memoized_property
|
||||
|
||||
|
||||
class ImagesManager(base_resources.ResourceManager):
|
||||
"""Used only to provide api resources. Heat does not create images."""
|
||||
|
||||
@staticmethod
|
||||
def add_resource_image(resource):
|
||||
data = resource.data
|
||||
manager = resource.manager
|
||||
if data.image:
|
||||
image_parameter_name = "%s_image" % resource.name
|
||||
description = (
|
||||
"Image to use for %s %s" % (
|
||||
manager.singular_name, resource.name
|
||||
)
|
||||
)
|
||||
constraints = [{'custom_constraint': "glance.image"}]
|
||||
resource.add_parameter(image_parameter_name, description,
|
||||
default=data.image['id'],
|
||||
constraints=constraints)
|
||||
resource.properties['image'] = {'get_param': image_parameter_name}
|
||||
|
||||
@memoized_property
|
||||
def api_resources(self):
|
||||
return data_list_to_dict(
|
||||
# self.conn.compute.images gives detailed images
|
||||
self.generator_memoize(self.conn.image.images)
|
||||
)
|
||||
|
||||
def get_hot_resources(self):
|
||||
return []
|
85
flameclient/resources/key_pairs.py
Normal file
85
flameclient/resources/key_pairs.py
Normal file
@ -0,0 +1,85 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# This software is released under the MIT License.
|
||||
#
|
||||
# Copyright (c) 2018 Orange Cloud for Business / Cloudwatt
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
import six
|
||||
|
||||
from flameclient import resources as base_resources
|
||||
from flameclient.utils import data_list_to_dict
|
||||
from flameclient.utils import memoized_property
|
||||
|
||||
|
||||
class KeyPair(base_resources.AdvancedHotResource):
|
||||
type = 'OS::Nova::KeyPair'
|
||||
property_keys = ('name', 'public_key',)
|
||||
|
||||
|
||||
class KeypairsManager(base_resources.ResourceManager):
|
||||
|
||||
def add_resource_keypair(self, resource):
|
||||
data = resource.data
|
||||
manager = resource.manager
|
||||
|
||||
if data.key_name:
|
||||
if (
|
||||
self.options.exclude_keypairs or
|
||||
data.key_name not in self.api.keypairs
|
||||
):
|
||||
key_parameter_name = "%s_key" % resource.name
|
||||
description = (
|
||||
"Key for %s %s" % (manager.singular_name, resource.name)
|
||||
|
||||
)
|
||||
constraints = [{'custom_constraint': "nova.keypair"}]
|
||||
resource.add_parameter(key_parameter_name, description,
|
||||
default=data.key_name,
|
||||
constraints=constraints)
|
||||
resource.properties['key_name'] = {
|
||||
'get_param': key_parameter_name
|
||||
}
|
||||
else:
|
||||
resource.properties['key_name'] = {
|
||||
'get_resource': self.get_resource_name(data.key_name)
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def add_arguments(cls, parser):
|
||||
parser.add_argument('--exclude-keypairs', action='store_true',
|
||||
default=False,
|
||||
help="Do not export key pair resources."
|
||||
)
|
||||
return parser
|
||||
|
||||
@memoized_property
|
||||
def api_resources(self):
|
||||
return data_list_to_dict(
|
||||
self.generator_memoize(self.conn.compute.keypairs)
|
||||
)
|
||||
|
||||
def get_hot_resources(self):
|
||||
if not self.options.exclude_keypairs:
|
||||
return [
|
||||
KeyPair(self, self.get_resource_name(resource.id), resource)
|
||||
for resource in six.itervalues(self.api.keypairs)
|
||||
]
|
||||
return []
|
90
flameclient/resources/networks.py
Normal file
90
flameclient/resources/networks.py
Normal file
@ -0,0 +1,90 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# This software is released under the MIT License.
|
||||
#
|
||||
# Copyright (c) 2018 Orange Cloud for Business / Cloudwatt
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
import six
|
||||
|
||||
import netaddr
|
||||
|
||||
from flameclient import resources as base_resources
|
||||
from flameclient.utils import data_list_to_dict
|
||||
from flameclient.utils import memoized_property
|
||||
|
||||
|
||||
class Network(base_resources.AdvancedHotResource):
|
||||
type = 'OS::Neutron::Net'
|
||||
property_keys = ('name', 'admin_state_up', 'shared')
|
||||
|
||||
|
||||
class NetworksManager(base_resources.ResourceManager):
|
||||
|
||||
def add_resource_networks(self, resource):
|
||||
addresses = resource.data.addresses
|
||||
networks = []
|
||||
for net_name in addresses:
|
||||
ip = addresses[net_name][0]['addr']
|
||||
for subnet in six.itervalues(self.api.subnets):
|
||||
if netaddr.IPAddress(ip) in netaddr.IPNetwork(subnet['cidr']):
|
||||
for network in six.itervalues(self.api.networks):
|
||||
if (network['name'] == net_name and
|
||||
network['id'] == subnet['network_id']):
|
||||
net = self.get_resource_name(subnet['network_id'])
|
||||
networks.append({'network': {'get_resource': net}})
|
||||
if networks:
|
||||
resource.properties['networks'] = networks
|
||||
|
||||
@memoized_property
|
||||
def all_networks(self):
|
||||
return data_list_to_dict(
|
||||
self.generator_memoize(self.conn.network.networks)
|
||||
)
|
||||
|
||||
@property
|
||||
def api_resources(self):
|
||||
return self.all_networks
|
||||
|
||||
@memoized_property
|
||||
def external_networks(self):
|
||||
return data_list_to_dict(
|
||||
(
|
||||
network for network in six.itervalues(self.all_networks)
|
||||
if network['router:external']
|
||||
),
|
||||
enum=False # Do not overwrite enumeration done in all_networks
|
||||
)
|
||||
|
||||
@memoized_property
|
||||
def internal_networks(self):
|
||||
return data_list_to_dict(
|
||||
(
|
||||
network for network in six.itervalues(self.all_networks)
|
||||
if network.id not in self.external_networks
|
||||
),
|
||||
enum=False # Do not overwrite enumeration done in all_networks
|
||||
)
|
||||
|
||||
def get_hot_resources(self):
|
||||
return [
|
||||
Network(self, self.get_resource_name(network.id), network)
|
||||
for network in six.itervalues(self.internal_networks)
|
||||
]
|
137
flameclient/resources/ports.py
Normal file
137
flameclient/resources/ports.py
Normal file
@ -0,0 +1,137 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# This software is released under the MIT License.
|
||||
#
|
||||
# Copyright (c) 2018 Orange Cloud for Business / Cloudwatt
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
import six
|
||||
|
||||
from flameclient import resources as base_resources
|
||||
from flameclient.utils import data_list_to_dict
|
||||
from flameclient.utils import memoized_property
|
||||
|
||||
|
||||
class Port(base_resources.AdvancedHotResource):
|
||||
type = 'OS::Neutron::Port'
|
||||
property_keys = ('admin_state_up', 'mac_address', 'device_owner')
|
||||
|
||||
def __init__(self, manager, name, port, properties=None):
|
||||
super(Port, self).__init__(manager, name, port, properties)
|
||||
|
||||
fixed_ips = []
|
||||
|
||||
for fixed_ip_dict in port['fixed_ips']:
|
||||
subnet_id = fixed_ip_dict['subnet_id']
|
||||
subnet_resource_name = self.managers.subnets.get_resource_name(
|
||||
subnet_id
|
||||
)
|
||||
fixed_ip_resource = {
|
||||
u'subnet_id': {'get_resource': subnet_resource_name},
|
||||
u'ip_address': fixed_ip_dict['ip_address']
|
||||
}
|
||||
fixed_ips.append(fixed_ip_resource)
|
||||
|
||||
net_resource_name = self.managers.networks.get_resource_name(
|
||||
port['network_id']
|
||||
)
|
||||
self.properties.update(
|
||||
{'network_id': {'get_resource': net_resource_name},
|
||||
'fixed_ips': fixed_ips}
|
||||
)
|
||||
if port['name'] != '':
|
||||
# This port has a name
|
||||
self.properties['name'] = port['name']
|
||||
|
||||
self.managers.security_groups.add_resource_secgrp_props_and_params(
|
||||
self
|
||||
)
|
||||
|
||||
|
||||
class NeutronFloatingIpAssociation(base_resources.TypedHotResource):
|
||||
type = 'OS::Neutron::FloatingIPAssociation'
|
||||
|
||||
|
||||
class PortsManager(base_resources.ResourceManager):
|
||||
|
||||
def get_fip_association(self, resource):
|
||||
ip = resource.data
|
||||
manager = resource.manager
|
||||
if ip['port_id'] and self.options.extract_ports:
|
||||
port_resource_name = self.get_resource_name(ip['port_id'])
|
||||
properties = {
|
||||
'floatingip_id': {'get_resource': resource.name},
|
||||
'port_id': {'get_resource': port_resource_name}
|
||||
}
|
||||
resource_num = manager.get_resource_num(resource.id)
|
||||
fip_assoc_id = ("%s:%s" % (ip['id'], ip['port_id']))
|
||||
return NeutronFloatingIpAssociation(
|
||||
manager,
|
||||
"floatingip_association_%d" % resource_num,
|
||||
fip_assoc_id,
|
||||
properties
|
||||
)
|
||||
|
||||
def get_ports_for_resource(self, resource):
|
||||
ports = []
|
||||
for port in six.itervalues(self.api.ports):
|
||||
if port['device_id'] == resource.data.id:
|
||||
ports.append(self.get_resource_name(port.id))
|
||||
return ports
|
||||
|
||||
def add_resource_ports_or_secgroups_and_networks(self, resource):
|
||||
if self.options.extract_ports:
|
||||
ports = [{"port": {"get_resource": port}}
|
||||
for port in self.get_ports_for_resource(resource)]
|
||||
if ports:
|
||||
resource.properties['networks'] = ports
|
||||
else:
|
||||
self.managers.security_groups \
|
||||
.add_resource_secgrp_props_and_params(resource)
|
||||
|
||||
self.managers.networks.add_resource_networks(resource)
|
||||
|
||||
@classmethod
|
||||
def add_arguments(cls, parser):
|
||||
parser.add_argument('--extract-ports', action='store_true',
|
||||
default=False,
|
||||
help="Export the tenant network ports.")
|
||||
return parser
|
||||
|
||||
@memoized_property
|
||||
def api_resources(self):
|
||||
return data_list_to_dict(
|
||||
self.generator_memoize(self.conn.network.ports)
|
||||
)
|
||||
|
||||
@memoized_property
|
||||
def port_resources(self):
|
||||
return [
|
||||
Port(self, self.get_resource_name(port.id), port)
|
||||
for port in six.itervalues(self.api.ports)
|
||||
]
|
||||
|
||||
def get_hot_resources(self):
|
||||
if self.options.extract_ports:
|
||||
return [
|
||||
port for port in self.port_resources
|
||||
if port['device_owner'].startswith('compute:')
|
||||
]
|
||||
return []
|
112
flameclient/resources/routers.py
Normal file
112
flameclient/resources/routers.py
Normal file
@ -0,0 +1,112 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# This software is released under the MIT License.
|
||||
#
|
||||
# Copyright (c) 2018 Orange Cloud for Business / Cloudwatt
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
import six
|
||||
|
||||
from flameclient import resources as base_resources
|
||||
from flameclient.utils import data_list_to_dict
|
||||
from flameclient.utils import memoized_property
|
||||
from flameclient.utils import munchify
|
||||
|
||||
|
||||
class RouterInterface(base_resources.TypedHotResource):
|
||||
type = 'OS::Neutron::RouterInterface'
|
||||
|
||||
|
||||
class RouterGateway(base_resources.TypedHotResource):
|
||||
type = 'OS::Neutron::RouterGateway'
|
||||
|
||||
|
||||
class Router(base_resources.AdvancedHotResource):
|
||||
type = 'OS::Neutron::Router'
|
||||
property_keys = ('name', 'admin_state_up')
|
||||
|
||||
@memoized_property
|
||||
def os_ports(self):
|
||||
return munchify(self.generator_memoize(
|
||||
self.conn.network.ports, device_id=self['id']
|
||||
))
|
||||
|
||||
@memoized_property
|
||||
def router_interfaces(self):
|
||||
router_interfaces = []
|
||||
for n, port in enumerate(self.os_ports):
|
||||
if port['device_owner'] != "network:router_interface":
|
||||
continue
|
||||
resource_name = "%s_interface_%d" % (self.name, n)
|
||||
subnet_resource_name = self.managers.subnets.get_resource_name(
|
||||
port['fixed_ips'][0]['subnet_id']
|
||||
)
|
||||
resource_id = ("%s:subnet_id=%s" %
|
||||
(port['device_id'],
|
||||
port['fixed_ips'][0]['subnet_id']))
|
||||
properties = {
|
||||
'subnet_id': {'get_resource': subnet_resource_name},
|
||||
'router_id': {'get_resource': self.name}
|
||||
}
|
||||
router_interfaces.append(
|
||||
RouterInterface(
|
||||
self.manager, resource_name, resource_id, properties)
|
||||
)
|
||||
return router_interfaces
|
||||
|
||||
@memoized_property
|
||||
def router_gateway(self):
|
||||
if self['external_gateway_info']:
|
||||
router_external_network_name = ("%s_external_network" % self.name)
|
||||
external_network = self['external_gateway_info']['network_id']
|
||||
properties = {
|
||||
'router_id': {'get_resource': self.name},
|
||||
'network_id': {'get_param': router_external_network_name}
|
||||
}
|
||||
gateway = RouterGateway(self.manager, "%s_gateway" % self.name,
|
||||
"%s:%s" % (self['id'], external_network),
|
||||
properties)
|
||||
description = "Router external network"
|
||||
constraints = [{'custom_constraint': "neutron.network"}]
|
||||
gateway.add_parameter(router_external_network_name, description,
|
||||
constraints=constraints,
|
||||
default=external_network)
|
||||
return gateway
|
||||
|
||||
|
||||
class RoutersManager(base_resources.ResourceManager):
|
||||
|
||||
@memoized_property
|
||||
def api_resources(self):
|
||||
return data_list_to_dict(
|
||||
self.generator_memoize(self.conn.network.routers)
|
||||
)
|
||||
|
||||
routers = api_resources
|
||||
|
||||
def get_hot_resources(self):
|
||||
resources = []
|
||||
for rid, router in six.iteritems(self.api.routers):
|
||||
resource = Router(self, self.get_resource_name(rid), router)
|
||||
resources.append(resource)
|
||||
resources.extend(resource.router_interfaces)
|
||||
if resource.router_gateway:
|
||||
resources.append(resource.router_gateway)
|
||||
return resources
|
175
flameclient/resources/security_groups.py
Normal file
175
flameclient/resources/security_groups.py
Normal file
@ -0,0 +1,175 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# This software is released under the MIT License.
|
||||
#
|
||||
# Copyright (c) 2018 Orange Cloud for Business / Cloudwatt
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
from copy import deepcopy
|
||||
import six
|
||||
|
||||
from flameclient import collections_abc
|
||||
from flameclient import resources as base_resources
|
||||
from flameclient.utils import clean_dict
|
||||
from flameclient.utils import data_list_to_dict
|
||||
from flameclient.utils import memoized_property
|
||||
|
||||
|
||||
class SecurityGroup(base_resources.AdvancedHotResource):
|
||||
type = 'OS::Neutron::SecurityGroup'
|
||||
property_keys = ('description',)
|
||||
|
||||
def __init__(self, manager, name, data, properties=None):
|
||||
super(SecurityGroup, self).__init__(
|
||||
manager, name, data, properties
|
||||
)
|
||||
if data['name'] == 'default':
|
||||
self.properties['name'] = '_default'
|
||||
else:
|
||||
self.properties['name'] = data['name']
|
||||
|
||||
self.properties['rules'] = self._build_rules(
|
||||
data['security_group_rules']
|
||||
)
|
||||
|
||||
def _build_rules(self, original_rules):
|
||||
final_rules = []
|
||||
for rule in original_rules:
|
||||
new_rule = deepcopy(rule)
|
||||
if new_rule['protocol'] == 'any':
|
||||
del new_rule['protocol']
|
||||
del new_rule['port_range_min']
|
||||
del new_rule['port_range_max']
|
||||
rg_id = new_rule['remote_group_id']
|
||||
if rg_id is not None:
|
||||
new_rule['remote_mode'] = "remote_group_id"
|
||||
resource_name = self.manager.get_resource_name(rg_id)
|
||||
if rg_id == new_rule['security_group_id']:
|
||||
del new_rule['remote_group_id']
|
||||
else:
|
||||
new_rule['remote_group_id'] = {
|
||||
'get_resource': resource_name
|
||||
}
|
||||
del new_rule['tenant_id']
|
||||
del new_rule['id']
|
||||
del new_rule['security_group_id']
|
||||
final_rule = clean_dict(new_rule, clean_list=False)
|
||||
final_rules.append(final_rule)
|
||||
return final_rules
|
||||
|
||||
|
||||
class SecurityGroupsManager(base_resources.ResourceManager):
|
||||
|
||||
@classmethod
|
||||
def add_arguments(cls, parser):
|
||||
parser.add_argument('--exclude-secgroups', action='store_true',
|
||||
default=False,
|
||||
help="Do not export the security group resources.")
|
||||
return parser
|
||||
|
||||
@memoized_property
|
||||
def api_resources(self):
|
||||
return data_list_to_dict(
|
||||
self.generator_memoize(self.conn.network.security_groups)
|
||||
)
|
||||
|
||||
def get_security_group(self, name_or_id):
|
||||
if isinstance(name_or_id, six.string_types):
|
||||
try:
|
||||
return self.api_resources[name_or_id]
|
||||
except KeyError:
|
||||
for sg in six.itervalues(self.api_resources):
|
||||
if name_or_id == sg.name:
|
||||
return sg
|
||||
raise ValueError(
|
||||
"No security group with '%s' id or name found"
|
||||
)
|
||||
elif isinstance(name_or_id, collections_abc.Mapping):
|
||||
if 'id' in name_or_id:
|
||||
return self.get_security_group(name_or_id['id'])
|
||||
elif 'name' in name_or_id:
|
||||
return self.get_security_group(name_or_id['name'])
|
||||
else:
|
||||
raise KeyError(
|
||||
"%s has no 'id' or 'name' key" % name_or_id
|
||||
)
|
||||
else:
|
||||
raise ValueError(
|
||||
"%s has to be a string or dict with 'id' or 'name' key."
|
||||
)
|
||||
|
||||
def get_resource_secgroups(self, resource):
|
||||
return [
|
||||
self.get_security_group(sg)
|
||||
for sg in resource.data.security_groups
|
||||
]
|
||||
|
||||
def add_resource_secgrp_props_and_params(self, resource):
|
||||
"""Add security group properties and parameters to a resource
|
||||
|
||||
:param BaseHotResource resource: a BaseHotResource (or subclass)
|
||||
instance
|
||||
|
||||
"""
|
||||
if not self.options.exclude_secgroups:
|
||||
|
||||
manager = resource.manager
|
||||
|
||||
data = resource.data
|
||||
security_groups = []
|
||||
|
||||
secgroup_default_parameter = None
|
||||
for secgr in self.get_resource_secgroups(resource):
|
||||
if secgr['name'] == 'default' and \
|
||||
self.options.generate_adoption_data:
|
||||
if not secgroup_default_parameter:
|
||||
res_name = manager.get_resource_name(data['id'])
|
||||
param_name = "%s_default_security_group" % res_name
|
||||
description = (
|
||||
"Default security group for %s %s" % (
|
||||
manager.singular_name, resource['name']
|
||||
)
|
||||
)
|
||||
default = secgr['id']
|
||||
resource.add_parameter(
|
||||
param_name, description, default=default
|
||||
)
|
||||
secgroup_default_parameter = {'get_param': param_name}
|
||||
security_groups.append(secgroup_default_parameter)
|
||||
else:
|
||||
resource_name = self.get_resource_name(secgr['id'])
|
||||
security_groups.append({'get_resource': resource_name})
|
||||
|
||||
if security_groups:
|
||||
resource.properties['security_groups'] = security_groups
|
||||
|
||||
def get_hot_resources(self):
|
||||
resources = []
|
||||
if not self.options.exclude_secgroups:
|
||||
for secgroup in six.itervalues(self.api.security_groups):
|
||||
if secgroup['name'] == 'default' \
|
||||
and self.options.generate_adoption_data:
|
||||
continue
|
||||
resources.append(
|
||||
SecurityGroup(
|
||||
self, self.get_resource_name(secgroup.id), secgroup
|
||||
)
|
||||
)
|
||||
return resources
|
61
flameclient/resources/server_groups.py
Normal file
61
flameclient/resources/server_groups.py
Normal file
@ -0,0 +1,61 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# This software is released under the MIT License.
|
||||
#
|
||||
# Copyright (c) 2018 Orange Cloud for Business / Cloudwatt
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
import six
|
||||
|
||||
from flameclient import resources as base_resources
|
||||
from flameclient.utils import data_list_to_dict
|
||||
from flameclient.utils import memoized_property
|
||||
|
||||
|
||||
class ServerGroup(base_resources.AdvancedHotResource):
|
||||
type = 'OS::Nova::ServerGroup'
|
||||
property_keys = ('name', 'policies')
|
||||
|
||||
|
||||
class ServerGroupsManager(base_resources.ResourceManager):
|
||||
|
||||
def add_resource_server_groups(self, resource):
|
||||
server = resource.data
|
||||
for servergroup in self.api_resources.values():
|
||||
if server.id in servergroup.members:
|
||||
hint = {
|
||||
'group': {
|
||||
'get_resource':
|
||||
self.get_resource_name(servergroup.id)
|
||||
}
|
||||
}
|
||||
resource.properties['scheduler_hints'] = hint
|
||||
|
||||
@memoized_property
|
||||
def api_resources(self):
|
||||
return data_list_to_dict(
|
||||
self.generator_memoize(self.conn.compute.server_groups)
|
||||
)
|
||||
|
||||
def get_hot_resources(self):
|
||||
return [
|
||||
ServerGroup(self, self.get_resource_name(sg.id), sg)
|
||||
for sg in six.itervalues(self.api_resources)
|
||||
]
|
93
flameclient/resources/servers.py
Normal file
93
flameclient/resources/servers.py
Normal file
@ -0,0 +1,93 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# This software is released under the MIT License.
|
||||
#
|
||||
# Copyright (c) 2018 Orange Cloud for Business / Cloudwatt
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
import six
|
||||
|
||||
from flameclient import resources as base_resources
|
||||
from flameclient.utils import data_list_to_dict
|
||||
from flameclient.utils import memoized_property
|
||||
|
||||
|
||||
class Server(base_resources.AdvancedHotResource):
|
||||
type = 'OS::Nova::Server'
|
||||
property_keys = ('name',)
|
||||
|
||||
def __init__(self, manager, name, server, properties=None):
|
||||
super(Server, self).__init__(manager, name, server, properties)
|
||||
for property_name in ('config_drive', 'metadata'):
|
||||
if server[property_name]:
|
||||
self.properties[property_name] = server[property_name]
|
||||
self.managers.flavors.add_resource_flavor(self)
|
||||
self.managers.images.add_resource_image(self)
|
||||
self.managers.keypairs.add_resource_keypair(self)
|
||||
self.managers.ports.add_resource_ports_or_secgroups_and_networks(self)
|
||||
self.managers.volumes.add_resource_attached_volumes(self)
|
||||
self.managers.server_groups.add_resource_server_groups(self)
|
||||
|
||||
|
||||
class NovaFloatingIpAssociation(base_resources.TypedHotResource):
|
||||
type = 'OS::Nova::FloatingIPAssociation'
|
||||
|
||||
|
||||
class ServersManager(base_resources.ResourceManager):
|
||||
|
||||
def get_fip_association(self, resource):
|
||||
ip = resource.data
|
||||
manager = resource.manager
|
||||
if not self.options.exclude_servers and ip['port_id']:
|
||||
server_id = self.api.ports[ip['port_id']]['device_id']
|
||||
if server_id and server_id in self.api.servers:
|
||||
server_resource_name = self.get_resource_name(server_id)
|
||||
resource_num = manager.get_resource_num(resource.id)
|
||||
properties = {
|
||||
'floating_ip': {'get_resource': resource.name},
|
||||
'server_id': {'get_resource': server_resource_name}
|
||||
}
|
||||
return NovaFloatingIpAssociation(
|
||||
manager,
|
||||
"floatingip_association_%d" % resource_num,
|
||||
None,
|
||||
properties
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def add_arguments(cls, parser):
|
||||
parser.add_argument('--exclude-servers', action='store_true',
|
||||
default=False,
|
||||
help="Do not export in template server resources.")
|
||||
return parser
|
||||
|
||||
@memoized_property
|
||||
def api_resources(self):
|
||||
return data_list_to_dict(
|
||||
self.generator_memoize(self.conn.compute.servers)
|
||||
)
|
||||
|
||||
def get_hot_resources(self):
|
||||
if not self.options.exclude_servers:
|
||||
return [
|
||||
Server(self, self.get_resource_name(server.id), server)
|
||||
for server in six.itervalues(self.api.servers)
|
||||
]
|
||||
return []
|
63
flameclient/resources/subnets.py
Normal file
63
flameclient/resources/subnets.py
Normal file
@ -0,0 +1,63 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# This software is released under the MIT License.
|
||||
#
|
||||
# Copyright (c) 2018 Orange Cloud for Business / Cloudwatt
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
import six
|
||||
|
||||
from flameclient import resources as base_resources
|
||||
from flameclient.utils import data_list_to_dict
|
||||
from flameclient.utils import memoized_property
|
||||
|
||||
|
||||
class Subnet(base_resources.AdvancedHotResource):
|
||||
type = 'OS::Neutron::Subnet'
|
||||
property_keys = (
|
||||
'name',
|
||||
'allocation_pools',
|
||||
'cidr',
|
||||
'dns_nameservers',
|
||||
'enable_dhcp',
|
||||
'host_routes',
|
||||
'ip_version',
|
||||
)
|
||||
|
||||
def __init__(self, manager, name, data, properties=None):
|
||||
super(Subnet, self).__init__(manager, name, data, properties)
|
||||
net_name = self.managers.networks.get_resource_name(self['network_id'])
|
||||
self.properties['network_id'] = {'get_resource': net_name}
|
||||
|
||||
|
||||
class SubnetsManager(base_resources.ResourceManager):
|
||||
|
||||
@memoized_property
|
||||
def api_resources(self):
|
||||
return data_list_to_dict(
|
||||
self.generator_memoize(self.conn.network.subnets)
|
||||
)
|
||||
|
||||
def get_hot_resources(self):
|
||||
return [
|
||||
Subnet(self, self.get_resource_name(subnet.id), subnet)
|
||||
for subnet in six.itervalues(self.api.subnets)
|
||||
if subnet['network_id'] in self.managers.networks.internal_networks
|
||||
]
|
158
flameclient/resources/volumes.py
Normal file
158
flameclient/resources/volumes.py
Normal file
@ -0,0 +1,158 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# This software is released under the MIT License.
|
||||
#
|
||||
# Copyright (c) 2018 Orange Cloud for Business / Cloudwatt
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
import six
|
||||
|
||||
from flameclient import resources as base_resources
|
||||
from flameclient.utils import data_list_to_dict
|
||||
from flameclient.utils import memoized_property
|
||||
|
||||
|
||||
class Volume(base_resources.AdvancedHotResource):
|
||||
type = 'OS::Cinder::Volume'
|
||||
property_keys = ('size', 'name')
|
||||
|
||||
def _add_source_volume(self):
|
||||
volume = self.data
|
||||
if volume.source_volid:
|
||||
if volume.source_volid in self.api.volumes:
|
||||
key = self.manager.get_resource_name(volume.source_volid)
|
||||
self.properties['source_volid'] = {'get_resource': key}
|
||||
else:
|
||||
key = "%s_source_volid" % self.name
|
||||
description = (
|
||||
"Volume to create volume %s from" % self.name)
|
||||
self.add_parameter(key, description)
|
||||
self.properties['source_volid'] = {'get_param': key}
|
||||
|
||||
def _add_image(self):
|
||||
volume = self.data
|
||||
if volume.bootable and not volume.snapshot_id:
|
||||
key = "%s_image" % self.name
|
||||
description = "Image to create volume %s from" % self.name
|
||||
constraints = [{'custom_constraint': "glance.image"}]
|
||||
default = volume.volume_image_metadata['image_id']
|
||||
self.add_parameter(key, description,
|
||||
constraints=constraints,
|
||||
default=default)
|
||||
self.properties['image'] = {'get_param': key}
|
||||
|
||||
def _add_snapshot(self):
|
||||
volume = self.data
|
||||
if volume.snapshot_id:
|
||||
key = "%s_snapshot_id" % self.name
|
||||
self.properties['snapshot_id'] = {'get_param': key}
|
||||
description = (
|
||||
"Snapshot to create volume %s from" % self.name)
|
||||
self.add_parameter(key, description,
|
||||
default=volume.snapshot_id)
|
||||
|
||||
def _add_display_name(self):
|
||||
volume = self.data
|
||||
if hasattr(volume, 'display_name') and volume.display_name:
|
||||
self.properties['name'] = volume.display_name
|
||||
|
||||
def _add_display_description(self):
|
||||
volume = self.data
|
||||
if (
|
||||
hasattr(volume, 'display_description') and
|
||||
volume.display_description
|
||||
):
|
||||
self.properties['description'] = volume.display_description
|
||||
|
||||
def _add_volume_type(self):
|
||||
volume = self.data
|
||||
if volume.volume_type and volume.volume_type != 'None':
|
||||
key = "%s_volume_type" % self.name
|
||||
description = (
|
||||
"Volume type for volume %s" % self.name)
|
||||
default = volume.volume_type
|
||||
self.add_parameter(key, description, default=default)
|
||||
self.properties['volume_type'] = {'get_param': key}
|
||||
|
||||
def _add_metadata(self):
|
||||
volume = self.data
|
||||
if volume.metadata:
|
||||
self.properties['metadata'] = volume.metadata
|
||||
|
||||
def __init__(self, manager, name, volume, properties=None):
|
||||
super(Volume, self).__init__(manager, name, volume, properties)
|
||||
self._add_source_volume()
|
||||
self._add_image()
|
||||
self._add_display_name()
|
||||
self._add_display_description()
|
||||
self._add_volume_type()
|
||||
self._add_metadata()
|
||||
|
||||
|
||||
class VolumesManager(base_resources.ResourceManager):
|
||||
|
||||
def add_resource_attached_volumes(self, resource):
|
||||
server = resource.data
|
||||
manager = resource.manager
|
||||
server_volumes = []
|
||||
att_key = 'os-extended-volumes:volumes_attached'
|
||||
for server_volume in server[att_key]:
|
||||
volume = self.api.volumes[server_volume['id']]
|
||||
volume_resource_name = self.get_resource_name(server_volume['id'])
|
||||
device = volume.attachments[0]['device']
|
||||
if not self.options.exclude_volumes:
|
||||
server_volumes.append(
|
||||
{'volume_id': {'get_resource': volume_resource_name},
|
||||
'device_name': device})
|
||||
else:
|
||||
volume_parameter_name = ("volume_%s_%d" %
|
||||
(server.name, volume.enum))
|
||||
description = ("Volume for %s %s, device %s" %
|
||||
(manager.singular_name, server.name, device))
|
||||
server_volumes.append(
|
||||
{'volume_id': {'get_param': volume_parameter_name},
|
||||
'device_name': device})
|
||||
resource.add_parameter(volume_parameter_name, description,
|
||||
default=server_volume['id'])
|
||||
if server_volumes:
|
||||
# block_device_mapping_v2 is the new way of associating
|
||||
# block devices to an instance
|
||||
resource.properties['block_device_mapping_v2'] = server_volumes
|
||||
|
||||
@classmethod
|
||||
def add_arguments(cls, parser):
|
||||
parser.add_argument('--exclude-volumes', action='store_true',
|
||||
default=False,
|
||||
help="Do not export volume resources.")
|
||||
return parser
|
||||
|
||||
@memoized_property
|
||||
def api_resources(self):
|
||||
return data_list_to_dict(
|
||||
self.generator_memoize(self.conn.volume.volumes)
|
||||
)
|
||||
|
||||
def get_hot_resources(self):
|
||||
if not self.options.exclude_volumes:
|
||||
return [
|
||||
Volume(self, self.get_resource_name(volume.id), volume)
|
||||
for volume in six.itervalues(self.api.volumes)
|
||||
]
|
||||
return []
|
278
flameclient/session.py
Normal file
278
flameclient/session.py
Normal file
@ -0,0 +1,278 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# This software is released under the MIT License.
|
||||
#
|
||||
# Copyright (c) 2018 Orange Cloud for Business / Cloudwatt
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
import argparse
|
||||
import logging
|
||||
import sys
|
||||
|
||||
from keystoneauth1 import loading
|
||||
from keystoneauth1 import session as keystone_session
|
||||
from openstack import connection as os_connection
|
||||
# We get a subclass of openstack.config.loader.OpenStackConfig which is more
|
||||
# complete:
|
||||
from os_client_config.config import OpenStackConfig # noqa
|
||||
from shade.openstackcloud import OpenStackCloud # noqa
|
||||
|
||||
from flameclient import utils
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def list_auth_types():
|
||||
return [loader for loader in loading.get_available_plugin_loaders()]
|
||||
|
||||
|
||||
def get_loader(auth_type):
|
||||
if auth_type not in list_auth_types():
|
||||
raise ValueError(
|
||||
"'auth_type' has to be one of %s (received %s)" % (
|
||||
list_auth_types(), auth_type
|
||||
)
|
||||
)
|
||||
return loading.get_plugin_loader(auth_type)
|
||||
|
||||
|
||||
def extract_loader_kwargs(loader, **kwargs):
|
||||
"""Get keystoneauth1.loading.get_plugin_loader's auth kwargs
|
||||
|
||||
Return the specific auth kwargs and remaining kwargs
|
||||
"""
|
||||
loader_keys = [option.dest for option in loader.get_options()]
|
||||
loader_kwargs = {
|
||||
key: kwargs[key] for key in loader_keys if key in kwargs
|
||||
}
|
||||
remaining_kwargs = {
|
||||
key: kwargs[key] for key in kwargs if key not in loader_keys
|
||||
}
|
||||
return loader_kwargs, remaining_kwargs
|
||||
|
||||
|
||||
def get_openstack_config_with_envvars(
|
||||
parser, config=None, load_envvars=False, load_yaml_config=False
|
||||
):
|
||||
"""Add openstack_options to argparse.ArgumentParser
|
||||
|
||||
:param argparse.ArgumentParser parser: argparse.ArgumentParser instance
|
||||
or None.
|
||||
|
||||
:param bool load_envvars:
|
||||
Whether or not to load config settings from environment variables.
|
||||
Defaults to True.
|
||||
|
||||
:returns: OpenStackConfig instance
|
||||
"""
|
||||
|
||||
if config is None:
|
||||
# If we use `openstack.config.loader.OpenStackConfig` instead of
|
||||
# `os_client_config.config.OpenStackConfig` and then instantiate a
|
||||
# `shade.openstackcloud.OpenStackCloud` instance as `cloud`, when
|
||||
# trying to access the `cloud.keystone_client` attribute (or any other
|
||||
# `*_client attribute`), we get a
|
||||
# "TypeError: 'NoneType' object is not callable" exception
|
||||
# This is why we use `os_client_config.config.OpenStackConfig`: it's to
|
||||
# have all `shade.openstackcloud.OpenStackCloud` attributes working
|
||||
# properly. Whether we use them or not, whether these attributes are
|
||||
# deprecated or not, we do not want a 'broken' shade instance in case
|
||||
# third party managers would use them.
|
||||
config = OpenStackConfig(
|
||||
load_envvars=load_envvars, load_yaml_config=load_yaml_config
|
||||
)
|
||||
if parser:
|
||||
if load_envvars or load_yaml_config:
|
||||
config.register_argparse_arguments(parser, sys.argv)
|
||||
else:
|
||||
config.register_argparse_arguments(parser, [])
|
||||
return config
|
||||
|
||||
|
||||
def get_openstack_cli_arguments(
|
||||
parser=None, load_envvars=True, load_yaml_config=True,
|
||||
renamed_args=False
|
||||
):
|
||||
if parser is None:
|
||||
parser = argparse.ArgumentParser()
|
||||
get_openstack_config_with_envvars(
|
||||
parser, load_envvars=load_envvars, load_yaml_config=load_yaml_config
|
||||
)
|
||||
known_args, unknown_args = parser.parse_known_args()
|
||||
if renamed_args:
|
||||
known_args = utils.rename_os_options(known_args, clean=False)
|
||||
return known_args, unknown_args
|
||||
|
||||
|
||||
def get_openstack_envvars_as_kwargs(
|
||||
with_args=False, parser=None, load_envvars=True, load_yaml_config=True
|
||||
):
|
||||
"""Get openstack environment variables"""
|
||||
known_args, unknown_args = get_openstack_cli_arguments(
|
||||
parser=parser, load_envvars=load_envvars,
|
||||
load_yaml_config=load_yaml_config
|
||||
)
|
||||
kwargs = utils.rename_os_kwargs(vars(known_args), clean=True)
|
||||
if with_args:
|
||||
return known_args, unknown_args, kwargs
|
||||
return kwargs
|
||||
|
||||
|
||||
def get_keystoneauth1_session(
|
||||
load_envvars=False, load_yaml_config=False, **kwargs
|
||||
):
|
||||
if load_envvars:
|
||||
kwargs.update(
|
||||
get_openstack_envvars_as_kwargs(
|
||||
load_envvars=load_envvars, load_yaml_config=load_yaml_config
|
||||
)
|
||||
)
|
||||
auth_type = kwargs.get('auth_type', 'password')
|
||||
loader = get_loader(auth_type)
|
||||
loader_kwargs, _ = extract_loader_kwargs(loader, **kwargs)
|
||||
auth = loader.load_from_options(**loader_kwargs)
|
||||
return keystone_session.Session(auth=auth)
|
||||
|
||||
|
||||
get_keystone_session = get_keystoneauth1_session
|
||||
|
||||
|
||||
def get_openstack_config(
|
||||
parser_or_options=None, load_envvars=False, load_yaml_config=False,
|
||||
**kwargs
|
||||
):
|
||||
"""Same as os_client_config.get_config with less errors.
|
||||
|
||||
Indeed, if we source OS_* variable environments, and one calls:
|
||||
|
||||
os_client_config.get_config(
|
||||
load_envvars=False, load_yaml_config=False, **kwargs
|
||||
)
|
||||
|
||||
we get this kind of error:
|
||||
|
||||
ConfigException: Region fr1 is not a valid region name for cloud
|
||||
envvars. Valid choices are fr0. Please note that region names are case
|
||||
sensitive.
|
||||
|
||||
It seems like os_client_config.get_config fails to NOT handle envvars.
|
||||
|
||||
Also, os_client_config.get_config saves the config in a global variable...
|
||||
This is absolutely not thread safe...
|
||||
|
||||
"""
|
||||
parsed_options = None
|
||||
parser = None
|
||||
if isinstance(parser_or_options, argparse.ArgumentParser):
|
||||
parser = parser_or_options
|
||||
config = get_openstack_config_with_envvars(
|
||||
parser=parser, load_envvars=load_envvars,
|
||||
load_yaml_config=load_yaml_config
|
||||
)
|
||||
if parser_or_options is not None:
|
||||
if isinstance(parser_or_options, argparse.Namespace):
|
||||
parsed_options = parser_or_options
|
||||
elif isinstance(parser_or_options, dict):
|
||||
parsed_options = utils.dict_to_options(parser_or_options)
|
||||
elif isinstance(parser_or_options, argparse.ArgumentParser):
|
||||
if load_envvars or load_yaml_config:
|
||||
parsed_options, _ = parser_or_options.parse_known_args(
|
||||
sys.argv)
|
||||
else:
|
||||
parsed_options, _ = parser_or_options.parse_known_args([])
|
||||
else:
|
||||
raise AttributeError(
|
||||
"'parser_options' has to be an 'argparse.ArgumentParser' or "
|
||||
"'argparse.Namespace' instance or dict or None. "
|
||||
"Received '%s'" % type(parser_or_options)
|
||||
)
|
||||
return config.get_one(
|
||||
options=parsed_options,
|
||||
load_yaml_config=load_yaml_config,
|
||||
load_envvars=load_envvars,
|
||||
**kwargs
|
||||
)
|
||||
|
||||
|
||||
def get_openstack_sdk_connection(
|
||||
parser_or_options=None, load_envvars=False, load_yaml_config=False,
|
||||
cloud_config=None, session=None,
|
||||
**kwargs
|
||||
):
|
||||
if session is not None:
|
||||
return os_connection.Connection(session=session, **kwargs)
|
||||
|
||||
if cloud_config is None:
|
||||
# we could return
|
||||
# `openstack.connect(load_envvars=load_envvars, load_yaml_config=load_yaml_config, **kwargs)` # noqa
|
||||
# but by doing so magic things are lacking in the config and we have
|
||||
# random failing methods on the instance. See comments in
|
||||
# get_openstack_config_with_envvars for more information.
|
||||
cloud_config = get_openstack_config(
|
||||
parser_or_options=parser_or_options, load_envvars=load_envvars,
|
||||
load_yaml_config=load_yaml_config,
|
||||
**kwargs
|
||||
)
|
||||
if isinstance(parser_or_options, dict):
|
||||
parser_or_options = utils.dict_to_options(parser_or_options)
|
||||
return os_connection.from_config(
|
||||
cloud_config=cloud_config, options=parser_or_options
|
||||
)
|
||||
|
||||
|
||||
def get_shade(
|
||||
parser_or_options=None, cloud_config=None, connection=None,
|
||||
load_envvars=False, load_yaml_config=False,
|
||||
**kwargs
|
||||
):
|
||||
"""Get shade instance
|
||||
|
||||
You can use an `argparse.ArgumentParser` or `argparse.Namespace` instance
|
||||
with `load_envvars` and/or `load_yaml_config` set to True,
|
||||
Or you kan use kwargs to authenticate with `load_envvars` AND
|
||||
`load_yaml_config` set to False:
|
||||
|
||||
cloud = get_shade(
|
||||
auth_type='password',
|
||||
auth_url='https://identity.fr1.cloudwatt.com/v2.0',
|
||||
interface='public',
|
||||
password='YourPassword',
|
||||
project_id='Your ProjectID,
|
||||
project_name='YourProjectName,
|
||||
region_name='YourRegionName',
|
||||
username='YourUserName'
|
||||
)
|
||||
|
||||
You can also use a token instead of password with kwargs, If so, use
|
||||
`auth_type='token'`.
|
||||
|
||||
"""
|
||||
if cloud_config is not None:
|
||||
return OpenStackCloud(cloud_config=cloud_config, **kwargs)
|
||||
elif connection is not None:
|
||||
return OpenStackCloud(cloud_config=connection.config, **kwargs)
|
||||
else:
|
||||
return OpenStackCloud(
|
||||
cloud_config=get_openstack_config(
|
||||
parser_or_options=parser_or_options, load_envvars=load_envvars,
|
||||
load_yaml_config=load_yaml_config,
|
||||
**kwargs
|
||||
)
|
||||
)
|
@ -0,0 +1,33 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# This software is released under the MIT License.
|
||||
#
|
||||
# Copyright (c) 2018 Orange Cloud for Business / Cloudwatt
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
try:
|
||||
from unittest import mock # Python 3.3+
|
||||
except ImportError:
|
||||
import mock # noqa: Python 2.7
|
||||
|
||||
try:
|
||||
import unittest2 as unittest # Python 2.7
|
||||
except ImportError:
|
||||
import unittest # noqa
|
@ -1,53 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright 2010-2011 OpenStack Foundation
|
||||
# Copyright (c) 2013 Hewlett-Packard Development Company, L.P.
|
||||
#
|
||||
# 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.
|
||||
|
||||
import os
|
||||
|
||||
import fixtures
|
||||
import testtools
|
||||
|
||||
_TRUE_VALUES = ('True', 'true', '1', 'yes')
|
||||
|
||||
|
||||
class TestCase(testtools.TestCase):
|
||||
|
||||
"""Test case base class for all unit tests."""
|
||||
|
||||
def setUp(self):
|
||||
"""Run before each test method to initialize test environment."""
|
||||
|
||||
super(TestCase, self).setUp()
|
||||
test_timeout = os.environ.get('OS_TEST_TIMEOUT', 0)
|
||||
try:
|
||||
test_timeout = int(test_timeout)
|
||||
except ValueError:
|
||||
# If timeout value is invalid do not set a timeout.
|
||||
test_timeout = 0
|
||||
if test_timeout > 0:
|
||||
self.useFixture(fixtures.Timeout(test_timeout, gentle=True))
|
||||
|
||||
self.useFixture(fixtures.NestedTempfile())
|
||||
self.useFixture(fixtures.TempHomeDir())
|
||||
|
||||
if os.environ.get('OS_STDOUT_CAPTURE') in _TRUE_VALUES:
|
||||
stdout = self.useFixture(fixtures.StringStream('stdout')).stream
|
||||
self.useFixture(fixtures.MonkeyPatch('sys.stdout', stdout))
|
||||
if os.environ.get('OS_STDERR_CAPTURE') in _TRUE_VALUES:
|
||||
stderr = self.useFixture(fixtures.StringStream('stderr')).stream
|
||||
self.useFixture(fixtures.MonkeyPatch('sys.stderr', stderr))
|
||||
|
||||
self.log_fixture = self.useFixture(fixtures.FakeLogger())
|
30
flameclient/tests/fixtures/__init__.py
vendored
Normal file
30
flameclient/tests/fixtures/__init__.py
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# This software is released under the MIT License.
|
||||
#
|
||||
# Copyright (c) 2018 Orange Cloud for Business / Cloudwatt
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
import os
|
||||
|
||||
|
||||
FIXTURES_DIR = os.path.realpath(
|
||||
os.path.dirname(__file__)
|
||||
)
|
28
flameclient/tests/fixtures/openstackcloud/__init__.py
vendored
Normal file
28
flameclient/tests/fixtures/openstackcloud/__init__.py
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# This software is released under the MIT License.
|
||||
#
|
||||
# Copyright (c) 2018 Orange Cloud for Business / Cloudwatt
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
from flameclient.utils import load_resource_modules
|
||||
|
||||
|
||||
FIXTURES = load_resource_modules(__file__)
|
432
flameclient/tests/fixtures/openstackcloud/flavors.py
vendored
Normal file
432
flameclient/tests/fixtures/openstackcloud/flavors.py
vendored
Normal file
@ -0,0 +1,432 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# This software is released under the MIT License.
|
||||
#
|
||||
# Copyright (c) 2018 Orange Cloud for Business / Cloudwatt
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
|
||||
NAME = 'compute.flavors'
|
||||
|
||||
FIXTURES = [{'OS-FLV-DISABLED:disabled': False,
|
||||
'OS-FLV-EXT-DATA:ephemeral': 0,
|
||||
'description': None,
|
||||
'disk': 20,
|
||||
'id': '16',
|
||||
'links': [{'href': 'https://compute.fr1.cloudwatt.com/v2/9824a7403a1b411d8d207d26218597ce/flavors/16',
|
||||
'rel': 'self'},
|
||||
{'href': 'https://compute.fr1.cloudwatt.com/9824a7403a1b411d8d207d26218597ce/flavors/16',
|
||||
'rel': 'bookmark'}],
|
||||
'name': 't1.cw.tiny',
|
||||
'os-flavor-access:is_public': True,
|
||||
'ram': 629,
|
||||
'rxtx_factor': 1.0,
|
||||
'swap': '',
|
||||
'vcpus': 1},
|
||||
{'OS-FLV-DISABLED:disabled': False,
|
||||
'OS-FLV-EXT-DATA:ephemeral': 0,
|
||||
'description': None,
|
||||
'disk': 50,
|
||||
'id': '17',
|
||||
'links': [{'href': 'https://compute.fr1.cloudwatt.com/v2/9824a7403a1b411d8d207d26218597ce/flavors/17',
|
||||
'rel': 'self'},
|
||||
{'href': 'https://compute.fr1.cloudwatt.com/9824a7403a1b411d8d207d26218597ce/flavors/17',
|
||||
'rel': 'bookmark'}],
|
||||
'name': 's1.cw.small-1',
|
||||
'os-flavor-access:is_public': True,
|
||||
'ram': 1792,
|
||||
'rxtx_factor': 1.0,
|
||||
'swap': '',
|
||||
'vcpus': 1},
|
||||
{'OS-FLV-DISABLED:disabled': False,
|
||||
'OS-FLV-EXT-DATA:ephemeral': 0,
|
||||
'description': None,
|
||||
'disk': 50,
|
||||
'id': '18',
|
||||
'links': [{'href': 'https://compute.fr1.cloudwatt.com/v2/9824a7403a1b411d8d207d26218597ce/flavors/18',
|
||||
'rel': 'self'},
|
||||
{'href': 'https://compute.fr1.cloudwatt.com/9824a7403a1b411d8d207d26218597ce/flavors/18',
|
||||
'rel': 'bookmark'}],
|
||||
'name': 'n1.cw.highcpu-2',
|
||||
'os-flavor-access:is_public': True,
|
||||
'ram': 4000,
|
||||
'rxtx_factor': 1.0,
|
||||
'swap': '',
|
||||
'vcpus': 2},
|
||||
{'OS-FLV-DISABLED:disabled': False,
|
||||
'OS-FLV-EXT-DATA:ephemeral': 0,
|
||||
'description': None,
|
||||
'disk': 50,
|
||||
'id': '19',
|
||||
'links': [{'href': 'https://compute.fr1.cloudwatt.com/v2/9824a7403a1b411d8d207d26218597ce/flavors/19',
|
||||
'rel': 'self'},
|
||||
{'href': 'https://compute.fr1.cloudwatt.com/9824a7403a1b411d8d207d26218597ce/flavors/19',
|
||||
'rel': 'bookmark'}],
|
||||
'name': 'n1.cw.highcpu-4',
|
||||
'os-flavor-access:is_public': True,
|
||||
'ram': 8000,
|
||||
'rxtx_factor': 1.0,
|
||||
'swap': '',
|
||||
'vcpus': 4},
|
||||
{'OS-FLV-DISABLED:disabled': False,
|
||||
'OS-FLV-EXT-DATA:ephemeral': 0,
|
||||
'description': None,
|
||||
'disk': 50,
|
||||
'id': '20',
|
||||
'links': [{'href': 'https://compute.fr1.cloudwatt.com/v2/9824a7403a1b411d8d207d26218597ce/flavors/20',
|
||||
'rel': 'self'},
|
||||
{'href': 'https://compute.fr1.cloudwatt.com/9824a7403a1b411d8d207d26218597ce/flavors/20',
|
||||
'rel': 'bookmark'}],
|
||||
'name': 'n1.cw.highcpu-8',
|
||||
'os-flavor-access:is_public': True,
|
||||
'ram': 16000,
|
||||
'rxtx_factor': 1.0,
|
||||
'swap': '',
|
||||
'vcpus': 8},
|
||||
{'OS-FLV-DISABLED:disabled': False,
|
||||
'OS-FLV-EXT-DATA:ephemeral': 0,
|
||||
'description': None,
|
||||
'disk': 50,
|
||||
'id': '21',
|
||||
'links': [{'href': 'https://compute.fr1.cloudwatt.com/v2/9824a7403a1b411d8d207d26218597ce/flavors/21',
|
||||
'rel': 'self'},
|
||||
{'href': 'https://compute.fr1.cloudwatt.com/9824a7403a1b411d8d207d26218597ce/flavors/21',
|
||||
'rel': 'bookmark'}],
|
||||
'name': 'n1.cw.standard-1',
|
||||
'os-flavor-access:is_public': True,
|
||||
'ram': 4000,
|
||||
'rxtx_factor': 1.0,
|
||||
'swap': '',
|
||||
'vcpus': 1},
|
||||
{'OS-FLV-DISABLED:disabled': False,
|
||||
'OS-FLV-EXT-DATA:ephemeral': 0,
|
||||
'description': None,
|
||||
'disk': 50,
|
||||
'id': '22',
|
||||
'links': [{'href': 'https://compute.fr1.cloudwatt.com/v2/9824a7403a1b411d8d207d26218597ce/flavors/22',
|
||||
'rel': 'self'},
|
||||
{'href': 'https://compute.fr1.cloudwatt.com/9824a7403a1b411d8d207d26218597ce/flavors/22',
|
||||
'rel': 'bookmark'}],
|
||||
'name': 'n1.cw.standard-2',
|
||||
'os-flavor-access:is_public': True,
|
||||
'ram': 8000,
|
||||
'rxtx_factor': 1.0,
|
||||
'swap': '',
|
||||
'vcpus': 2},
|
||||
{'OS-FLV-DISABLED:disabled': False,
|
||||
'OS-FLV-EXT-DATA:ephemeral': 0,
|
||||
'description': None,
|
||||
'disk': 50,
|
||||
'id': '23',
|
||||
'links': [{'href': 'https://compute.fr1.cloudwatt.com/v2/9824a7403a1b411d8d207d26218597ce/flavors/23',
|
||||
'rel': 'self'},
|
||||
{'href': 'https://compute.fr1.cloudwatt.com/9824a7403a1b411d8d207d26218597ce/flavors/23',
|
||||
'rel': 'bookmark'}],
|
||||
'name': 'n1.cw.standard-4',
|
||||
'os-flavor-access:is_public': True,
|
||||
'ram': 16000,
|
||||
'rxtx_factor': 1.0,
|
||||
'swap': '',
|
||||
'vcpus': 4},
|
||||
{'OS-FLV-DISABLED:disabled': False,
|
||||
'OS-FLV-EXT-DATA:ephemeral': 0,
|
||||
'description': None,
|
||||
'disk': 50,
|
||||
'id': '24',
|
||||
'links': [{'href': 'https://compute.fr1.cloudwatt.com/v2/9824a7403a1b411d8d207d26218597ce/flavors/24',
|
||||
'rel': 'self'},
|
||||
{'href': 'https://compute.fr1.cloudwatt.com/9824a7403a1b411d8d207d26218597ce/flavors/24',
|
||||
'rel': 'bookmark'}],
|
||||
'name': 'n1.cw.standard-8',
|
||||
'os-flavor-access:is_public': True,
|
||||
'ram': 32000,
|
||||
'rxtx_factor': 1.0,
|
||||
'swap': '',
|
||||
'vcpus': 8},
|
||||
{'OS-FLV-DISABLED:disabled': False,
|
||||
'OS-FLV-EXT-DATA:ephemeral': 0,
|
||||
'description': None,
|
||||
'disk': 50,
|
||||
'id': '25',
|
||||
'links': [{'href': 'https://compute.fr1.cloudwatt.com/v2/9824a7403a1b411d8d207d26218597ce/flavors/25',
|
||||
'rel': 'self'},
|
||||
{'href': 'https://compute.fr1.cloudwatt.com/9824a7403a1b411d8d207d26218597ce/flavors/25',
|
||||
'rel': 'bookmark'}],
|
||||
'name': 'n1.cw.standard-12',
|
||||
'os-flavor-access:is_public': True,
|
||||
'ram': 48000,
|
||||
'rxtx_factor': 1.0,
|
||||
'swap': '',
|
||||
'vcpus': 12},
|
||||
{'OS-FLV-DISABLED:disabled': False,
|
||||
'OS-FLV-EXT-DATA:ephemeral': 0,
|
||||
'description': None,
|
||||
'disk': 50,
|
||||
'id': '26',
|
||||
'links': [{'href': 'https://compute.fr1.cloudwatt.com/v2/9824a7403a1b411d8d207d26218597ce/flavors/26',
|
||||
'rel': 'self'},
|
||||
{'href': 'https://compute.fr1.cloudwatt.com/9824a7403a1b411d8d207d26218597ce/flavors/26',
|
||||
'rel': 'bookmark'}],
|
||||
'name': 'n1.cw.standard-16',
|
||||
'os-flavor-access:is_public': True,
|
||||
'ram': 64000,
|
||||
'rxtx_factor': 1.0,
|
||||
'swap': '',
|
||||
'vcpus': 16},
|
||||
{'OS-FLV-DISABLED:disabled': False,
|
||||
'OS-FLV-EXT-DATA:ephemeral': 0,
|
||||
'description': None,
|
||||
'disk': 50,
|
||||
'id': '28',
|
||||
'links': [{'href': 'https://compute.fr1.cloudwatt.com/v2/9824a7403a1b411d8d207d26218597ce/flavors/28',
|
||||
'rel': 'self'},
|
||||
{'href': 'https://compute.fr1.cloudwatt.com/9824a7403a1b411d8d207d26218597ce/flavors/28',
|
||||
'rel': 'bookmark'}],
|
||||
'name': 'n1.cw.highmem-2',
|
||||
'os-flavor-access:is_public': True,
|
||||
'ram': 13312,
|
||||
'rxtx_factor': 1.0,
|
||||
'swap': '',
|
||||
'vcpus': 2},
|
||||
{'OS-FLV-DISABLED:disabled': False,
|
||||
'OS-FLV-EXT-DATA:ephemeral': 0,
|
||||
'description': None,
|
||||
'disk': 50,
|
||||
'id': '29',
|
||||
'links': [{'href': 'https://compute.fr1.cloudwatt.com/v2/9824a7403a1b411d8d207d26218597ce/flavors/29',
|
||||
'rel': 'self'},
|
||||
{'href': 'https://compute.fr1.cloudwatt.com/9824a7403a1b411d8d207d26218597ce/flavors/29',
|
||||
'rel': 'bookmark'}],
|
||||
'name': 'n1.cw.highmem-4',
|
||||
'os-flavor-access:is_public': True,
|
||||
'ram': 26624,
|
||||
'rxtx_factor': 1.0,
|
||||
'swap': '',
|
||||
'vcpus': 4},
|
||||
{'OS-FLV-DISABLED:disabled': False,
|
||||
'OS-FLV-EXT-DATA:ephemeral': 0,
|
||||
'description': None,
|
||||
'disk': 50,
|
||||
'id': '30',
|
||||
'links': [{'href': 'https://compute.fr1.cloudwatt.com/v2/9824a7403a1b411d8d207d26218597ce/flavors/30',
|
||||
'rel': 'self'},
|
||||
{'href': 'https://compute.fr1.cloudwatt.com/9824a7403a1b411d8d207d26218597ce/flavors/30',
|
||||
'rel': 'bookmark'}],
|
||||
'name': 'n1.cw.highmem-8',
|
||||
'os-flavor-access:is_public': True,
|
||||
'ram': 53248,
|
||||
'rxtx_factor': 1.0,
|
||||
'swap': '',
|
||||
'vcpus': 8},
|
||||
{'OS-FLV-DISABLED:disabled': False,
|
||||
'OS-FLV-EXT-DATA:ephemeral': 0,
|
||||
'description': None,
|
||||
'disk': 50,
|
||||
'id': '31',
|
||||
'links': [{'href': 'https://compute.fr1.cloudwatt.com/v2/9824a7403a1b411d8d207d26218597ce/flavors/31',
|
||||
'rel': 'self'},
|
||||
{'href': 'https://compute.fr1.cloudwatt.com/9824a7403a1b411d8d207d26218597ce/flavors/31',
|
||||
'rel': 'bookmark'}],
|
||||
'name': 'n1.cw.highmem-12',
|
||||
'os-flavor-access:is_public': True,
|
||||
'ram': 79872,
|
||||
'rxtx_factor': 1.0,
|
||||
'swap': '',
|
||||
'vcpus': 12},
|
||||
{'OS-FLV-DISABLED:disabled': False,
|
||||
'OS-FLV-EXT-DATA:ephemeral': 0,
|
||||
'description': None,
|
||||
'disk': 50,
|
||||
'id': '38',
|
||||
'links': [{'href': 'https://compute.fr1.cloudwatt.com/v2/9824a7403a1b411d8d207d26218597ce/flavors/38',
|
||||
'rel': 'self'},
|
||||
{'href': 'https://compute.fr1.cloudwatt.com/9824a7403a1b411d8d207d26218597ce/flavors/38',
|
||||
'rel': 'bookmark'}],
|
||||
'name': 'n2.cw.highmem-2',
|
||||
'os-flavor-access:is_public': True,
|
||||
'ram': 13312,
|
||||
'rxtx_factor': 1.0,
|
||||
'swap': '',
|
||||
'vcpus': 2},
|
||||
{'OS-FLV-DISABLED:disabled': False,
|
||||
'OS-FLV-EXT-DATA:ephemeral': 50,
|
||||
'description': None,
|
||||
'disk': 50,
|
||||
'id': '39',
|
||||
'links': [{'href': 'https://compute.fr1.cloudwatt.com/v2/9824a7403a1b411d8d207d26218597ce/flavors/39',
|
||||
'rel': 'self'},
|
||||
{'href': 'https://compute.fr1.cloudwatt.com/9824a7403a1b411d8d207d26218597ce/flavors/39',
|
||||
'rel': 'bookmark'}],
|
||||
'name': 'n2.cw.highmem-4',
|
||||
'os-flavor-access:is_public': True,
|
||||
'ram': 26624,
|
||||
'rxtx_factor': 1.0,
|
||||
'swap': '',
|
||||
'vcpus': 4},
|
||||
{'OS-FLV-DISABLED:disabled': False,
|
||||
'OS-FLV-EXT-DATA:ephemeral': 100,
|
||||
'description': None,
|
||||
'disk': 50,
|
||||
'id': '40',
|
||||
'links': [{'href': 'https://compute.fr1.cloudwatt.com/v2/9824a7403a1b411d8d207d26218597ce/flavors/40',
|
||||
'rel': 'self'},
|
||||
{'href': 'https://compute.fr1.cloudwatt.com/9824a7403a1b411d8d207d26218597ce/flavors/40',
|
||||
'rel': 'bookmark'}],
|
||||
'name': 'n2.cw.highmem-8',
|
||||
'os-flavor-access:is_public': True,
|
||||
'ram': 53248,
|
||||
'rxtx_factor': 1.0,
|
||||
'swap': '',
|
||||
'vcpus': 8},
|
||||
{'OS-FLV-DISABLED:disabled': False,
|
||||
'OS-FLV-EXT-DATA:ephemeral': 300,
|
||||
'description': None,
|
||||
'disk': 50,
|
||||
'id': '41',
|
||||
'links': [{'href': 'https://compute.fr1.cloudwatt.com/v2/9824a7403a1b411d8d207d26218597ce/flavors/41',
|
||||
'rel': 'self'},
|
||||
{'href': 'https://compute.fr1.cloudwatt.com/9824a7403a1b411d8d207d26218597ce/flavors/41',
|
||||
'rel': 'bookmark'}],
|
||||
'name': 'n2.cw.highmem-16',
|
||||
'os-flavor-access:is_public': True,
|
||||
'ram': 104000,
|
||||
'rxtx_factor': 1.0,
|
||||
'swap': '',
|
||||
'vcpus': 16},
|
||||
{'OS-FLV-DISABLED:disabled': False,
|
||||
'OS-FLV-EXT-DATA:ephemeral': 0,
|
||||
'description': None,
|
||||
'disk': 50,
|
||||
'id': '42',
|
||||
'links': [{'href': 'https://compute.fr1.cloudwatt.com/v2/9824a7403a1b411d8d207d26218597ce/flavors/42',
|
||||
'rel': 'self'},
|
||||
{'href': 'https://compute.fr1.cloudwatt.com/9824a7403a1b411d8d207d26218597ce/flavors/42',
|
||||
'rel': 'bookmark'}],
|
||||
'name': 'n2.cw.standard-1',
|
||||
'os-flavor-access:is_public': True,
|
||||
'ram': 4000,
|
||||
'rxtx_factor': 1.0,
|
||||
'swap': '',
|
||||
'vcpus': 1},
|
||||
{'OS-FLV-DISABLED:disabled': False,
|
||||
'OS-FLV-EXT-DATA:ephemeral': 0,
|
||||
'description': None,
|
||||
'disk': 50,
|
||||
'id': '43',
|
||||
'links': [{'href': 'https://compute.fr1.cloudwatt.com/v2/9824a7403a1b411d8d207d26218597ce/flavors/43',
|
||||
'rel': 'self'},
|
||||
{'href': 'https://compute.fr1.cloudwatt.com/9824a7403a1b411d8d207d26218597ce/flavors/43',
|
||||
'rel': 'bookmark'}],
|
||||
'name': 'n2.cw.standard-2',
|
||||
'os-flavor-access:is_public': True,
|
||||
'ram': 8000,
|
||||
'rxtx_factor': 1.0,
|
||||
'swap': '',
|
||||
'vcpus': 2},
|
||||
{'OS-FLV-DISABLED:disabled': False,
|
||||
'OS-FLV-EXT-DATA:ephemeral': 0,
|
||||
'description': None,
|
||||
'disk': 50,
|
||||
'id': '44',
|
||||
'links': [{'href': 'https://compute.fr1.cloudwatt.com/v2/9824a7403a1b411d8d207d26218597ce/flavors/44',
|
||||
'rel': 'self'},
|
||||
{'href': 'https://compute.fr1.cloudwatt.com/9824a7403a1b411d8d207d26218597ce/flavors/44',
|
||||
'rel': 'bookmark'}],
|
||||
'name': 'n2.cw.standard-4',
|
||||
'os-flavor-access:is_public': True,
|
||||
'ram': 16000,
|
||||
'rxtx_factor': 1.0,
|
||||
'swap': '',
|
||||
'vcpus': 4},
|
||||
{'OS-FLV-DISABLED:disabled': False,
|
||||
'OS-FLV-EXT-DATA:ephemeral': 0,
|
||||
'description': None,
|
||||
'disk': 50,
|
||||
'id': '45',
|
||||
'links': [{'href': 'https://compute.fr1.cloudwatt.com/v2/9824a7403a1b411d8d207d26218597ce/flavors/45',
|
||||
'rel': 'self'},
|
||||
{'href': 'https://compute.fr1.cloudwatt.com/9824a7403a1b411d8d207d26218597ce/flavors/45',
|
||||
'rel': 'bookmark'}],
|
||||
'name': 'n2.cw.standard-8',
|
||||
'os-flavor-access:is_public': True,
|
||||
'ram': 32000,
|
||||
'rxtx_factor': 1.0,
|
||||
'swap': '',
|
||||
'vcpus': 8},
|
||||
{'OS-FLV-DISABLED:disabled': False,
|
||||
'OS-FLV-EXT-DATA:ephemeral': 0,
|
||||
'description': None,
|
||||
'disk': 50,
|
||||
'id': '46',
|
||||
'links': [{'href': 'https://compute.fr1.cloudwatt.com/v2/9824a7403a1b411d8d207d26218597ce/flavors/46',
|
||||
'rel': 'self'},
|
||||
{'href': 'https://compute.fr1.cloudwatt.com/9824a7403a1b411d8d207d26218597ce/flavors/46',
|
||||
'rel': 'bookmark'}],
|
||||
'name': 'n2.cw.standard-16',
|
||||
'os-flavor-access:is_public': True,
|
||||
'ram': 64000,
|
||||
'rxtx_factor': 1.0,
|
||||
'swap': '',
|
||||
'vcpus': 16},
|
||||
{'OS-FLV-DISABLED:disabled': False,
|
||||
'OS-FLV-EXT-DATA:ephemeral': 400,
|
||||
'description': None,
|
||||
'disk': 50,
|
||||
'id': '53',
|
||||
'links': [{'href': 'https://compute.fr1.cloudwatt.com/v2/9824a7403a1b411d8d207d26218597ce/flavors/53',
|
||||
'rel': 'self'},
|
||||
{'href': 'https://compute.fr1.cloudwatt.com/9824a7403a1b411d8d207d26218597ce/flavors/53',
|
||||
'rel': 'bookmark'}],
|
||||
'name': 'i2.cw.largessd-4',
|
||||
'os-flavor-access:is_public': True,
|
||||
'ram': 32000,
|
||||
'rxtx_factor': 1.0,
|
||||
'swap': '',
|
||||
'vcpus': 4},
|
||||
{'OS-FLV-DISABLED:disabled': False,
|
||||
'OS-FLV-EXT-DATA:ephemeral': 850,
|
||||
'description': None,
|
||||
'disk': 50,
|
||||
'id': '54',
|
||||
'links': [{'href': 'https://compute.fr1.cloudwatt.com/v2/9824a7403a1b411d8d207d26218597ce/flavors/54',
|
||||
'rel': 'self'},
|
||||
{'href': 'https://compute.fr1.cloudwatt.com/9824a7403a1b411d8d207d26218597ce/flavors/54',
|
||||
'rel': 'bookmark'}],
|
||||
'name': 'i2.cw.largessd-8',
|
||||
'os-flavor-access:is_public': True,
|
||||
'ram': 64000,
|
||||
'rxtx_factor': 1.0,
|
||||
'swap': '',
|
||||
'vcpus': 8},
|
||||
{'OS-FLV-DISABLED:disabled': False,
|
||||
'OS-FLV-EXT-DATA:ephemeral': 1750,
|
||||
'description': None,
|
||||
'disk': 50,
|
||||
'id': '55',
|
||||
'links': [{'href': 'https://compute.fr1.cloudwatt.com/v2/9824a7403a1b411d8d207d26218597ce/flavors/55',
|
||||
'rel': 'self'},
|
||||
{'href': 'https://compute.fr1.cloudwatt.com/9824a7403a1b411d8d207d26218597ce/flavors/55',
|
||||
'rel': 'bookmark'}],
|
||||
'name': 'i2.cw.largessd-16',
|
||||
'os-flavor-access:is_public': True,
|
||||
'ram': 128000,
|
||||
'rxtx_factor': 1.0,
|
||||
'swap': '',
|
||||
'vcpus': 16}]
|
46
flameclient/tests/fixtures/openstackcloud/floatingips.py
vendored
Normal file
46
flameclient/tests/fixtures/openstackcloud/floatingips.py
vendored
Normal file
@ -0,0 +1,46 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# This software is released under the MIT License.
|
||||
#
|
||||
# Copyright (c) 2018 Orange Cloud for Business / Cloudwatt
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
|
||||
NAME = 'network.ips'
|
||||
|
||||
FIXTURES = [{'created_at': None,
|
||||
'description': None,
|
||||
'dns_domain': None,
|
||||
'dns_name': None,
|
||||
'fixed_ip_address': '192.168.0.8',
|
||||
'floating_ip_address': '84.39.32.171',
|
||||
'floating_network_id': '6ea98324-0f14-49f6-97c0-885d1b8dc517',
|
||||
'id': 'e6f50641-6c7e-468c-9623-1fd5ee2c1ebc',
|
||||
'name': '84.39.32.171',
|
||||
'port_details': None,
|
||||
'port_id': None,
|
||||
'qos_policy_id': None,
|
||||
'revision_number': None,
|
||||
'router_id': None,
|
||||
'status': 'ACTIVE',
|
||||
'subnet_id': None,
|
||||
'tags': [],
|
||||
'tenant_id': '9824a7403a1b411d8d207d26218597ce',
|
||||
'updated_at': None}]
|
201
flameclient/tests/fixtures/openstackcloud/images.py
vendored
Normal file
201
flameclient/tests/fixtures/openstackcloud/images.py
vendored
Normal file
@ -0,0 +1,201 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# This software is released under the MIT License.
|
||||
#
|
||||
# Copyright (c) 2018 Orange Cloud for Business / Cloudwatt
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
|
||||
NAME = 'image.images'
|
||||
|
||||
FIXTURES = [{'architecture': None,
|
||||
'auto_disk_config': None,
|
||||
'checksum': '57baccdf32b77ff7939d429b842d4440',
|
||||
'container_format': 'bare',
|
||||
'created_at': '2017-06-20T14:53:41Z',
|
||||
'direct_url': None,
|
||||
'disk_format': 'qcow2',
|
||||
'file': '/v2/images/8254d703-e46f-4101-88ff-6f40bf7df51a/file',
|
||||
'hw_boot_menu': None,
|
||||
'hw_cpu_cores': None,
|
||||
'hw_cpu_sockets': None,
|
||||
'hw_cpu_threads': None,
|
||||
'hw_disk_bus': None,
|
||||
'hw_machine_type': None,
|
||||
'hw_qemu_guest_agent': None,
|
||||
'hw_rng_model': 'virtio',
|
||||
'hw_scsi_model': None,
|
||||
'hw_serial_port_count': None,
|
||||
'hw_video_model': None,
|
||||
'hw_video_ram': None,
|
||||
'hw_vif_model': None,
|
||||
'hw_vif_multiqueue_enabled': None,
|
||||
'hw_watchdog_action': None,
|
||||
'hypervisor-type': None,
|
||||
'id': '8254d703-e46f-4101-88ff-6f40bf7df51a',
|
||||
'img_config_drive': None,
|
||||
'instance_type_rxtx_factor': None,
|
||||
'instance_uuid': None,
|
||||
'kernel_id': None,
|
||||
'locations': None,
|
||||
'metadata': None,
|
||||
'min_disk': 50,
|
||||
'min_ram': 2048,
|
||||
'name': 'Windows Server 2012 R2 Standard FR',
|
||||
'os_admin_user': None,
|
||||
'os_command_line': None,
|
||||
'os_distro': None,
|
||||
'os_require_quiesce': None,
|
||||
'os_secure_boot': None,
|
||||
'os_type': None,
|
||||
'os_version': None,
|
||||
'owner': '3ab52a7f1b824983bf418df633d9d88d',
|
||||
'path': None,
|
||||
'properties': None,
|
||||
'protected': False,
|
||||
'ramdisk_id': None,
|
||||
'size': 7976386560,
|
||||
'status': 'active',
|
||||
'store': None,
|
||||
'tags': [],
|
||||
'updated_at': '2017-06-20T14:56:43Z',
|
||||
'url': None,
|
||||
'value': None,
|
||||
'virtual_size': None,
|
||||
'visibility': 'public',
|
||||
'vm_mode': None,
|
||||
'vmware_adaptertype': None,
|
||||
'vmware_ostype': None},
|
||||
{'architecture': None,
|
||||
'auto_disk_config': None,
|
||||
'checksum': '8ec802fe753dfe8e226645a2e0106bf7',
|
||||
'container_format': 'bare',
|
||||
'created_at': '2017-03-23T15:46:41Z',
|
||||
'direct_url': None,
|
||||
'disk_format': 'qcow2',
|
||||
'file': '/v2/images/70a9c910-dd99-4065-bce9-11e89bc479fe/file',
|
||||
'hw_boot_menu': None,
|
||||
'hw_cpu_cores': None,
|
||||
'hw_cpu_sockets': None,
|
||||
'hw_cpu_threads': None,
|
||||
'hw_disk_bus': None,
|
||||
'hw_machine_type': None,
|
||||
'hw_qemu_guest_agent': None,
|
||||
'hw_rng_model': 'virtio',
|
||||
'hw_scsi_model': None,
|
||||
'hw_serial_port_count': None,
|
||||
'hw_video_model': None,
|
||||
'hw_video_ram': None,
|
||||
'hw_vif_model': None,
|
||||
'hw_vif_multiqueue_enabled': None,
|
||||
'hw_watchdog_action': None,
|
||||
'hypervisor-type': None,
|
||||
'id': '70a9c910-dd99-4065-bce9-11e89bc479fe',
|
||||
'img_config_drive': None,
|
||||
'instance_type_rxtx_factor': None,
|
||||
'instance_uuid': None,
|
||||
'kernel_id': None,
|
||||
'locations': None,
|
||||
'metadata': None,
|
||||
'min_disk': 20,
|
||||
'min_ram': 0,
|
||||
'name': 'Ubuntu 14.04',
|
||||
'os_admin_user': None,
|
||||
'os_command_line': None,
|
||||
'os_distro': None,
|
||||
'os_require_quiesce': None,
|
||||
'os_secure_boot': None,
|
||||
'os_type': None,
|
||||
'os_version': None,
|
||||
'owner': '3ab52a7f1b824983bf418df633d9d88d',
|
||||
'path': None,
|
||||
'properties': None,
|
||||
'protected': False,
|
||||
'ramdisk_id': None,
|
||||
'size': 1009057792,
|
||||
'status': 'active',
|
||||
'store': None,
|
||||
'tags': [],
|
||||
'updated_at': '2017-12-26T10:33:50Z',
|
||||
'url': None,
|
||||
'value': None,
|
||||
'virtual_size': None,
|
||||
'visibility': 'public',
|
||||
'vm_mode': None,
|
||||
'vmware_adaptertype': None,
|
||||
'vmware_ostype': None},
|
||||
{'architecture': None,
|
||||
'auto_disk_config': None,
|
||||
'checksum': '12872d8897d2eabfceac8b4627ff88f0',
|
||||
'container_format': 'bare',
|
||||
'created_at': '2016-06-07T07:36:26Z',
|
||||
'direct_url': None,
|
||||
'disk_format': 'qcow2',
|
||||
'file': '/v2/images/dd7d4b21-79b8-42f0-8464-0d1a5274c638/file',
|
||||
'hw_boot_menu': None,
|
||||
'hw_cpu_cores': None,
|
||||
'hw_cpu_sockets': None,
|
||||
'hw_cpu_threads': None,
|
||||
'hw_disk_bus': None,
|
||||
'hw_machine_type': None,
|
||||
'hw_qemu_guest_agent': None,
|
||||
'hw_rng_model': None,
|
||||
'hw_scsi_model': None,
|
||||
'hw_serial_port_count': None,
|
||||
'hw_video_model': None,
|
||||
'hw_video_ram': None,
|
||||
'hw_vif_model': None,
|
||||
'hw_vif_multiqueue_enabled': None,
|
||||
'hw_watchdog_action': None,
|
||||
'hypervisor-type': None,
|
||||
'id': 'dd7d4b21-79b8-42f0-8464-0d1a5274c638',
|
||||
'img_config_drive': None,
|
||||
'instance_type_rxtx_factor': None,
|
||||
'instance_uuid': None,
|
||||
'kernel_id': None,
|
||||
'locations': None,
|
||||
'metadata': None,
|
||||
'min_disk': 0,
|
||||
'min_ram': 0,
|
||||
'name': 'tempest-ubuntu-do-not-erase',
|
||||
'os_admin_user': None,
|
||||
'os_command_line': None,
|
||||
'os_distro': None,
|
||||
'os_require_quiesce': None,
|
||||
'os_secure_boot': None,
|
||||
'os_type': None,
|
||||
'os_version': None,
|
||||
'owner': '3ab52a7f1b824983bf418df633d9d88d',
|
||||
'path': None,
|
||||
'properties': None,
|
||||
'protected': False,
|
||||
'ramdisk_id': None,
|
||||
'size': 261488640,
|
||||
'status': 'active',
|
||||
'store': None,
|
||||
'tags': [],
|
||||
'updated_at': '2016-06-07T07:36:31Z',
|
||||
'url': None,
|
||||
'value': None,
|
||||
'virtual_size': None,
|
||||
'visibility': 'private',
|
||||
'vm_mode': None,
|
||||
'vmware_adaptertype': None,
|
||||
'vmware_ostype': None}]
|
41
flameclient/tests/fixtures/openstackcloud/key_pairs.py
vendored
Normal file
41
flameclient/tests/fixtures/openstackcloud/key_pairs.py
vendored
Normal file
@ -0,0 +1,41 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# This software is released under the MIT License.
|
||||
#
|
||||
# Copyright (c) 2018 Orange Cloud for Business / Cloudwatt
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
|
||||
NAME = 'compute.keypairs'
|
||||
|
||||
FIXTURES = [{'fingerprint': '01:99:63:d2:96:d4:23:25:2f:d5:c9:e4:2f:30:d2:3f',
|
||||
'id': 'tellurium-key',
|
||||
'name': 'tellurium-key',
|
||||
'private_key': None,
|
||||
'public_key': 'ssh-rsa '
|
||||
'AAAAB3NzaC1yc2EAAAADAQABAAABAQCwp5kVZ+3baPZllNXZDG2mivd5nJ5wWY6Jj/WV6NlO6cUiaH5om6itU3lyJxtAbLgbbvY2FjMg1PI2JI3EHx0OSPEbDdeNsQGi31qyuiB1S5p6TreI0Dfy0tywJ9G2CURjkuJnC8SvnMfVYLMFBvx7p8RzxSdDm/zrmc4KY3ktdfYQDNtEiH2jucUUiY0ipVkDNhhv03+5C9cnpaIcVDBkddE/KEME8NIIh7s6aYCXJEWJx85nOVVRD5qK7ouV6FcGVn6zqWRD3jn0iSxcFwiKx7p6M77PmJAY4gBIpWQmutok6T4ZrXxa7jE4dybwo5e8dyvGyc7WWGqXcmcinUWr '
|
||||
'Generated-by-Nova'},
|
||||
{'fingerprint': '76:e2:94:d2:13:c0:72:49:43:a7:58:f5:92:2f:e9:62',
|
||||
'id': 'tellurium-key-phrase',
|
||||
'name': 'tellurium-key-phrase',
|
||||
'private_key': None,
|
||||
'public_key': 'ssh-rsa '
|
||||
'AAAAB3NzaC1yc2EAAAADAQABAAABAQCaYaTC6KCC2GURFMpRQiRq8Og10PcBbVnrQqluzi2E5vAqTHAegzivmGB8h2xrjXUfbKV2bE8kz2ZE66sq1yLO/jZ+rkOA+zLnOxNwkk3gQq57b26ZegPL2tTgottJTPGyPz6v2+LLtDf/+xTJMjkPKcMWylu12Js0XKVkdY35fwN7fRvA4xghtGu1GcmS2XFDMmeLDrG1KNPbBLj5cGoD723Ho7ZhAjLThoY/xMN2OYsSNzrg3S00QngZMzQvJf0ETrB3GtITk5FUs54qMRfiyUC72lw0gLTIJK8rs7fX/yeO+467afRt2xwHN50rEWJPeTVYWdlH/msh7NQ3LZ8/ '
|
||||
'root@9b638ff21113'}]
|
103
flameclient/tests/fixtures/openstackcloud/networks.py
vendored
Normal file
103
flameclient/tests/fixtures/openstackcloud/networks.py
vendored
Normal file
@ -0,0 +1,103 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# This software is released under the MIT License.
|
||||
#
|
||||
# Copyright (c) 2018 Orange Cloud for Business / Cloudwatt
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
|
||||
NAME = 'network.networks'
|
||||
|
||||
FIXTURES = [{'admin_state_up': True,
|
||||
'availability_zone_hints': None,
|
||||
'availability_zones': None,
|
||||
'created_at': None,
|
||||
'description': None,
|
||||
'dns_domain': None,
|
||||
'id': '6ea98324-0f14-49f6-97c0-885d1b8dc517',
|
||||
'ipv4_address_scope': None,
|
||||
'ipv6_address_scope': None,
|
||||
'is_default': None,
|
||||
'mtu': None,
|
||||
'name': 'public',
|
||||
'port_security_enabled': False,
|
||||
'project_id': None,
|
||||
'provider:network_type': None,
|
||||
'provider:physical_network': None,
|
||||
'provider:segmentation_id': None,
|
||||
'qos_policy_id': None,
|
||||
'revision_number': None,
|
||||
'router:external': True,
|
||||
'segments': None,
|
||||
'shared': False,
|
||||
'status': 'ACTIVE',
|
||||
'subnets': ['7ce9190e-397e-4523-bb9a-942a338555c8',
|
||||
'16af2b37-a739-474a-b64d-ad5b515b24d7',
|
||||
'85bc9804-bde9-4fc3-ac28-138bbed0be47',
|
||||
'12469c2c-6902-460a-ad54-9252ca791d55',
|
||||
'84095c22-48af-4cf5-b03d-0c745bfa1586',
|
||||
'12f473cc-a01e-4f70-86d7-c1ae05058545',
|
||||
'02efcad7-4744-41c4-8429-332828309d4f',
|
||||
'aa8fc58b-5db8-45ba-a354-180e5e2ae84b',
|
||||
'6ac09891-9788-46b7-8165-9d2c9cefa483',
|
||||
'38d8fc45-2698-4ffc-9beb-59331e3ef68d',
|
||||
'aded311e-5766-4adc-b6d8-64dd5c93a8c3',
|
||||
'b7f41f14-35a2-4bf4-a2b3-60c2200c0fb5',
|
||||
'65d8722e-09f6-4b39-a693-e61018867377',
|
||||
'c5387c58-542c-4cfd-8338-afcbd37e4546',
|
||||
'baa6798a-0eba-417e-b294-31fbf1c4a7c5',
|
||||
'3c8fde67-c209-4716-a515-5777667a4835',
|
||||
'bf806833-7f33-4254-865f-8a874d36d17c',
|
||||
'6736cae7-7501-4e10-af94-bb06acaf5de6',
|
||||
'7b2e3c57-e8cc-47ac-a008-e0ee2db5e567',
|
||||
'85342bf1-7e69-4468-b269-8435c4991773',
|
||||
'6e289f4e-ec6a-4fd7-9bbc-94c3f17e57a8',
|
||||
'de042fd3-acf3-487f-819f-7b18617728ec',
|
||||
'da35a785-99ea-4d54-b056-0c20feca1125'],
|
||||
'tags': [],
|
||||
'updated_at': None,
|
||||
'vlan_transparent': None},
|
||||
{'admin_state_up': True,
|
||||
'availability_zone_hints': None,
|
||||
'availability_zones': None,
|
||||
'created_at': None,
|
||||
'description': None,
|
||||
'dns_domain': None,
|
||||
'id': 'f054013d-7052-4708-9c72-2948a329fac3',
|
||||
'ipv4_address_scope': None,
|
||||
'ipv6_address_scope': None,
|
||||
'is_default': None,
|
||||
'mtu': None,
|
||||
'name': 'tellurium_net',
|
||||
'port_security_enabled': False,
|
||||
'project_id': None,
|
||||
'provider:network_type': None,
|
||||
'provider:physical_network': None,
|
||||
'provider:segmentation_id': None,
|
||||
'qos_policy_id': None,
|
||||
'revision_number': None,
|
||||
'router:external': False,
|
||||
'segments': None,
|
||||
'shared': False,
|
||||
'status': 'ACTIVE',
|
||||
'subnets': ['541f0782-587f-428b-bd79-ca227a66973b'],
|
||||
'tags': [],
|
||||
'updated_at': None,
|
||||
'vlan_transparent': None}]
|
183
flameclient/tests/fixtures/openstackcloud/ports.py
vendored
Normal file
183
flameclient/tests/fixtures/openstackcloud/ports.py
vendored
Normal file
@ -0,0 +1,183 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# This software is released under the MIT License.
|
||||
#
|
||||
# Copyright (c) 2018 Orange Cloud for Business / Cloudwatt
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
|
||||
NAME = 'network.ports'
|
||||
|
||||
FIXTURES = [{'admin_state_up': True,
|
||||
'allowed_address_pairs': None,
|
||||
'binding:host_id': None,
|
||||
'binding:profile': None,
|
||||
'binding:vif_details': None,
|
||||
'binding:vif_type': None,
|
||||
'binding:vnic_type': 'normal',
|
||||
'created_at': None,
|
||||
'data_plane_status': None,
|
||||
'description': None,
|
||||
'device_id': '2cf8db13-312a-4307-ba38-43b727ebcce6',
|
||||
'device_owner': 'compute:None',
|
||||
'dns_assignment': None,
|
||||
'dns_domain': None,
|
||||
'dns_name': None,
|
||||
'extra_dhcp_opts': None,
|
||||
'fixed_ips': [{'ip_address': '192.168.0.3',
|
||||
'subnet_id': '541f0782-587f-428b-bd79-ca227a66973b'}],
|
||||
'id': '3decf6f8-2591-4ab0-af19-00f6ce6a0cf5',
|
||||
'mac_address': '02:3d:ec:f6:f8:25',
|
||||
'name': 'Tellurium_Fixtures-windows_port-hxvnswbzi56x',
|
||||
'network_id': 'f054013d-7052-4708-9c72-2948a329fac3',
|
||||
'port_security_enabled': False,
|
||||
'qos_policy_id': None,
|
||||
'revision_number': None,
|
||||
'security_groups': ['9ffd2654-7ca6-48ae-852d-6503d5ce4a60'],
|
||||
'status': 'ACTIVE',
|
||||
'tags': [],
|
||||
'tenant_id': '9824a7403a1b411d8d207d26218597ce',
|
||||
'trunk_details': None,
|
||||
'updated_at': None},
|
||||
{'admin_state_up': True,
|
||||
'allowed_address_pairs': None,
|
||||
'binding:host_id': None,
|
||||
'binding:profile': None,
|
||||
'binding:vif_details': None,
|
||||
'binding:vif_type': None,
|
||||
'binding:vnic_type': 'normal',
|
||||
'created_at': None,
|
||||
'data_plane_status': None,
|
||||
'description': None,
|
||||
'device_id': '4add78fa-93df-4550-aaf7-aba2239ba00a',
|
||||
'device_owner': 'compute:None',
|
||||
'dns_assignment': None,
|
||||
'dns_domain': None,
|
||||
'dns_name': None,
|
||||
'extra_dhcp_opts': None,
|
||||
'fixed_ips': [{'ip_address': '192.168.0.4',
|
||||
'subnet_id': '541f0782-587f-428b-bd79-ca227a66973b'}],
|
||||
'id': '206df716-da1a-4a50-ba1a-74f42a007dd0',
|
||||
'mac_address': '02:20:6d:f7:16:da',
|
||||
'name': 'Tellurium_Fixtures-instance_port-fmln6fjl4yvo',
|
||||
'network_id': 'f054013d-7052-4708-9c72-2948a329fac3',
|
||||
'port_security_enabled': False,
|
||||
'qos_policy_id': None,
|
||||
'revision_number': None,
|
||||
'security_groups': ['9ffd2654-7ca6-48ae-852d-6503d5ce4a60'],
|
||||
'status': 'ACTIVE',
|
||||
'tags': [],
|
||||
'tenant_id': '9824a7403a1b411d8d207d26218597ce',
|
||||
'trunk_details': None,
|
||||
'updated_at': None},
|
||||
{'admin_state_up': True,
|
||||
'allowed_address_pairs': None,
|
||||
'binding:host_id': None,
|
||||
'binding:profile': None,
|
||||
'binding:vif_details': None,
|
||||
'binding:vif_type': None,
|
||||
'binding:vnic_type': 'normal',
|
||||
'created_at': None,
|
||||
'data_plane_status': None,
|
||||
'description': None,
|
||||
'device_id': 'b6316031-e629-48b8-aac5-3f1b21ffe0f3',
|
||||
'device_owner': 'compute:None',
|
||||
'dns_assignment': None,
|
||||
'dns_domain': None,
|
||||
'dns_name': None,
|
||||
'extra_dhcp_opts': None,
|
||||
'fixed_ips': [{'ip_address': '192.168.0.5',
|
||||
'subnet_id': '541f0782-587f-428b-bd79-ca227a66973b'}],
|
||||
'id': 'cb336b60-f298-4a51-9443-89880e3cdb51',
|
||||
'mac_address': '02:cb:33:6b:60:f2',
|
||||
'name': 'Tellurium_Fixtures-windows_ssh_pass_port-4zlwanbetsg2',
|
||||
'network_id': 'f054013d-7052-4708-9c72-2948a329fac3',
|
||||
'port_security_enabled': False,
|
||||
'qos_policy_id': None,
|
||||
'revision_number': None,
|
||||
'security_groups': ['9ffd2654-7ca6-48ae-852d-6503d5ce4a60'],
|
||||
'status': 'ACTIVE',
|
||||
'tags': [],
|
||||
'tenant_id': '9824a7403a1b411d8d207d26218597ce',
|
||||
'trunk_details': None,
|
||||
'updated_at': None},
|
||||
{'admin_state_up': True,
|
||||
'allowed_address_pairs': None,
|
||||
'binding:host_id': None,
|
||||
'binding:profile': None,
|
||||
'binding:vif_details': None,
|
||||
'binding:vif_type': None,
|
||||
'binding:vnic_type': 'normal',
|
||||
'created_at': None,
|
||||
'data_plane_status': None,
|
||||
'description': None,
|
||||
'device_id': 'ebc6dd0c-a276-4368-8084-bd37c587cc24',
|
||||
'device_owner': 'network:router_interface',
|
||||
'dns_assignment': None,
|
||||
'dns_domain': None,
|
||||
'dns_name': None,
|
||||
'extra_dhcp_opts': None,
|
||||
'fixed_ips': [{'ip_address': '192.168.0.1',
|
||||
'subnet_id': '541f0782-587f-428b-bd79-ca227a66973b'}],
|
||||
'id': 'e3b88764-3c46-44aa-ae26-fa6ec2df93bd',
|
||||
'mac_address': '02:e3:b8:87:64:3c',
|
||||
'name': 'e3b88764-3c46-44aa-ae26-fa6ec2df93bd',
|
||||
'network_id': 'f054013d-7052-4708-9c72-2948a329fac3',
|
||||
'port_security_enabled': False,
|
||||
'qos_policy_id': None,
|
||||
'revision_number': None,
|
||||
'security_groups': ['9ffd2654-7ca6-48ae-852d-6503d5ce4a60'],
|
||||
'status': 'ACTIVE',
|
||||
'tags': [],
|
||||
'tenant_id': '9824a7403a1b411d8d207d26218597ce',
|
||||
'trunk_details': None,
|
||||
'updated_at': None},
|
||||
{'admin_state_up': True,
|
||||
'allowed_address_pairs': None,
|
||||
'binding:host_id': None,
|
||||
'binding:profile': None,
|
||||
'binding:vif_details': None,
|
||||
'binding:vif_type': None,
|
||||
'binding:vnic_type': 'normal',
|
||||
'created_at': None,
|
||||
'data_plane_status': None,
|
||||
'description': None,
|
||||
'device_id': '99c42e21-5099-4903-9121-063925aad299',
|
||||
'device_owner': 'compute:nova',
|
||||
'dns_assignment': None,
|
||||
'dns_domain': None,
|
||||
'dns_name': None,
|
||||
'extra_dhcp_opts': None,
|
||||
'fixed_ips': [{'ip_address': '192.168.0.6',
|
||||
'subnet_id': '541f0782-587f-428b-bd79-ca227a66973b'}],
|
||||
'id': '4f413432-b499-4fcc-a81a-1ee0d8bc16b7',
|
||||
'mac_address': '02:4f:41:34:32:b4',
|
||||
'name': '4f413432-b499-4fcc-a81a-1ee0d8bc16b7',
|
||||
'network_id': 'f054013d-7052-4708-9c72-2948a329fac3',
|
||||
'port_security_enabled': False,
|
||||
'qos_policy_id': None,
|
||||
'revision_number': None,
|
||||
'security_groups': ['156799a3-565e-48b3-938c-f95f09093c66',
|
||||
'9ffd2654-7ca6-48ae-852d-6503d5ce4a60'],
|
||||
'status': 'ACTIVE',
|
||||
'tags': [],
|
||||
'tenant_id': '9824a7403a1b411d8d207d26218597ce',
|
||||
'trunk_details': None,
|
||||
'updated_at': None}]
|
45
flameclient/tests/fixtures/openstackcloud/routers.py
vendored
Normal file
45
flameclient/tests/fixtures/openstackcloud/routers.py
vendored
Normal file
@ -0,0 +1,45 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# This software is released under the MIT License.
|
||||
#
|
||||
# Copyright (c) 2018 Orange Cloud for Business / Cloudwatt
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
|
||||
NAME = 'network.routers'
|
||||
|
||||
FIXTURES = [{'admin_state_up': True,
|
||||
'availability_zone_hints': None,
|
||||
'availability_zones': None,
|
||||
'created_at': None,
|
||||
'description': None,
|
||||
'distributed': None,
|
||||
'external_gateway_info': {'enable_snat': True,
|
||||
'network_id': '6ea98324-0f14-49f6-97c0-885d1b8dc517'},
|
||||
'flavor_id': None,
|
||||
'ha': None,
|
||||
'id': 'ebc6dd0c-a276-4368-8084-bd37c587cc24',
|
||||
'name': 'tellurium_router',
|
||||
'revision': None,
|
||||
'routes': None,
|
||||
'status': 'ACTIVE',
|
||||
'tags': [],
|
||||
'tenant_id': '9824a7403a1b411d8d207d26218597ce',
|
||||
'updated_at': None}]
|
113
flameclient/tests/fixtures/openstackcloud/security_groups.py
vendored
Normal file
113
flameclient/tests/fixtures/openstackcloud/security_groups.py
vendored
Normal file
@ -0,0 +1,113 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# This software is released under the MIT License.
|
||||
#
|
||||
# Copyright (c) 2018 Orange Cloud for Business / Cloudwatt
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
|
||||
NAME = 'network.security_groups'
|
||||
|
||||
FIXTURES = [{'created_at': None,
|
||||
'description': None,
|
||||
'id': '9ffd2654-7ca6-48ae-852d-6503d5ce4a60',
|
||||
'name': 'default',
|
||||
'revision_number': None,
|
||||
'security_group_rules': [{'direction': 'ingress',
|
||||
'ethertype': 'IPv4',
|
||||
'id': 'ec72eaca-22e2-47b6-b1a5-2fe6f8129e47',
|
||||
'port_range_max': None,
|
||||
'port_range_min': None,
|
||||
'protocol': None,
|
||||
'remote_group_id': '9ffd2654-7ca6-48ae-852d-6503d5ce4a60',
|
||||
'remote_ip_prefix': None,
|
||||
'security_group_id': '9ffd2654-7ca6-48ae-852d-6503d5ce4a60',
|
||||
'tenant_id': '9824a7403a1b411d8d207d26218597ce'},
|
||||
{'direction': 'ingress',
|
||||
'ethertype': 'IPv6',
|
||||
'id': 'd5720f56-e7ce-4c7f-982d-a70d76c37b11',
|
||||
'port_range_max': None,
|
||||
'port_range_min': None,
|
||||
'protocol': None,
|
||||
'remote_group_id': '9ffd2654-7ca6-48ae-852d-6503d5ce4a60',
|
||||
'remote_ip_prefix': None,
|
||||
'security_group_id': '9ffd2654-7ca6-48ae-852d-6503d5ce4a60',
|
||||
'tenant_id': '9824a7403a1b411d8d207d26218597ce'},
|
||||
{'direction': 'egress',
|
||||
'ethertype': 'IPv4',
|
||||
'id': 'd05bc784-b34c-4e0c-a2ea-7b10992caa1e',
|
||||
'port_range_max': None,
|
||||
'port_range_min': None,
|
||||
'protocol': None,
|
||||
'remote_group_id': None,
|
||||
'remote_ip_prefix': '0.0.0.0/0',
|
||||
'security_group_id': '9ffd2654-7ca6-48ae-852d-6503d5ce4a60',
|
||||
'tenant_id': '9824a7403a1b411d8d207d26218597ce'},
|
||||
{'direction': 'egress',
|
||||
'ethertype': 'IPv6',
|
||||
'id': 'a6abbc8e-92c2-42f6-9ac9-a04544588739',
|
||||
'port_range_max': None,
|
||||
'port_range_min': None,
|
||||
'protocol': None,
|
||||
'remote_group_id': None,
|
||||
'remote_ip_prefix': '::/0',
|
||||
'security_group_id': '9ffd2654-7ca6-48ae-852d-6503d5ce4a60',
|
||||
'tenant_id': '9824a7403a1b411d8d207d26218597ce'}],
|
||||
'tags': [],
|
||||
'tenant_id': '9824a7403a1b411d8d207d26218597ce',
|
||||
'updated_at': None},
|
||||
{'created_at': None,
|
||||
'description': '',
|
||||
'id': '156799a3-565e-48b3-938c-f95f09093c66',
|
||||
'name': 'http',
|
||||
'revision_number': None,
|
||||
'security_group_rules': [{'direction': 'egress',
|
||||
'ethertype': 'IPv4',
|
||||
'id': '80508f7d-b893-4bcb-bddc-51a946634492',
|
||||
'port_range_max': None,
|
||||
'port_range_min': None,
|
||||
'protocol': None,
|
||||
'remote_group_id': None,
|
||||
'remote_ip_prefix': '0.0.0.0/0',
|
||||
'security_group_id': '156799a3-565e-48b3-938c-f95f09093c66',
|
||||
'tenant_id': '9824a7403a1b411d8d207d26218597ce'},
|
||||
{'direction': 'egress',
|
||||
'ethertype': 'IPv6',
|
||||
'id': 'eab50b80-bc3c-484c-a3c8-fd6cf5ee9c50',
|
||||
'port_range_max': None,
|
||||
'port_range_min': None,
|
||||
'protocol': None,
|
||||
'remote_group_id': None,
|
||||
'remote_ip_prefix': None,
|
||||
'security_group_id': '156799a3-565e-48b3-938c-f95f09093c66',
|
||||
'tenant_id': '9824a7403a1b411d8d207d26218597ce'},
|
||||
{'direction': 'ingress',
|
||||
'ethertype': 'IPv4',
|
||||
'id': 'a6ed0dc8-ee29-462e-84a0-961675e08c4a',
|
||||
'port_range_max': 80,
|
||||
'port_range_min': 80,
|
||||
'protocol': 'tcp',
|
||||
'remote_group_id': None,
|
||||
'remote_ip_prefix': '0.0.0.0/0',
|
||||
'security_group_id': '156799a3-565e-48b3-938c-f95f09093c66',
|
||||
'tenant_id': '9824a7403a1b411d8d207d26218597ce'}],
|
||||
'tags': [],
|
||||
'tenant_id': '9824a7403a1b411d8d207d26218597ce',
|
||||
'updated_at': None}]
|
28
flameclient/tests/fixtures/openstackcloud/server_groups.py
vendored
Normal file
28
flameclient/tests/fixtures/openstackcloud/server_groups.py
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# This software is released under the MIT License.
|
||||
#
|
||||
# Copyright (c) 2018 Orange Cloud for Business / Cloudwatt
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
|
||||
NAME = 'compute.server_groups'
|
||||
|
||||
FIXTURES = []
|
213
flameclient/tests/fixtures/openstackcloud/servers.py
vendored
Normal file
213
flameclient/tests/fixtures/openstackcloud/servers.py
vendored
Normal file
@ -0,0 +1,213 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# This software is released under the MIT License.
|
||||
#
|
||||
# Copyright (c) 2018 Orange Cloud for Business / Cloudwatt
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
|
||||
NAME = 'compute.servers'
|
||||
|
||||
FIXTURES = [{'OS-DCF:diskConfig': 'AUTO',
|
||||
'OS-EXT-AZ:availability_zone': 'nova',
|
||||
'OS-EXT-SRV-ATTR:hypervisor_hostname': None,
|
||||
'OS-EXT-SRV-ATTR:instance_name': None,
|
||||
'OS-EXT-SRV-ATTR:user_data': None,
|
||||
'OS-EXT-STS:power_state': 1,
|
||||
'OS-EXT-STS:task_state': None,
|
||||
'OS-EXT-STS:vm_state': 'active',
|
||||
'OS-SCH-HNT:scheduler_hints': None,
|
||||
'OS-SRV-USG:launched_at': '2018-11-09T13:39:42.000000',
|
||||
'OS-SRV-USG:terminated_at': None,
|
||||
'accessIPv4': '',
|
||||
'accessIPv6': '',
|
||||
'addresses': {'tellurium_net': [{'OS-EXT-IPS-MAC:mac_addr': '02:4f:41:34:32:b4',
|
||||
'OS-EXT-IPS:type': 'fixed',
|
||||
'addr': '192.168.0.6',
|
||||
'version': 4}]},
|
||||
'adminPass': None,
|
||||
'block_device_mapping_v2': None,
|
||||
'config_drive': '',
|
||||
'created': '2018-11-09T13:39:38Z',
|
||||
'flavor': {'id': '17',
|
||||
'links': [{'href': 'https://compute.fr1.cloudwatt.com/9824a7403a1b411d8d207d26218597ce/flavors/17',
|
||||
'rel': 'bookmark'}]},
|
||||
'flavorRef': None,
|
||||
'hostId': '84246cf2f8ac920628901e7a84a054b45f246f2d77f6df3f6c30cc43',
|
||||
'id': '99c42e21-5099-4903-9121-063925aad299',
|
||||
'image': {},
|
||||
'imageRef': None,
|
||||
'key_name': 'tellurium-key',
|
||||
'links': [{'href': 'https://compute.fr1.cloudwatt.com/v2/9824a7403a1b411d8d207d26218597ce/servers/99c42e21-5099-4903-9121-063925aad299',
|
||||
'rel': 'self'},
|
||||
{'href': 'https://compute.fr1.cloudwatt.com/9824a7403a1b411d8d207d26218597ce/servers/99c42e21-5099-4903-9121-063925aad299',
|
||||
'rel': 'bookmark'}],
|
||||
'metadata': {},
|
||||
'name': 'Ubuntu 14.04',
|
||||
'networks': None,
|
||||
'os-extended-volumes:volumes_attached': [{'id': '8ca10346-fe4c-4e68-9a18-98df875d1ecc'}],
|
||||
'personality': None,
|
||||
'progress': 0,
|
||||
'security_groups': [{'name': 'http'}, {'name': 'default'}],
|
||||
'status': 'ACTIVE',
|
||||
'tenant_id': '9824a7403a1b411d8d207d26218597ce',
|
||||
'updated': '2018-11-09T13:39:42Z',
|
||||
'user_id': '7f71ea7b8abd41e5a1f303f4a1bc16b9'},
|
||||
{'OS-DCF:diskConfig': 'MANUAL',
|
||||
'OS-EXT-AZ:availability_zone': 'nova',
|
||||
'OS-EXT-SRV-ATTR:hypervisor_hostname': None,
|
||||
'OS-EXT-SRV-ATTR:instance_name': None,
|
||||
'OS-EXT-SRV-ATTR:user_data': None,
|
||||
'OS-EXT-STS:power_state': 1,
|
||||
'OS-EXT-STS:task_state': None,
|
||||
'OS-EXT-STS:vm_state': 'active',
|
||||
'OS-SCH-HNT:scheduler_hints': None,
|
||||
'OS-SRV-USG:launched_at': '2018-11-09T04:54:35.000000',
|
||||
'OS-SRV-USG:terminated_at': None,
|
||||
'accessIPv4': '',
|
||||
'accessIPv6': '',
|
||||
'addresses': {'tellurium_net': [{'OS-EXT-IPS-MAC:mac_addr': '02:3d:ec:f6:f8:25',
|
||||
'OS-EXT-IPS:type': 'fixed',
|
||||
'addr': '192.168.0.3',
|
||||
'version': 4}]},
|
||||
'adminPass': None,
|
||||
'block_device_mapping_v2': None,
|
||||
'config_drive': '',
|
||||
'created': '2018-11-09T04:54:32Z',
|
||||
'flavor': {'id': '42',
|
||||
'links': [{'href': 'https://compute.fr1.cloudwatt.com/9824a7403a1b411d8d207d26218597ce/flavors/42',
|
||||
'rel': 'bookmark'}]},
|
||||
'flavorRef': None,
|
||||
'hostId': 'dd853263647ff603cfe0726dc78e34e0b9b2fc092bead501af233bcf',
|
||||
'id': '2cf8db13-312a-4307-ba38-43b727ebcce6',
|
||||
'image': {'id': '8254d703-e46f-4101-88ff-6f40bf7df51a',
|
||||
'links': [{'href': 'https://compute.fr1.cloudwatt.com/9824a7403a1b411d8d207d26218597ce/images/8254d703-e46f-4101-88ff-6f40bf7df51a',
|
||||
'rel': 'bookmark'}]},
|
||||
'imageRef': None,
|
||||
'key_name': 'tellurium-key',
|
||||
'links': [{'href': 'https://compute.fr1.cloudwatt.com/v2/9824a7403a1b411d8d207d26218597ce/servers/2cf8db13-312a-4307-ba38-43b727ebcce6',
|
||||
'rel': 'self'},
|
||||
{'href': 'https://compute.fr1.cloudwatt.com/9824a7403a1b411d8d207d26218597ce/servers/2cf8db13-312a-4307-ba38-43b727ebcce6',
|
||||
'rel': 'bookmark'}],
|
||||
'metadata': {},
|
||||
'name': 'tellurium_win_instance',
|
||||
'networks': None,
|
||||
'os-extended-volumes:volumes_attached': [],
|
||||
'personality': None,
|
||||
'progress': 0,
|
||||
'security_groups': [{'name': 'default'}],
|
||||
'status': 'ACTIVE',
|
||||
'tenant_id': '9824a7403a1b411d8d207d26218597ce',
|
||||
'updated': '2018-11-09T04:55:58Z',
|
||||
'user_id': '7f71ea7b8abd41e5a1f303f4a1bc16b9'},
|
||||
{'OS-DCF:diskConfig': 'MANUAL',
|
||||
'OS-EXT-AZ:availability_zone': 'nova',
|
||||
'OS-EXT-SRV-ATTR:hypervisor_hostname': None,
|
||||
'OS-EXT-SRV-ATTR:instance_name': None,
|
||||
'OS-EXT-SRV-ATTR:user_data': None,
|
||||
'OS-EXT-STS:power_state': 1,
|
||||
'OS-EXT-STS:task_state': None,
|
||||
'OS-EXT-STS:vm_state': 'active',
|
||||
'OS-SCH-HNT:scheduler_hints': None,
|
||||
'OS-SRV-USG:launched_at': '2018-11-09T04:57:15.000000',
|
||||
'OS-SRV-USG:terminated_at': None,
|
||||
'accessIPv4': '',
|
||||
'accessIPv6': '',
|
||||
'addresses': {'tellurium_net': [{'OS-EXT-IPS-MAC:mac_addr': '02:cb:33:6b:60:f2',
|
||||
'OS-EXT-IPS:type': 'fixed',
|
||||
'addr': '192.168.0.5',
|
||||
'version': 4}]},
|
||||
'adminPass': None,
|
||||
'block_device_mapping_v2': None,
|
||||
'config_drive': '',
|
||||
'created': '2018-11-09T04:54:32Z',
|
||||
'flavor': {'id': '42',
|
||||
'links': [{'href': 'https://compute.fr1.cloudwatt.com/9824a7403a1b411d8d207d26218597ce/flavors/42',
|
||||
'rel': 'bookmark'}]},
|
||||
'flavorRef': None,
|
||||
'hostId': 'b357f8b6b7368a07bb2aed776c6579d132c90f7dcb2f28a2a34c98e8',
|
||||
'id': 'b6316031-e629-48b8-aac5-3f1b21ffe0f3',
|
||||
'image': {'id': '8254d703-e46f-4101-88ff-6f40bf7df51a',
|
||||
'links': [{'href': 'https://compute.fr1.cloudwatt.com/9824a7403a1b411d8d207d26218597ce/images/8254d703-e46f-4101-88ff-6f40bf7df51a',
|
||||
'rel': 'bookmark'}]},
|
||||
'imageRef': None,
|
||||
'key_name': 'tellurium-key-phrase',
|
||||
'links': [{'href': 'https://compute.fr1.cloudwatt.com/v2/9824a7403a1b411d8d207d26218597ce/servers/b6316031-e629-48b8-aac5-3f1b21ffe0f3',
|
||||
'rel': 'self'},
|
||||
{'href': 'https://compute.fr1.cloudwatt.com/9824a7403a1b411d8d207d26218597ce/servers/b6316031-e629-48b8-aac5-3f1b21ffe0f3',
|
||||
'rel': 'bookmark'}],
|
||||
'metadata': {},
|
||||
'name': 'tellurium_win_instance_ssh_pass',
|
||||
'networks': None,
|
||||
'os-extended-volumes:volumes_attached': [],
|
||||
'personality': None,
|
||||
'progress': 0,
|
||||
'security_groups': [{'name': 'default'}],
|
||||
'status': 'ACTIVE',
|
||||
'tenant_id': '9824a7403a1b411d8d207d26218597ce',
|
||||
'updated': '2018-11-09T04:59:08Z',
|
||||
'user_id': '7f71ea7b8abd41e5a1f303f4a1bc16b9'},
|
||||
{'OS-DCF:diskConfig': 'MANUAL',
|
||||
'OS-EXT-AZ:availability_zone': 'nova',
|
||||
'OS-EXT-SRV-ATTR:hypervisor_hostname': None,
|
||||
'OS-EXT-SRV-ATTR:instance_name': None,
|
||||
'OS-EXT-SRV-ATTR:user_data': None,
|
||||
'OS-EXT-STS:power_state': 1,
|
||||
'OS-EXT-STS:task_state': None,
|
||||
'OS-EXT-STS:vm_state': 'active',
|
||||
'OS-SCH-HNT:scheduler_hints': None,
|
||||
'OS-SRV-USG:launched_at': '2018-11-09T04:54:36.000000',
|
||||
'OS-SRV-USG:terminated_at': None,
|
||||
'accessIPv4': '',
|
||||
'accessIPv6': '',
|
||||
'addresses': {'tellurium_net': [{'OS-EXT-IPS-MAC:mac_addr': '02:20:6d:f7:16:da',
|
||||
'OS-EXT-IPS:type': 'fixed',
|
||||
'addr': '192.168.0.4',
|
||||
'version': 4}]},
|
||||
'adminPass': None,
|
||||
'block_device_mapping_v2': None,
|
||||
'config_drive': '',
|
||||
'created': '2018-11-09T04:54:32Z',
|
||||
'flavor': {'id': '16',
|
||||
'links': [{'href': 'https://compute.fr1.cloudwatt.com/9824a7403a1b411d8d207d26218597ce/flavors/16',
|
||||
'rel': 'bookmark'}]},
|
||||
'flavorRef': None,
|
||||
'hostId': 'a5586828459ec792613bc24c0807801ce4341a562d47ff3203d41722',
|
||||
'id': '4add78fa-93df-4550-aaf7-aba2239ba00a',
|
||||
'image': {'id': 'dd7d4b21-79b8-42f0-8464-0d1a5274c638',
|
||||
'links': [{'href': 'https://compute.fr1.cloudwatt.com/9824a7403a1b411d8d207d26218597ce/images/dd7d4b21-79b8-42f0-8464-0d1a5274c638',
|
||||
'rel': 'bookmark'}]},
|
||||
'imageRef': None,
|
||||
'key_name': 'tellurium-key',
|
||||
'links': [{'href': 'https://compute.fr1.cloudwatt.com/v2/9824a7403a1b411d8d207d26218597ce/servers/4add78fa-93df-4550-aaf7-aba2239ba00a',
|
||||
'rel': 'self'},
|
||||
{'href': 'https://compute.fr1.cloudwatt.com/9824a7403a1b411d8d207d26218597ce/servers/4add78fa-93df-4550-aaf7-aba2239ba00a',
|
||||
'rel': 'bookmark'}],
|
||||
'metadata': {},
|
||||
'name': 'tellurium_instance',
|
||||
'networks': None,
|
||||
'os-extended-volumes:volumes_attached': [],
|
||||
'personality': None,
|
||||
'progress': 0,
|
||||
'security_groups': [{'name': 'default'}],
|
||||
'status': 'ACTIVE',
|
||||
'tenant_id': '9824a7403a1b411d8d207d26218597ce',
|
||||
'updated': '2018-11-09T05:22:45Z',
|
||||
'user_id': '7f71ea7b8abd41e5a1f303f4a1bc16b9'}]
|
49
flameclient/tests/fixtures/openstackcloud/subnets.py
vendored
Normal file
49
flameclient/tests/fixtures/openstackcloud/subnets.py
vendored
Normal file
@ -0,0 +1,49 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# This software is released under the MIT License.
|
||||
#
|
||||
# Copyright (c) 2018 Orange Cloud for Business / Cloudwatt
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
|
||||
NAME = 'network.subnets'
|
||||
|
||||
FIXTURES = [{'allocation_pools': [{'end': '192.168.0.254', 'start': '192.168.0.2'}],
|
||||
'cidr': '192.168.0.0/24',
|
||||
'created_at': None,
|
||||
'description': None,
|
||||
'dns_nameservers': ['8.8.8.8'],
|
||||
'enable_dhcp': True,
|
||||
'gateway_ip': '192.168.0.1',
|
||||
'host_routes': [],
|
||||
'id': '541f0782-587f-428b-bd79-ca227a66973b',
|
||||
'ip_version': 4,
|
||||
'ipv6_address_mode': None,
|
||||
'ipv6_ra_mode': None,
|
||||
'name': 'tellurium_net_subnet',
|
||||
'network_id': 'f054013d-7052-4708-9c72-2948a329fac3',
|
||||
'revision_number': None,
|
||||
'segment_id': None,
|
||||
'service_types': None,
|
||||
'subnetpool_id': None,
|
||||
'tags': [],
|
||||
'tenant_id': '9824a7403a1b411d8d207d26218597ce',
|
||||
'updated_at': None,
|
||||
'use_default_subnetpool': None}]
|
102
flameclient/tests/fixtures/openstackcloud/volumes.py
vendored
Normal file
102
flameclient/tests/fixtures/openstackcloud/volumes.py
vendored
Normal file
@ -0,0 +1,102 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# This software is released under the MIT License.
|
||||
#
|
||||
# Copyright (c) 2018 Orange Cloud for Business / Cloudwatt
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
|
||||
NAME = 'volume.volumes'
|
||||
|
||||
FIXTURES = [{'attachments': [{'attached_at': '2018-11-09T13:39:41.000000',
|
||||
'attachment_id': '7edd34f8-5c1b-4c46-afac-916db0e10726',
|
||||
'device': '/dev/vda',
|
||||
'host_name': None,
|
||||
'id': '8ca10346-fe4c-4e68-9a18-98df875d1ecc',
|
||||
'server_id': '99c42e21-5099-4903-9121-063925aad299',
|
||||
'volume_id': '8ca10346-fe4c-4e68-9a18-98df875d1ecc'}],
|
||||
'availability_zone': 'prd1',
|
||||
'bootable': True,
|
||||
'consistencygroup_id': None,
|
||||
'created_at': '2018-11-09T13:34:08.000000',
|
||||
'description': '',
|
||||
'encrypted': False,
|
||||
'id': '8ca10346-fe4c-4e68-9a18-98df875d1ecc',
|
||||
'imageRef': None,
|
||||
'links': [{'href': 'https://volume.fr1.cloudwatt.com/v2/9824a7403a1b411d8d207d26218597ce/volumes/8ca10346-fe4c-4e68-9a18-98df875d1ecc',
|
||||
'rel': 'self'},
|
||||
{'href': 'https://volume.fr1.cloudwatt.com/9824a7403a1b411d8d207d26218597ce/volumes/8ca10346-fe4c-4e68-9a18-98df875d1ecc',
|
||||
'rel': 'bookmark'}],
|
||||
'metadata': {'attached_mode': 'rw', 'readonly': 'False'},
|
||||
'name': 'Ubuntu 14.04',
|
||||
'os-vol-host-attr:host': None,
|
||||
'os-vol-mig-status-attr:migstat': None,
|
||||
'os-vol-mig-status-attr:name_id': None,
|
||||
'os-vol-tenant-attr:tenant_id': '9824a7403a1b411d8d207d26218597ce',
|
||||
'os-volume-replication:driver_data': None,
|
||||
'os-volume-replication:extended_status': None,
|
||||
'replication_status': 'disabled',
|
||||
'size': 20,
|
||||
'snapshot_id': None,
|
||||
'source_volid': None,
|
||||
'status': 'in-use',
|
||||
'volume_image_metadata': {'checksum': '8ec802fe753dfe8e226645a2e0106bf7',
|
||||
'container_format': 'bare',
|
||||
'cw_cat': 'open_source',
|
||||
'cw_logo': 'lin-ubuntu.png',
|
||||
'cw_origin': 'Cloudwatt',
|
||||
'cw_os': 'Ubuntu',
|
||||
'disk_format': 'qcow2',
|
||||
'hw_cpu_max_sockets': '1',
|
||||
'hw_rng_model': 'virtio',
|
||||
'image_id': '70a9c910-dd99-4065-bce9-11e89bc479fe',
|
||||
'image_name': 'Ubuntu 14.04',
|
||||
'min_disk': '20',
|
||||
'min_ram': '0',
|
||||
'size': '1009057792'},
|
||||
'volume_type': 'standard'},
|
||||
{'attachments': [],
|
||||
'availability_zone': 'prd1',
|
||||
'bootable': False,
|
||||
'consistencygroup_id': None,
|
||||
'created_at': '2018-11-09T04:54:29.000000',
|
||||
'description': None,
|
||||
'encrypted': False,
|
||||
'id': '34ce951a-f2d9-4bdd-904d-9f70269c680b',
|
||||
'imageRef': None,
|
||||
'links': [{'href': 'https://volume.fr1.cloudwatt.com/v2/9824a7403a1b411d8d207d26218597ce/volumes/34ce951a-f2d9-4bdd-904d-9f70269c680b',
|
||||
'rel': 'self'},
|
||||
{'href': 'https://volume.fr1.cloudwatt.com/9824a7403a1b411d8d207d26218597ce/volumes/34ce951a-f2d9-4bdd-904d-9f70269c680b',
|
||||
'rel': 'bookmark'}],
|
||||
'metadata': {},
|
||||
'name': 'tellurium_volume',
|
||||
'os-vol-host-attr:host': None,
|
||||
'os-vol-mig-status-attr:migstat': None,
|
||||
'os-vol-mig-status-attr:name_id': None,
|
||||
'os-vol-tenant-attr:tenant_id': '9824a7403a1b411d8d207d26218597ce',
|
||||
'os-volume-replication:driver_data': None,
|
||||
'os-volume-replication:extended_status': None,
|
||||
'replication_status': 'disabled',
|
||||
'size': 5,
|
||||
'snapshot_id': None,
|
||||
'source_volid': None,
|
||||
'status': 'available',
|
||||
'volume_image_metadata': {},
|
||||
'volume_type': 'standard'}]
|
0
flameclient/tests/fixtures/results/__init__.py
vendored
Normal file
0
flameclient/tests/fixtures/results/__init__.py
vendored
Normal file
225
flameclient/tests/fixtures/results/flame.yaml
vendored
Normal file
225
flameclient/tests/fixtures/results/flame.yaml
vendored
Normal file
@ -0,0 +1,225 @@
|
||||
description: Generated template
|
||||
heat_template_version: 2013-05-23
|
||||
parameters:
|
||||
external_network_for_floating_ip_0:
|
||||
default: 6ea98324-0f14-49f6-97c0-885d1b8dc517
|
||||
description: Network to allocate floating IP from
|
||||
type: string
|
||||
router_0_external_network:
|
||||
default: 6ea98324-0f14-49f6-97c0-885d1b8dc517
|
||||
description: Router external network
|
||||
type: string
|
||||
server_0_flavor:
|
||||
default: '17'
|
||||
description: Flavor to use for server server_0
|
||||
type: string
|
||||
server_1_flavor:
|
||||
default: '42'
|
||||
description: Flavor to use for server server_1
|
||||
type: string
|
||||
server_1_image:
|
||||
default: 8254d703-e46f-4101-88ff-6f40bf7df51a
|
||||
description: Image to use for server server_1
|
||||
type: string
|
||||
server_2_flavor:
|
||||
default: '42'
|
||||
description: Flavor to use for server server_2
|
||||
type: string
|
||||
server_2_image:
|
||||
default: 8254d703-e46f-4101-88ff-6f40bf7df51a
|
||||
description: Image to use for server server_2
|
||||
type: string
|
||||
server_3_flavor:
|
||||
default: '16'
|
||||
description: Flavor to use for server server_3
|
||||
type: string
|
||||
server_3_image:
|
||||
default: dd7d4b21-79b8-42f0-8464-0d1a5274c638
|
||||
description: Image to use for server server_3
|
||||
type: string
|
||||
volume_0_image:
|
||||
default: 70a9c910-dd99-4065-bce9-11e89bc479fe
|
||||
description: Image to create volume volume_0 from
|
||||
type: string
|
||||
volume_0_volume_type:
|
||||
default: standard
|
||||
description: Volume type for volume volume_0
|
||||
type: string
|
||||
volume_1_volume_type:
|
||||
default: standard
|
||||
description: Volume type for volume volume_1
|
||||
type: string
|
||||
resources:
|
||||
floating_ip_0:
|
||||
properties:
|
||||
floating_network_id:
|
||||
get_param: external_network_for_floating_ip_0
|
||||
type: OS::Neutron::FloatingIP
|
||||
keypair_0:
|
||||
properties:
|
||||
name: tellurium-key
|
||||
public_key: ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCwp5kVZ+3baPZllNXZDG2mivd5nJ5wWY6Jj/WV6NlO6cUiaH5om6itU3lyJxtAbLgbbvY2FjMg1PI2JI3EHx0OSPEbDdeNsQGi31qyuiB1S5p6TreI0Dfy0tywJ9G2CURjkuJnC8SvnMfVYLMFBvx7p8RzxSdDm/zrmc4KY3ktdfYQDNtEiH2jucUUiY0ipVkDNhhv03+5C9cnpaIcVDBkddE/KEME8NIIh7s6aYCXJEWJx85nOVVRD5qK7ouV6FcGVn6zqWRD3jn0iSxcFwiKx7p6M77PmJAY4gBIpWQmutok6T4ZrXxa7jE4dybwo5e8dyvGyc7WWGqXcmcinUWr
|
||||
Generated-by-Nova
|
||||
type: OS::Nova::KeyPair
|
||||
keypair_1:
|
||||
properties:
|
||||
name: tellurium-key-phrase
|
||||
public_key: ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCaYaTC6KCC2GURFMpRQiRq8Og10PcBbVnrQqluzi2E5vAqTHAegzivmGB8h2xrjXUfbKV2bE8kz2ZE66sq1yLO/jZ+rkOA+zLnOxNwkk3gQq57b26ZegPL2tTgottJTPGyPz6v2+LLtDf/+xTJMjkPKcMWylu12Js0XKVkdY35fwN7fRvA4xghtGu1GcmS2XFDMmeLDrG1KNPbBLj5cGoD723Ho7ZhAjLThoY/xMN2OYsSNzrg3S00QngZMzQvJf0ETrB3GtITk5FUs54qMRfiyUC72lw0gLTIJK8rs7fX/yeO+467afRt2xwHN50rEWJPeTVYWdlH/msh7NQ3LZ8/
|
||||
root@9b638ff21113
|
||||
type: OS::Nova::KeyPair
|
||||
network_1:
|
||||
properties:
|
||||
admin_state_up: true
|
||||
name: tellurium_net
|
||||
shared: false
|
||||
type: OS::Neutron::Net
|
||||
router_0:
|
||||
properties:
|
||||
admin_state_up: true
|
||||
name: tellurium_router
|
||||
type: OS::Neutron::Router
|
||||
router_0_gateway:
|
||||
properties:
|
||||
network_id:
|
||||
get_param: router_0_external_network
|
||||
router_id:
|
||||
get_resource: router_0
|
||||
type: OS::Neutron::RouterGateway
|
||||
router_0_interface_3:
|
||||
properties:
|
||||
router_id:
|
||||
get_resource: router_0
|
||||
subnet_id:
|
||||
get_resource: subnet_0
|
||||
type: OS::Neutron::RouterInterface
|
||||
security_group_0:
|
||||
properties:
|
||||
name: _default
|
||||
rules:
|
||||
- direction: ingress
|
||||
ethertype: IPv4
|
||||
remote_mode: remote_group_id
|
||||
- direction: ingress
|
||||
ethertype: IPv6
|
||||
remote_mode: remote_group_id
|
||||
- direction: egress
|
||||
ethertype: IPv4
|
||||
remote_ip_prefix: 0.0.0.0/0
|
||||
- direction: egress
|
||||
ethertype: IPv6
|
||||
remote_ip_prefix: ::/0
|
||||
type: OS::Neutron::SecurityGroup
|
||||
security_group_1:
|
||||
properties:
|
||||
description: ''
|
||||
name: http
|
||||
rules:
|
||||
- direction: egress
|
||||
ethertype: IPv4
|
||||
remote_ip_prefix: 0.0.0.0/0
|
||||
- direction: egress
|
||||
ethertype: IPv6
|
||||
- direction: ingress
|
||||
ethertype: IPv4
|
||||
port_range_max: 80
|
||||
port_range_min: 80
|
||||
protocol: tcp
|
||||
remote_ip_prefix: 0.0.0.0/0
|
||||
type: OS::Neutron::SecurityGroup
|
||||
server_0:
|
||||
properties:
|
||||
block_device_mapping_v2:
|
||||
- device_name: /dev/vda
|
||||
volume_id:
|
||||
get_resource: volume_0
|
||||
flavor:
|
||||
get_param: server_0_flavor
|
||||
key_name:
|
||||
get_resource: keypair_0
|
||||
name: Ubuntu 14.04
|
||||
networks:
|
||||
- network:
|
||||
get_resource: network_1
|
||||
security_groups:
|
||||
- get_resource: security_group_1
|
||||
- get_resource: security_group_0
|
||||
type: OS::Nova::Server
|
||||
server_1:
|
||||
properties:
|
||||
flavor:
|
||||
get_param: server_1_flavor
|
||||
image:
|
||||
get_param: server_1_image
|
||||
key_name:
|
||||
get_resource: keypair_0
|
||||
name: tellurium_win_instance
|
||||
networks:
|
||||
- network:
|
||||
get_resource: network_1
|
||||
security_groups:
|
||||
- get_resource: security_group_0
|
||||
type: OS::Nova::Server
|
||||
server_2:
|
||||
properties:
|
||||
flavor:
|
||||
get_param: server_2_flavor
|
||||
image:
|
||||
get_param: server_2_image
|
||||
key_name:
|
||||
get_resource: keypair_1
|
||||
name: tellurium_win_instance_ssh_pass
|
||||
networks:
|
||||
- network:
|
||||
get_resource: network_1
|
||||
security_groups:
|
||||
- get_resource: security_group_0
|
||||
type: OS::Nova::Server
|
||||
server_3:
|
||||
properties:
|
||||
flavor:
|
||||
get_param: server_3_flavor
|
||||
image:
|
||||
get_param: server_3_image
|
||||
key_name:
|
||||
get_resource: keypair_0
|
||||
name: tellurium_instance
|
||||
networks:
|
||||
- network:
|
||||
get_resource: network_1
|
||||
security_groups:
|
||||
- get_resource: security_group_0
|
||||
type: OS::Nova::Server
|
||||
subnet_0:
|
||||
properties:
|
||||
allocation_pools:
|
||||
- end: 192.168.0.254
|
||||
start: 192.168.0.2
|
||||
cidr: 192.168.0.0/24
|
||||
dns_nameservers:
|
||||
- 8.8.8.8
|
||||
enable_dhcp: true
|
||||
host_routes: []
|
||||
ip_version: 4
|
||||
name: tellurium_net_subnet
|
||||
network_id:
|
||||
get_resource: network_1
|
||||
type: OS::Neutron::Subnet
|
||||
volume_0:
|
||||
properties:
|
||||
image:
|
||||
get_param: volume_0_image
|
||||
metadata:
|
||||
attached_mode: rw
|
||||
readonly: 'False'
|
||||
name: Ubuntu 14.04
|
||||
size: 20
|
||||
volume_type:
|
||||
get_param: volume_0_volume_type
|
||||
type: OS::Cinder::Volume
|
||||
volume_1:
|
||||
properties:
|
||||
name: tellurium_volume
|
||||
size: 5
|
||||
volume_type:
|
||||
get_param: volume_1_volume_type
|
||||
type: OS::Cinder::Volume
|
351
flameclient/tests/fixtures/results/flame_adoption_data.yaml
vendored
Normal file
351
flameclient/tests/fixtures/results/flame_adoption_data.yaml
vendored
Normal file
@ -0,0 +1,351 @@
|
||||
action: CREATE
|
||||
environment:
|
||||
parameter_defaults: {}
|
||||
parameters: {}
|
||||
resources:
|
||||
floating_ip_0:
|
||||
action: CREATE
|
||||
metadata: {}
|
||||
name: floating_ip_0
|
||||
resource_data: {}
|
||||
resource_id: e6f50641-6c7e-468c-9623-1fd5ee2c1ebc
|
||||
status: COMPLETE
|
||||
type: OS::Neutron::FloatingIP
|
||||
keypair_0:
|
||||
action: CREATE
|
||||
metadata: {}
|
||||
name: keypair_0
|
||||
resource_data: {}
|
||||
resource_id: tellurium-key
|
||||
status: COMPLETE
|
||||
type: OS::Nova::KeyPair
|
||||
keypair_1:
|
||||
action: CREATE
|
||||
metadata: {}
|
||||
name: keypair_1
|
||||
resource_data: {}
|
||||
resource_id: tellurium-key-phrase
|
||||
status: COMPLETE
|
||||
type: OS::Nova::KeyPair
|
||||
network_1:
|
||||
action: CREATE
|
||||
metadata: {}
|
||||
name: network_1
|
||||
resource_data: {}
|
||||
resource_id: f054013d-7052-4708-9c72-2948a329fac3
|
||||
status: COMPLETE
|
||||
type: OS::Neutron::Net
|
||||
router_0:
|
||||
action: CREATE
|
||||
metadata: {}
|
||||
name: router_0
|
||||
resource_data: {}
|
||||
resource_id: ebc6dd0c-a276-4368-8084-bd37c587cc24
|
||||
status: COMPLETE
|
||||
type: OS::Neutron::Router
|
||||
router_0_gateway:
|
||||
action: CREATE
|
||||
metadata: {}
|
||||
name: router_0_gateway
|
||||
resource_data: {}
|
||||
resource_id: ebc6dd0c-a276-4368-8084-bd37c587cc24:6ea98324-0f14-49f6-97c0-885d1b8dc517
|
||||
status: COMPLETE
|
||||
type: OS::Neutron::RouterGateway
|
||||
router_0_interface_3:
|
||||
action: CREATE
|
||||
metadata: {}
|
||||
name: router_0_interface_3
|
||||
resource_data: {}
|
||||
resource_id: ebc6dd0c-a276-4368-8084-bd37c587cc24:subnet_id=541f0782-587f-428b-bd79-ca227a66973b
|
||||
status: COMPLETE
|
||||
type: OS::Neutron::RouterInterface
|
||||
security_group_1:
|
||||
action: CREATE
|
||||
metadata: {}
|
||||
name: security_group_1
|
||||
resource_data: {}
|
||||
resource_id: 156799a3-565e-48b3-938c-f95f09093c66
|
||||
status: COMPLETE
|
||||
type: OS::Neutron::SecurityGroup
|
||||
server_0:
|
||||
action: CREATE
|
||||
metadata: {}
|
||||
name: server_0
|
||||
resource_data: {}
|
||||
resource_id: 99c42e21-5099-4903-9121-063925aad299
|
||||
status: COMPLETE
|
||||
type: OS::Nova::Server
|
||||
server_1:
|
||||
action: CREATE
|
||||
metadata: {}
|
||||
name: server_1
|
||||
resource_data: {}
|
||||
resource_id: 2cf8db13-312a-4307-ba38-43b727ebcce6
|
||||
status: COMPLETE
|
||||
type: OS::Nova::Server
|
||||
server_2:
|
||||
action: CREATE
|
||||
metadata: {}
|
||||
name: server_2
|
||||
resource_data: {}
|
||||
resource_id: b6316031-e629-48b8-aac5-3f1b21ffe0f3
|
||||
status: COMPLETE
|
||||
type: OS::Nova::Server
|
||||
server_3:
|
||||
action: CREATE
|
||||
metadata: {}
|
||||
name: server_3
|
||||
resource_data: {}
|
||||
resource_id: 4add78fa-93df-4550-aaf7-aba2239ba00a
|
||||
status: COMPLETE
|
||||
type: OS::Nova::Server
|
||||
subnet_0:
|
||||
action: CREATE
|
||||
metadata: {}
|
||||
name: subnet_0
|
||||
resource_data: {}
|
||||
resource_id: 541f0782-587f-428b-bd79-ca227a66973b
|
||||
status: COMPLETE
|
||||
type: OS::Neutron::Subnet
|
||||
volume_0:
|
||||
action: CREATE
|
||||
metadata: {}
|
||||
name: volume_0
|
||||
resource_data: {}
|
||||
resource_id: 8ca10346-fe4c-4e68-9a18-98df875d1ecc
|
||||
status: COMPLETE
|
||||
type: OS::Cinder::Volume
|
||||
volume_1:
|
||||
action: CREATE
|
||||
metadata: {}
|
||||
name: volume_1
|
||||
resource_data: {}
|
||||
resource_id: 34ce951a-f2d9-4bdd-904d-9f70269c680b
|
||||
status: COMPLETE
|
||||
type: OS::Cinder::Volume
|
||||
status: COMPLETE
|
||||
template:
|
||||
description: Generated template
|
||||
heat_template_version: 2013-05-23
|
||||
parameters:
|
||||
external_network_for_floating_ip_0:
|
||||
default: 6ea98324-0f14-49f6-97c0-885d1b8dc517
|
||||
description: Network to allocate floating IP from
|
||||
type: string
|
||||
router_0_external_network:
|
||||
default: 6ea98324-0f14-49f6-97c0-885d1b8dc517
|
||||
description: Router external network
|
||||
type: string
|
||||
server_0_default_security_group:
|
||||
default: 9ffd2654-7ca6-48ae-852d-6503d5ce4a60
|
||||
description: Default security group for server Ubuntu 14.04
|
||||
type: string
|
||||
server_0_flavor:
|
||||
default: '17'
|
||||
description: Flavor to use for server server_0
|
||||
type: string
|
||||
server_1_default_security_group:
|
||||
default: 9ffd2654-7ca6-48ae-852d-6503d5ce4a60
|
||||
description: Default security group for server tellurium_win_instance
|
||||
type: string
|
||||
server_1_flavor:
|
||||
default: '42'
|
||||
description: Flavor to use for server server_1
|
||||
type: string
|
||||
server_1_image:
|
||||
default: 8254d703-e46f-4101-88ff-6f40bf7df51a
|
||||
description: Image to use for server server_1
|
||||
type: string
|
||||
server_2_default_security_group:
|
||||
default: 9ffd2654-7ca6-48ae-852d-6503d5ce4a60
|
||||
description: Default security group for server tellurium_win_instance_ssh_pass
|
||||
type: string
|
||||
server_2_flavor:
|
||||
default: '42'
|
||||
description: Flavor to use for server server_2
|
||||
type: string
|
||||
server_2_image:
|
||||
default: 8254d703-e46f-4101-88ff-6f40bf7df51a
|
||||
description: Image to use for server server_2
|
||||
type: string
|
||||
server_3_default_security_group:
|
||||
default: 9ffd2654-7ca6-48ae-852d-6503d5ce4a60
|
||||
description: Default security group for server tellurium_instance
|
||||
type: string
|
||||
server_3_flavor:
|
||||
default: '16'
|
||||
description: Flavor to use for server server_3
|
||||
type: string
|
||||
server_3_image:
|
||||
default: dd7d4b21-79b8-42f0-8464-0d1a5274c638
|
||||
description: Image to use for server server_3
|
||||
type: string
|
||||
volume_0_image:
|
||||
default: 70a9c910-dd99-4065-bce9-11e89bc479fe
|
||||
description: Image to create volume volume_0 from
|
||||
type: string
|
||||
volume_0_volume_type:
|
||||
default: standard
|
||||
description: Volume type for volume volume_0
|
||||
type: string
|
||||
volume_1_volume_type:
|
||||
default: standard
|
||||
description: Volume type for volume volume_1
|
||||
type: string
|
||||
resources:
|
||||
floating_ip_0:
|
||||
properties:
|
||||
floating_network_id:
|
||||
get_param: external_network_for_floating_ip_0
|
||||
type: OS::Neutron::FloatingIP
|
||||
keypair_0:
|
||||
properties:
|
||||
name: tellurium-key
|
||||
public_key: ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCwp5kVZ+3baPZllNXZDG2mivd5nJ5wWY6Jj/WV6NlO6cUiaH5om6itU3lyJxtAbLgbbvY2FjMg1PI2JI3EHx0OSPEbDdeNsQGi31qyuiB1S5p6TreI0Dfy0tywJ9G2CURjkuJnC8SvnMfVYLMFBvx7p8RzxSdDm/zrmc4KY3ktdfYQDNtEiH2jucUUiY0ipVkDNhhv03+5C9cnpaIcVDBkddE/KEME8NIIh7s6aYCXJEWJx85nOVVRD5qK7ouV6FcGVn6zqWRD3jn0iSxcFwiKx7p6M77PmJAY4gBIpWQmutok6T4ZrXxa7jE4dybwo5e8dyvGyc7WWGqXcmcinUWr
|
||||
Generated-by-Nova
|
||||
type: OS::Nova::KeyPair
|
||||
keypair_1:
|
||||
properties:
|
||||
name: tellurium-key-phrase
|
||||
public_key: ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCaYaTC6KCC2GURFMpRQiRq8Og10PcBbVnrQqluzi2E5vAqTHAegzivmGB8h2xrjXUfbKV2bE8kz2ZE66sq1yLO/jZ+rkOA+zLnOxNwkk3gQq57b26ZegPL2tTgottJTPGyPz6v2+LLtDf/+xTJMjkPKcMWylu12Js0XKVkdY35fwN7fRvA4xghtGu1GcmS2XFDMmeLDrG1KNPbBLj5cGoD723Ho7ZhAjLThoY/xMN2OYsSNzrg3S00QngZMzQvJf0ETrB3GtITk5FUs54qMRfiyUC72lw0gLTIJK8rs7fX/yeO+467afRt2xwHN50rEWJPeTVYWdlH/msh7NQ3LZ8/
|
||||
root@9b638ff21113
|
||||
type: OS::Nova::KeyPair
|
||||
network_1:
|
||||
properties:
|
||||
admin_state_up: true
|
||||
name: tellurium_net
|
||||
shared: false
|
||||
type: OS::Neutron::Net
|
||||
router_0:
|
||||
properties:
|
||||
admin_state_up: true
|
||||
name: tellurium_router
|
||||
type: OS::Neutron::Router
|
||||
router_0_gateway:
|
||||
properties:
|
||||
network_id:
|
||||
get_param: router_0_external_network
|
||||
router_id:
|
||||
get_resource: router_0
|
||||
type: OS::Neutron::RouterGateway
|
||||
router_0_interface_3:
|
||||
properties:
|
||||
router_id:
|
||||
get_resource: router_0
|
||||
subnet_id:
|
||||
get_resource: subnet_0
|
||||
type: OS::Neutron::RouterInterface
|
||||
security_group_1:
|
||||
properties:
|
||||
description: ''
|
||||
name: http
|
||||
rules:
|
||||
- direction: egress
|
||||
ethertype: IPv4
|
||||
remote_ip_prefix: 0.0.0.0/0
|
||||
- direction: egress
|
||||
ethertype: IPv6
|
||||
- direction: ingress
|
||||
ethertype: IPv4
|
||||
port_range_max: 80
|
||||
port_range_min: 80
|
||||
protocol: tcp
|
||||
remote_ip_prefix: 0.0.0.0/0
|
||||
type: OS::Neutron::SecurityGroup
|
||||
server_0:
|
||||
properties:
|
||||
block_device_mapping_v2:
|
||||
- device_name: /dev/vda
|
||||
volume_id:
|
||||
get_resource: volume_0
|
||||
flavor:
|
||||
get_param: server_0_flavor
|
||||
key_name:
|
||||
get_resource: keypair_0
|
||||
name: Ubuntu 14.04
|
||||
networks:
|
||||
- network:
|
||||
get_resource: network_1
|
||||
security_groups:
|
||||
- get_resource: security_group_1
|
||||
- get_param: server_0_default_security_group
|
||||
type: OS::Nova::Server
|
||||
server_1:
|
||||
properties:
|
||||
flavor:
|
||||
get_param: server_1_flavor
|
||||
image:
|
||||
get_param: server_1_image
|
||||
key_name:
|
||||
get_resource: keypair_0
|
||||
name: tellurium_win_instance
|
||||
networks:
|
||||
- network:
|
||||
get_resource: network_1
|
||||
security_groups:
|
||||
- get_param: server_1_default_security_group
|
||||
type: OS::Nova::Server
|
||||
server_2:
|
||||
properties:
|
||||
flavor:
|
||||
get_param: server_2_flavor
|
||||
image:
|
||||
get_param: server_2_image
|
||||
key_name:
|
||||
get_resource: keypair_1
|
||||
name: tellurium_win_instance_ssh_pass
|
||||
networks:
|
||||
- network:
|
||||
get_resource: network_1
|
||||
security_groups:
|
||||
- get_param: server_2_default_security_group
|
||||
type: OS::Nova::Server
|
||||
server_3:
|
||||
properties:
|
||||
flavor:
|
||||
get_param: server_3_flavor
|
||||
image:
|
||||
get_param: server_3_image
|
||||
key_name:
|
||||
get_resource: keypair_0
|
||||
name: tellurium_instance
|
||||
networks:
|
||||
- network:
|
||||
get_resource: network_1
|
||||
security_groups:
|
||||
- get_param: server_3_default_security_group
|
||||
type: OS::Nova::Server
|
||||
subnet_0:
|
||||
properties:
|
||||
allocation_pools:
|
||||
- end: 192.168.0.254
|
||||
start: 192.168.0.2
|
||||
cidr: 192.168.0.0/24
|
||||
dns_nameservers:
|
||||
- 8.8.8.8
|
||||
enable_dhcp: true
|
||||
host_routes: []
|
||||
ip_version: 4
|
||||
name: tellurium_net_subnet
|
||||
network_id:
|
||||
get_resource: network_1
|
||||
type: OS::Neutron::Subnet
|
||||
volume_0:
|
||||
properties:
|
||||
image:
|
||||
get_param: volume_0_image
|
||||
metadata:
|
||||
attached_mode: rw
|
||||
readonly: 'False'
|
||||
name: Ubuntu 14.04
|
||||
size: 20
|
||||
volume_type:
|
||||
get_param: volume_0_volume_type
|
||||
type: OS::Cinder::Volume
|
||||
volume_1:
|
||||
properties:
|
||||
name: tellurium_volume
|
||||
size: 5
|
||||
volume_type:
|
||||
get_param: volume_1_volume_type
|
||||
type: OS::Cinder::Volume
|
237
flameclient/tests/fixtures/results/flame_constraints.yaml
vendored
Normal file
237
flameclient/tests/fixtures/results/flame_constraints.yaml
vendored
Normal file
@ -0,0 +1,237 @@
|
||||
description: Generated template
|
||||
heat_template_version: 2013-05-23
|
||||
parameters:
|
||||
external_network_for_floating_ip_0:
|
||||
constraints:
|
||||
- custom_constraint: neutron.network
|
||||
default: 6ea98324-0f14-49f6-97c0-885d1b8dc517
|
||||
description: Network to allocate floating IP from
|
||||
type: string
|
||||
router_0_external_network:
|
||||
constraints:
|
||||
- custom_constraint: neutron.network
|
||||
default: 6ea98324-0f14-49f6-97c0-885d1b8dc517
|
||||
description: Router external network
|
||||
type: string
|
||||
server_0_flavor:
|
||||
default: '17'
|
||||
description: Flavor to use for server server_0
|
||||
type: string
|
||||
server_1_flavor:
|
||||
default: '42'
|
||||
description: Flavor to use for server server_1
|
||||
type: string
|
||||
server_1_image:
|
||||
constraints:
|
||||
- custom_constraint: glance.image
|
||||
default: 8254d703-e46f-4101-88ff-6f40bf7df51a
|
||||
description: Image to use for server server_1
|
||||
type: string
|
||||
server_2_flavor:
|
||||
default: '42'
|
||||
description: Flavor to use for server server_2
|
||||
type: string
|
||||
server_2_image:
|
||||
constraints:
|
||||
- custom_constraint: glance.image
|
||||
default: 8254d703-e46f-4101-88ff-6f40bf7df51a
|
||||
description: Image to use for server server_2
|
||||
type: string
|
||||
server_3_flavor:
|
||||
default: '16'
|
||||
description: Flavor to use for server server_3
|
||||
type: string
|
||||
server_3_image:
|
||||
constraints:
|
||||
- custom_constraint: glance.image
|
||||
default: dd7d4b21-79b8-42f0-8464-0d1a5274c638
|
||||
description: Image to use for server server_3
|
||||
type: string
|
||||
volume_0_image:
|
||||
constraints:
|
||||
- custom_constraint: glance.image
|
||||
default: 70a9c910-dd99-4065-bce9-11e89bc479fe
|
||||
description: Image to create volume volume_0 from
|
||||
type: string
|
||||
volume_0_volume_type:
|
||||
default: standard
|
||||
description: Volume type for volume volume_0
|
||||
type: string
|
||||
volume_1_volume_type:
|
||||
default: standard
|
||||
description: Volume type for volume volume_1
|
||||
type: string
|
||||
resources:
|
||||
floating_ip_0:
|
||||
properties:
|
||||
floating_network_id:
|
||||
get_param: external_network_for_floating_ip_0
|
||||
type: OS::Neutron::FloatingIP
|
||||
keypair_0:
|
||||
properties:
|
||||
name: tellurium-key
|
||||
public_key: ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCwp5kVZ+3baPZllNXZDG2mivd5nJ5wWY6Jj/WV6NlO6cUiaH5om6itU3lyJxtAbLgbbvY2FjMg1PI2JI3EHx0OSPEbDdeNsQGi31qyuiB1S5p6TreI0Dfy0tywJ9G2CURjkuJnC8SvnMfVYLMFBvx7p8RzxSdDm/zrmc4KY3ktdfYQDNtEiH2jucUUiY0ipVkDNhhv03+5C9cnpaIcVDBkddE/KEME8NIIh7s6aYCXJEWJx85nOVVRD5qK7ouV6FcGVn6zqWRD3jn0iSxcFwiKx7p6M77PmJAY4gBIpWQmutok6T4ZrXxa7jE4dybwo5e8dyvGyc7WWGqXcmcinUWr
|
||||
Generated-by-Nova
|
||||
type: OS::Nova::KeyPair
|
||||
keypair_1:
|
||||
properties:
|
||||
name: tellurium-key-phrase
|
||||
public_key: ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCaYaTC6KCC2GURFMpRQiRq8Og10PcBbVnrQqluzi2E5vAqTHAegzivmGB8h2xrjXUfbKV2bE8kz2ZE66sq1yLO/jZ+rkOA+zLnOxNwkk3gQq57b26ZegPL2tTgottJTPGyPz6v2+LLtDf/+xTJMjkPKcMWylu12Js0XKVkdY35fwN7fRvA4xghtGu1GcmS2XFDMmeLDrG1KNPbBLj5cGoD723Ho7ZhAjLThoY/xMN2OYsSNzrg3S00QngZMzQvJf0ETrB3GtITk5FUs54qMRfiyUC72lw0gLTIJK8rs7fX/yeO+467afRt2xwHN50rEWJPeTVYWdlH/msh7NQ3LZ8/
|
||||
root@9b638ff21113
|
||||
type: OS::Nova::KeyPair
|
||||
network_1:
|
||||
properties:
|
||||
admin_state_up: true
|
||||
name: tellurium_net
|
||||
shared: false
|
||||
type: OS::Neutron::Net
|
||||
router_0:
|
||||
properties:
|
||||
admin_state_up: true
|
||||
name: tellurium_router
|
||||
type: OS::Neutron::Router
|
||||
router_0_gateway:
|
||||
properties:
|
||||
network_id:
|
||||
get_param: router_0_external_network
|
||||
router_id:
|
||||
get_resource: router_0
|
||||
type: OS::Neutron::RouterGateway
|
||||
router_0_interface_3:
|
||||
properties:
|
||||
router_id:
|
||||
get_resource: router_0
|
||||
subnet_id:
|
||||
get_resource: subnet_0
|
||||
type: OS::Neutron::RouterInterface
|
||||
security_group_0:
|
||||
properties:
|
||||
name: _default
|
||||
rules:
|
||||
- direction: ingress
|
||||
ethertype: IPv4
|
||||
remote_mode: remote_group_id
|
||||
- direction: ingress
|
||||
ethertype: IPv6
|
||||
remote_mode: remote_group_id
|
||||
- direction: egress
|
||||
ethertype: IPv4
|
||||
remote_ip_prefix: 0.0.0.0/0
|
||||
- direction: egress
|
||||
ethertype: IPv6
|
||||
remote_ip_prefix: ::/0
|
||||
type: OS::Neutron::SecurityGroup
|
||||
security_group_1:
|
||||
properties:
|
||||
description: ''
|
||||
name: http
|
||||
rules:
|
||||
- direction: egress
|
||||
ethertype: IPv4
|
||||
remote_ip_prefix: 0.0.0.0/0
|
||||
- direction: egress
|
||||
ethertype: IPv6
|
||||
- direction: ingress
|
||||
ethertype: IPv4
|
||||
port_range_max: 80
|
||||
port_range_min: 80
|
||||
protocol: tcp
|
||||
remote_ip_prefix: 0.0.0.0/0
|
||||
type: OS::Neutron::SecurityGroup
|
||||
server_0:
|
||||
properties:
|
||||
block_device_mapping_v2:
|
||||
- device_name: /dev/vda
|
||||
volume_id:
|
||||
get_resource: volume_0
|
||||
flavor:
|
||||
get_param: server_0_flavor
|
||||
key_name:
|
||||
get_resource: keypair_0
|
||||
name: Ubuntu 14.04
|
||||
networks:
|
||||
- network:
|
||||
get_resource: network_1
|
||||
security_groups:
|
||||
- get_resource: security_group_1
|
||||
- get_resource: security_group_0
|
||||
type: OS::Nova::Server
|
||||
server_1:
|
||||
properties:
|
||||
flavor:
|
||||
get_param: server_1_flavor
|
||||
image:
|
||||
get_param: server_1_image
|
||||
key_name:
|
||||
get_resource: keypair_0
|
||||
name: tellurium_win_instance
|
||||
networks:
|
||||
- network:
|
||||
get_resource: network_1
|
||||
security_groups:
|
||||
- get_resource: security_group_0
|
||||
type: OS::Nova::Server
|
||||
server_2:
|
||||
properties:
|
||||
flavor:
|
||||
get_param: server_2_flavor
|
||||
image:
|
||||
get_param: server_2_image
|
||||
key_name:
|
||||
get_resource: keypair_1
|
||||
name: tellurium_win_instance_ssh_pass
|
||||
networks:
|
||||
- network:
|
||||
get_resource: network_1
|
||||
security_groups:
|
||||
- get_resource: security_group_0
|
||||
type: OS::Nova::Server
|
||||
server_3:
|
||||
properties:
|
||||
flavor:
|
||||
get_param: server_3_flavor
|
||||
image:
|
||||
get_param: server_3_image
|
||||
key_name:
|
||||
get_resource: keypair_0
|
||||
name: tellurium_instance
|
||||
networks:
|
||||
- network:
|
||||
get_resource: network_1
|
||||
security_groups:
|
||||
- get_resource: security_group_0
|
||||
type: OS::Nova::Server
|
||||
subnet_0:
|
||||
properties:
|
||||
allocation_pools:
|
||||
- end: 192.168.0.254
|
||||
start: 192.168.0.2
|
||||
cidr: 192.168.0.0/24
|
||||
dns_nameservers:
|
||||
- 8.8.8.8
|
||||
enable_dhcp: true
|
||||
host_routes: []
|
||||
ip_version: 4
|
||||
name: tellurium_net_subnet
|
||||
network_id:
|
||||
get_resource: network_1
|
||||
type: OS::Neutron::Subnet
|
||||
volume_0:
|
||||
properties:
|
||||
image:
|
||||
get_param: volume_0_image
|
||||
metadata:
|
||||
attached_mode: rw
|
||||
readonly: 'False'
|
||||
name: Ubuntu 14.04
|
||||
size: 20
|
||||
volume_type:
|
||||
get_param: volume_0_volume_type
|
||||
type: OS::Cinder::Volume
|
||||
volume_1:
|
||||
properties:
|
||||
name: tellurium_volume
|
||||
size: 5
|
||||
volume_type:
|
||||
get_param: volume_1_volume_type
|
||||
type: OS::Cinder::Volume
|
289
flameclient/tests/fixtures/results/flame_constraints_extract_ports.yaml
vendored
Normal file
289
flameclient/tests/fixtures/results/flame_constraints_extract_ports.yaml
vendored
Normal file
@ -0,0 +1,289 @@
|
||||
description: Generated template
|
||||
heat_template_version: 2013-05-23
|
||||
parameters:
|
||||
external_network_for_floating_ip_0:
|
||||
constraints:
|
||||
- custom_constraint: neutron.network
|
||||
default: 6ea98324-0f14-49f6-97c0-885d1b8dc517
|
||||
description: Network to allocate floating IP from
|
||||
type: string
|
||||
router_0_external_network:
|
||||
constraints:
|
||||
- custom_constraint: neutron.network
|
||||
default: 6ea98324-0f14-49f6-97c0-885d1b8dc517
|
||||
description: Router external network
|
||||
type: string
|
||||
server_0_flavor:
|
||||
default: '17'
|
||||
description: Flavor to use for server server_0
|
||||
type: string
|
||||
server_1_flavor:
|
||||
default: '42'
|
||||
description: Flavor to use for server server_1
|
||||
type: string
|
||||
server_1_image:
|
||||
constraints:
|
||||
- custom_constraint: glance.image
|
||||
default: 8254d703-e46f-4101-88ff-6f40bf7df51a
|
||||
description: Image to use for server server_1
|
||||
type: string
|
||||
server_2_flavor:
|
||||
default: '42'
|
||||
description: Flavor to use for server server_2
|
||||
type: string
|
||||
server_2_image:
|
||||
constraints:
|
||||
- custom_constraint: glance.image
|
||||
default: 8254d703-e46f-4101-88ff-6f40bf7df51a
|
||||
description: Image to use for server server_2
|
||||
type: string
|
||||
server_3_flavor:
|
||||
default: '16'
|
||||
description: Flavor to use for server server_3
|
||||
type: string
|
||||
server_3_image:
|
||||
constraints:
|
||||
- custom_constraint: glance.image
|
||||
default: dd7d4b21-79b8-42f0-8464-0d1a5274c638
|
||||
description: Image to use for server server_3
|
||||
type: string
|
||||
volume_0_image:
|
||||
constraints:
|
||||
- custom_constraint: glance.image
|
||||
default: 70a9c910-dd99-4065-bce9-11e89bc479fe
|
||||
description: Image to create volume volume_0 from
|
||||
type: string
|
||||
volume_0_volume_type:
|
||||
default: standard
|
||||
description: Volume type for volume volume_0
|
||||
type: string
|
||||
volume_1_volume_type:
|
||||
default: standard
|
||||
description: Volume type for volume volume_1
|
||||
type: string
|
||||
resources:
|
||||
floating_ip_0:
|
||||
properties:
|
||||
floating_network_id:
|
||||
get_param: external_network_for_floating_ip_0
|
||||
type: OS::Neutron::FloatingIP
|
||||
keypair_0:
|
||||
properties:
|
||||
name: tellurium-key
|
||||
public_key: ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCwp5kVZ+3baPZllNXZDG2mivd5nJ5wWY6Jj/WV6NlO6cUiaH5om6itU3lyJxtAbLgbbvY2FjMg1PI2JI3EHx0OSPEbDdeNsQGi31qyuiB1S5p6TreI0Dfy0tywJ9G2CURjkuJnC8SvnMfVYLMFBvx7p8RzxSdDm/zrmc4KY3ktdfYQDNtEiH2jucUUiY0ipVkDNhhv03+5C9cnpaIcVDBkddE/KEME8NIIh7s6aYCXJEWJx85nOVVRD5qK7ouV6FcGVn6zqWRD3jn0iSxcFwiKx7p6M77PmJAY4gBIpWQmutok6T4ZrXxa7jE4dybwo5e8dyvGyc7WWGqXcmcinUWr
|
||||
Generated-by-Nova
|
||||
type: OS::Nova::KeyPair
|
||||
keypair_1:
|
||||
properties:
|
||||
name: tellurium-key-phrase
|
||||
public_key: ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCaYaTC6KCC2GURFMpRQiRq8Og10PcBbVnrQqluzi2E5vAqTHAegzivmGB8h2xrjXUfbKV2bE8kz2ZE66sq1yLO/jZ+rkOA+zLnOxNwkk3gQq57b26ZegPL2tTgottJTPGyPz6v2+LLtDf/+xTJMjkPKcMWylu12Js0XKVkdY35fwN7fRvA4xghtGu1GcmS2XFDMmeLDrG1KNPbBLj5cGoD723Ho7ZhAjLThoY/xMN2OYsSNzrg3S00QngZMzQvJf0ETrB3GtITk5FUs54qMRfiyUC72lw0gLTIJK8rs7fX/yeO+467afRt2xwHN50rEWJPeTVYWdlH/msh7NQ3LZ8/
|
||||
root@9b638ff21113
|
||||
type: OS::Nova::KeyPair
|
||||
network_1:
|
||||
properties:
|
||||
admin_state_up: true
|
||||
name: tellurium_net
|
||||
shared: false
|
||||
type: OS::Neutron::Net
|
||||
port_0:
|
||||
properties:
|
||||
admin_state_up: true
|
||||
device_owner: compute:None
|
||||
fixed_ips:
|
||||
- ip_address: 192.168.0.3
|
||||
subnet_id:
|
||||
get_resource: subnet_0
|
||||
mac_address: 02:3d:ec:f6:f8:25
|
||||
name: Tellurium_Fixtures-windows_port-hxvnswbzi56x
|
||||
network_id:
|
||||
get_resource: network_1
|
||||
security_groups:
|
||||
- get_resource: security_group_0
|
||||
type: OS::Neutron::Port
|
||||
port_1:
|
||||
properties:
|
||||
admin_state_up: true
|
||||
device_owner: compute:None
|
||||
fixed_ips:
|
||||
- ip_address: 192.168.0.4
|
||||
subnet_id:
|
||||
get_resource: subnet_0
|
||||
mac_address: 02:20:6d:f7:16:da
|
||||
name: Tellurium_Fixtures-instance_port-fmln6fjl4yvo
|
||||
network_id:
|
||||
get_resource: network_1
|
||||
security_groups:
|
||||
- get_resource: security_group_0
|
||||
type: OS::Neutron::Port
|
||||
port_2:
|
||||
properties:
|
||||
admin_state_up: true
|
||||
device_owner: compute:None
|
||||
fixed_ips:
|
||||
- ip_address: 192.168.0.5
|
||||
subnet_id:
|
||||
get_resource: subnet_0
|
||||
mac_address: 02:cb:33:6b:60:f2
|
||||
name: Tellurium_Fixtures-windows_ssh_pass_port-4zlwanbetsg2
|
||||
network_id:
|
||||
get_resource: network_1
|
||||
security_groups:
|
||||
- get_resource: security_group_0
|
||||
type: OS::Neutron::Port
|
||||
port_4:
|
||||
properties:
|
||||
admin_state_up: true
|
||||
device_owner: compute:nova
|
||||
fixed_ips:
|
||||
- ip_address: 192.168.0.6
|
||||
subnet_id:
|
||||
get_resource: subnet_0
|
||||
mac_address: 02:4f:41:34:32:b4
|
||||
name: 4f413432-b499-4fcc-a81a-1ee0d8bc16b7
|
||||
network_id:
|
||||
get_resource: network_1
|
||||
security_groups:
|
||||
- get_resource: security_group_1
|
||||
- get_resource: security_group_0
|
||||
type: OS::Neutron::Port
|
||||
router_0:
|
||||
properties:
|
||||
admin_state_up: true
|
||||
name: tellurium_router
|
||||
type: OS::Neutron::Router
|
||||
router_0_gateway:
|
||||
properties:
|
||||
network_id:
|
||||
get_param: router_0_external_network
|
||||
router_id:
|
||||
get_resource: router_0
|
||||
type: OS::Neutron::RouterGateway
|
||||
router_0_interface_3:
|
||||
properties:
|
||||
router_id:
|
||||
get_resource: router_0
|
||||
subnet_id:
|
||||
get_resource: subnet_0
|
||||
type: OS::Neutron::RouterInterface
|
||||
security_group_0:
|
||||
properties:
|
||||
name: _default
|
||||
rules:
|
||||
- direction: ingress
|
||||
ethertype: IPv4
|
||||
remote_mode: remote_group_id
|
||||
- direction: ingress
|
||||
ethertype: IPv6
|
||||
remote_mode: remote_group_id
|
||||
- direction: egress
|
||||
ethertype: IPv4
|
||||
remote_ip_prefix: 0.0.0.0/0
|
||||
- direction: egress
|
||||
ethertype: IPv6
|
||||
remote_ip_prefix: ::/0
|
||||
type: OS::Neutron::SecurityGroup
|
||||
security_group_1:
|
||||
properties:
|
||||
description: ''
|
||||
name: http
|
||||
rules:
|
||||
- direction: egress
|
||||
ethertype: IPv4
|
||||
remote_ip_prefix: 0.0.0.0/0
|
||||
- direction: egress
|
||||
ethertype: IPv6
|
||||
- direction: ingress
|
||||
ethertype: IPv4
|
||||
port_range_max: 80
|
||||
port_range_min: 80
|
||||
protocol: tcp
|
||||
remote_ip_prefix: 0.0.0.0/0
|
||||
type: OS::Neutron::SecurityGroup
|
||||
server_0:
|
||||
properties:
|
||||
block_device_mapping_v2:
|
||||
- device_name: /dev/vda
|
||||
volume_id:
|
||||
get_resource: volume_0
|
||||
flavor:
|
||||
get_param: server_0_flavor
|
||||
key_name:
|
||||
get_resource: keypair_0
|
||||
name: Ubuntu 14.04
|
||||
networks:
|
||||
- port:
|
||||
get_resource: port_4
|
||||
type: OS::Nova::Server
|
||||
server_1:
|
||||
properties:
|
||||
flavor:
|
||||
get_param: server_1_flavor
|
||||
image:
|
||||
get_param: server_1_image
|
||||
key_name:
|
||||
get_resource: keypair_0
|
||||
name: tellurium_win_instance
|
||||
networks:
|
||||
- port:
|
||||
get_resource: port_0
|
||||
type: OS::Nova::Server
|
||||
server_2:
|
||||
properties:
|
||||
flavor:
|
||||
get_param: server_2_flavor
|
||||
image:
|
||||
get_param: server_2_image
|
||||
key_name:
|
||||
get_resource: keypair_1
|
||||
name: tellurium_win_instance_ssh_pass
|
||||
networks:
|
||||
- port:
|
||||
get_resource: port_2
|
||||
type: OS::Nova::Server
|
||||
server_3:
|
||||
properties:
|
||||
flavor:
|
||||
get_param: server_3_flavor
|
||||
image:
|
||||
get_param: server_3_image
|
||||
key_name:
|
||||
get_resource: keypair_0
|
||||
name: tellurium_instance
|
||||
networks:
|
||||
- port:
|
||||
get_resource: port_1
|
||||
type: OS::Nova::Server
|
||||
subnet_0:
|
||||
properties:
|
||||
allocation_pools:
|
||||
- end: 192.168.0.254
|
||||
start: 192.168.0.2
|
||||
cidr: 192.168.0.0/24
|
||||
dns_nameservers:
|
||||
- 8.8.8.8
|
||||
enable_dhcp: true
|
||||
host_routes: []
|
||||
ip_version: 4
|
||||
name: tellurium_net_subnet
|
||||
network_id:
|
||||
get_resource: network_1
|
||||
type: OS::Neutron::Subnet
|
||||
volume_0:
|
||||
properties:
|
||||
image:
|
||||
get_param: volume_0_image
|
||||
metadata:
|
||||
attached_mode: rw
|
||||
readonly: 'False'
|
||||
name: Ubuntu 14.04
|
||||
size: 20
|
||||
volume_type:
|
||||
get_param: volume_0_volume_type
|
||||
type: OS::Cinder::Volume
|
||||
volume_1:
|
||||
properties:
|
||||
name: tellurium_volume
|
||||
size: 5
|
||||
volume_type:
|
||||
get_param: volume_1_volume_type
|
||||
type: OS::Cinder::Volume
|
277
flameclient/tests/fixtures/results/flame_extract_ports.yaml
vendored
Normal file
277
flameclient/tests/fixtures/results/flame_extract_ports.yaml
vendored
Normal file
@ -0,0 +1,277 @@
|
||||
description: Generated template
|
||||
heat_template_version: 2013-05-23
|
||||
parameters:
|
||||
external_network_for_floating_ip_0:
|
||||
default: 6ea98324-0f14-49f6-97c0-885d1b8dc517
|
||||
description: Network to allocate floating IP from
|
||||
type: string
|
||||
router_0_external_network:
|
||||
default: 6ea98324-0f14-49f6-97c0-885d1b8dc517
|
||||
description: Router external network
|
||||
type: string
|
||||
server_0_flavor:
|
||||
default: '17'
|
||||
description: Flavor to use for server server_0
|
||||
type: string
|
||||
server_1_flavor:
|
||||
default: '42'
|
||||
description: Flavor to use for server server_1
|
||||
type: string
|
||||
server_1_image:
|
||||
default: 8254d703-e46f-4101-88ff-6f40bf7df51a
|
||||
description: Image to use for server server_1
|
||||
type: string
|
||||
server_2_flavor:
|
||||
default: '42'
|
||||
description: Flavor to use for server server_2
|
||||
type: string
|
||||
server_2_image:
|
||||
default: 8254d703-e46f-4101-88ff-6f40bf7df51a
|
||||
description: Image to use for server server_2
|
||||
type: string
|
||||
server_3_flavor:
|
||||
default: '16'
|
||||
description: Flavor to use for server server_3
|
||||
type: string
|
||||
server_3_image:
|
||||
default: dd7d4b21-79b8-42f0-8464-0d1a5274c638
|
||||
description: Image to use for server server_3
|
||||
type: string
|
||||
volume_0_image:
|
||||
default: 70a9c910-dd99-4065-bce9-11e89bc479fe
|
||||
description: Image to create volume volume_0 from
|
||||
type: string
|
||||
volume_0_volume_type:
|
||||
default: standard
|
||||
description: Volume type for volume volume_0
|
||||
type: string
|
||||
volume_1_volume_type:
|
||||
default: standard
|
||||
description: Volume type for volume volume_1
|
||||
type: string
|
||||
resources:
|
||||
floating_ip_0:
|
||||
properties:
|
||||
floating_network_id:
|
||||
get_param: external_network_for_floating_ip_0
|
||||
type: OS::Neutron::FloatingIP
|
||||
keypair_0:
|
||||
properties:
|
||||
name: tellurium-key
|
||||
public_key: ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCwp5kVZ+3baPZllNXZDG2mivd5nJ5wWY6Jj/WV6NlO6cUiaH5om6itU3lyJxtAbLgbbvY2FjMg1PI2JI3EHx0OSPEbDdeNsQGi31qyuiB1S5p6TreI0Dfy0tywJ9G2CURjkuJnC8SvnMfVYLMFBvx7p8RzxSdDm/zrmc4KY3ktdfYQDNtEiH2jucUUiY0ipVkDNhhv03+5C9cnpaIcVDBkddE/KEME8NIIh7s6aYCXJEWJx85nOVVRD5qK7ouV6FcGVn6zqWRD3jn0iSxcFwiKx7p6M77PmJAY4gBIpWQmutok6T4ZrXxa7jE4dybwo5e8dyvGyc7WWGqXcmcinUWr
|
||||
Generated-by-Nova
|
||||
type: OS::Nova::KeyPair
|
||||
keypair_1:
|
||||
properties:
|
||||
name: tellurium-key-phrase
|
||||
public_key: ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCaYaTC6KCC2GURFMpRQiRq8Og10PcBbVnrQqluzi2E5vAqTHAegzivmGB8h2xrjXUfbKV2bE8kz2ZE66sq1yLO/jZ+rkOA+zLnOxNwkk3gQq57b26ZegPL2tTgottJTPGyPz6v2+LLtDf/+xTJMjkPKcMWylu12Js0XKVkdY35fwN7fRvA4xghtGu1GcmS2XFDMmeLDrG1KNPbBLj5cGoD723Ho7ZhAjLThoY/xMN2OYsSNzrg3S00QngZMzQvJf0ETrB3GtITk5FUs54qMRfiyUC72lw0gLTIJK8rs7fX/yeO+467afRt2xwHN50rEWJPeTVYWdlH/msh7NQ3LZ8/
|
||||
root@9b638ff21113
|
||||
type: OS::Nova::KeyPair
|
||||
network_1:
|
||||
properties:
|
||||
admin_state_up: true
|
||||
name: tellurium_net
|
||||
shared: false
|
||||
type: OS::Neutron::Net
|
||||
port_0:
|
||||
properties:
|
||||
admin_state_up: true
|
||||
device_owner: compute:None
|
||||
fixed_ips:
|
||||
- ip_address: 192.168.0.3
|
||||
subnet_id:
|
||||
get_resource: subnet_0
|
||||
mac_address: 02:3d:ec:f6:f8:25
|
||||
name: Tellurium_Fixtures-windows_port-hxvnswbzi56x
|
||||
network_id:
|
||||
get_resource: network_1
|
||||
security_groups:
|
||||
- get_resource: security_group_0
|
||||
type: OS::Neutron::Port
|
||||
port_1:
|
||||
properties:
|
||||
admin_state_up: true
|
||||
device_owner: compute:None
|
||||
fixed_ips:
|
||||
- ip_address: 192.168.0.4
|
||||
subnet_id:
|
||||
get_resource: subnet_0
|
||||
mac_address: 02:20:6d:f7:16:da
|
||||
name: Tellurium_Fixtures-instance_port-fmln6fjl4yvo
|
||||
network_id:
|
||||
get_resource: network_1
|
||||
security_groups:
|
||||
- get_resource: security_group_0
|
||||
type: OS::Neutron::Port
|
||||
port_2:
|
||||
properties:
|
||||
admin_state_up: true
|
||||
device_owner: compute:None
|
||||
fixed_ips:
|
||||
- ip_address: 192.168.0.5
|
||||
subnet_id:
|
||||
get_resource: subnet_0
|
||||
mac_address: 02:cb:33:6b:60:f2
|
||||
name: Tellurium_Fixtures-windows_ssh_pass_port-4zlwanbetsg2
|
||||
network_id:
|
||||
get_resource: network_1
|
||||
security_groups:
|
||||
- get_resource: security_group_0
|
||||
type: OS::Neutron::Port
|
||||
port_4:
|
||||
properties:
|
||||
admin_state_up: true
|
||||
device_owner: compute:nova
|
||||
fixed_ips:
|
||||
- ip_address: 192.168.0.6
|
||||
subnet_id:
|
||||
get_resource: subnet_0
|
||||
mac_address: 02:4f:41:34:32:b4
|
||||
name: 4f413432-b499-4fcc-a81a-1ee0d8bc16b7
|
||||
network_id:
|
||||
get_resource: network_1
|
||||
security_groups:
|
||||
- get_resource: security_group_1
|
||||
- get_resource: security_group_0
|
||||
type: OS::Neutron::Port
|
||||
router_0:
|
||||
properties:
|
||||
admin_state_up: true
|
||||
name: tellurium_router
|
||||
type: OS::Neutron::Router
|
||||
router_0_gateway:
|
||||
properties:
|
||||
network_id:
|
||||
get_param: router_0_external_network
|
||||
router_id:
|
||||
get_resource: router_0
|
||||
type: OS::Neutron::RouterGateway
|
||||
router_0_interface_3:
|
||||
properties:
|
||||
router_id:
|
||||
get_resource: router_0
|
||||
subnet_id:
|
||||
get_resource: subnet_0
|
||||
type: OS::Neutron::RouterInterface
|
||||
security_group_0:
|
||||
properties:
|
||||
name: _default
|
||||
rules:
|
||||
- direction: ingress
|
||||
ethertype: IPv4
|
||||
remote_mode: remote_group_id
|
||||
- direction: ingress
|
||||
ethertype: IPv6
|
||||
remote_mode: remote_group_id
|
||||
- direction: egress
|
||||
ethertype: IPv4
|
||||
remote_ip_prefix: 0.0.0.0/0
|
||||
- direction: egress
|
||||
ethertype: IPv6
|
||||
remote_ip_prefix: ::/0
|
||||
type: OS::Neutron::SecurityGroup
|
||||
security_group_1:
|
||||
properties:
|
||||
description: ''
|
||||
name: http
|
||||
rules:
|
||||
- direction: egress
|
||||
ethertype: IPv4
|
||||
remote_ip_prefix: 0.0.0.0/0
|
||||
- direction: egress
|
||||
ethertype: IPv6
|
||||
- direction: ingress
|
||||
ethertype: IPv4
|
||||
port_range_max: 80
|
||||
port_range_min: 80
|
||||
protocol: tcp
|
||||
remote_ip_prefix: 0.0.0.0/0
|
||||
type: OS::Neutron::SecurityGroup
|
||||
server_0:
|
||||
properties:
|
||||
block_device_mapping_v2:
|
||||
- device_name: /dev/vda
|
||||
volume_id:
|
||||
get_resource: volume_0
|
||||
flavor:
|
||||
get_param: server_0_flavor
|
||||
key_name:
|
||||
get_resource: keypair_0
|
||||
name: Ubuntu 14.04
|
||||
networks:
|
||||
- port:
|
||||
get_resource: port_4
|
||||
type: OS::Nova::Server
|
||||
server_1:
|
||||
properties:
|
||||
flavor:
|
||||
get_param: server_1_flavor
|
||||
image:
|
||||
get_param: server_1_image
|
||||
key_name:
|
||||
get_resource: keypair_0
|
||||
name: tellurium_win_instance
|
||||
networks:
|
||||
- port:
|
||||
get_resource: port_0
|
||||
type: OS::Nova::Server
|
||||
server_2:
|
||||
properties:
|
||||
flavor:
|
||||
get_param: server_2_flavor
|
||||
image:
|
||||
get_param: server_2_image
|
||||
key_name:
|
||||
get_resource: keypair_1
|
||||
name: tellurium_win_instance_ssh_pass
|
||||
networks:
|
||||
- port:
|
||||
get_resource: port_2
|
||||
type: OS::Nova::Server
|
||||
server_3:
|
||||
properties:
|
||||
flavor:
|
||||
get_param: server_3_flavor
|
||||
image:
|
||||
get_param: server_3_image
|
||||
key_name:
|
||||
get_resource: keypair_0
|
||||
name: tellurium_instance
|
||||
networks:
|
||||
- port:
|
||||
get_resource: port_1
|
||||
type: OS::Nova::Server
|
||||
subnet_0:
|
||||
properties:
|
||||
allocation_pools:
|
||||
- end: 192.168.0.254
|
||||
start: 192.168.0.2
|
||||
cidr: 192.168.0.0/24
|
||||
dns_nameservers:
|
||||
- 8.8.8.8
|
||||
enable_dhcp: true
|
||||
host_routes: []
|
||||
ip_version: 4
|
||||
name: tellurium_net_subnet
|
||||
network_id:
|
||||
get_resource: network_1
|
||||
type: OS::Neutron::Subnet
|
||||
volume_0:
|
||||
properties:
|
||||
image:
|
||||
get_param: volume_0_image
|
||||
metadata:
|
||||
attached_mode: rw
|
||||
readonly: 'False'
|
||||
name: Ubuntu 14.04
|
||||
size: 20
|
||||
volume_type:
|
||||
get_param: volume_0_volume_type
|
||||
type: OS::Cinder::Volume
|
||||
volume_1:
|
||||
properties:
|
||||
name: tellurium_volume
|
||||
size: 5
|
||||
volume_type:
|
||||
get_param: volume_1_volume_type
|
||||
type: OS::Cinder::Volume
|
124
flameclient/tests/fixtures/utils.py
vendored
Normal file
124
flameclient/tests/fixtures/utils.py
vendored
Normal file
@ -0,0 +1,124 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# This software is released under the MIT License.
|
||||
#
|
||||
# Copyright (c) 2018 Orange Cloud for Business / Cloudwatt
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
import os
|
||||
from pprint import pformat
|
||||
|
||||
import six
|
||||
|
||||
from flameclient.utils import get_deep_attr
|
||||
from flameclient.utils import munchify
|
||||
|
||||
|
||||
def get_licence():
|
||||
import flameclient
|
||||
licence_filename = os.path.join(
|
||||
os.path.realpath(os.path.dirname(flameclient.__file__)),
|
||||
'LICENSE.txt'
|
||||
)
|
||||
with open(licence_filename) as fp:
|
||||
return fp.read()
|
||||
|
||||
|
||||
def get_python_header():
|
||||
top = '# -*- coding: utf-8 -*-'
|
||||
lines = get_licence().strip().split('\n')
|
||||
commented_lines = ['# %s' % line.strip() for line in lines]
|
||||
commented_lines = [line.strip() for line in commented_lines]
|
||||
commented_licence = '\n'.join(commented_lines)
|
||||
return '%s\n\n%s\n' % (top, commented_licence)
|
||||
|
||||
|
||||
def write_openstackcloud_fixture_data(filename, attr_name, data):
|
||||
"""Write a fixtures file with given data
|
||||
|
||||
:param str filename: filename holding the fixtures.
|
||||
:param str attr_name: attribute name of the `connection` parameter.
|
||||
|
||||
:param list data: a python list of data which needs to be returned
|
||||
|
||||
"""
|
||||
fixtures = [vars(munchify(element)) for element in data]
|
||||
|
||||
openstackcloud_dir = os.path.join(
|
||||
os.path.realpath(os.path.dirname(__file__)),
|
||||
'openstackcloud'
|
||||
)
|
||||
|
||||
if not filename.startswith('/'):
|
||||
filename = os.path.join(openstackcloud_dir, filename)
|
||||
|
||||
head = get_python_header()
|
||||
|
||||
file_str = "%s\n\nNAME = '%s'\n\nFIXTURES = %s\n" % (
|
||||
head, attr_name, pformat(fixtures, indent=1)
|
||||
)
|
||||
with open(filename, 'w') as fp:
|
||||
fp.write(file_str)
|
||||
|
||||
|
||||
def write_openstackcloud_fixture(filename, attr_name, connection):
|
||||
"""Write a fixtures API call file
|
||||
|
||||
:param str filename: filename holding the fixtures.
|
||||
:param str attr_name: attribute name of the `connection` parameter.
|
||||
|
||||
:param openstack.connection.Connection connection:
|
||||
An `openstack.connection.Connection` instance (`openstacksdk`).
|
||||
Since `shade.openstackcloud.OpenStackCloud` (`shade`) is a subclass
|
||||
you can also use shade instances.
|
||||
|
||||
ex. to write connection.network.security_groups to a fixtures file:
|
||||
|
||||
write_openstackcloud_fixture(
|
||||
'flameclient/tests/fixtures/openstackcloud/security_groups.py',
|
||||
'network.security_groups',
|
||||
connection
|
||||
)
|
||||
|
||||
"""
|
||||
method = get_deep_attr(connection, attr_name)
|
||||
write_openstackcloud_fixture_data(filename, attr_name, method())
|
||||
|
||||
|
||||
def rewrite_all_openstackcloud_fixtures(connection):
|
||||
"""Rewrite all fixtures in flameclient.tests.fixtures
|
||||
|
||||
This function rewrites all fixture files present in
|
||||
flameclient.tests.fixtures from an existing openstack session.
|
||||
|
||||
:param openstack.connection.Connection connection:
|
||||
An `openstack.connection.Connection` instance (`openstacksdk`).
|
||||
Since `shade.openstackcloud.OpenStackCloud` (`shade`) is a subclass
|
||||
you can also use shade instances.
|
||||
|
||||
DANGEROUS! You can break everything!!!
|
||||
"""
|
||||
from flameclient.tests.fixtures import openstackcloud
|
||||
for fixture_module in six.itervalues(openstackcloud.FIXTURES):
|
||||
write_openstackcloud_fixture(
|
||||
fixture_module.__file__,
|
||||
fixture_module.NAME,
|
||||
connection
|
||||
)
|
File diff suppressed because it is too large
Load Diff
@ -1,640 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright (c) 2014 Cloudwatt
|
||||
|
||||
# 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.
|
||||
|
||||
import re
|
||||
|
||||
import mock
|
||||
|
||||
from flameclient import flame
|
||||
from flameclient.tests import base
|
||||
|
||||
|
||||
class FakeBase(object):
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
for key, value in kwargs.items():
|
||||
setattr(self, key, value)
|
||||
|
||||
|
||||
class FakeVolume(FakeBase):
|
||||
id = 1234
|
||||
size = 1
|
||||
source_volid = None
|
||||
bootable = 'false'
|
||||
snapshot_id = None
|
||||
display_name = 'vol1'
|
||||
display_description = 'Description'
|
||||
volume_type = 'fast'
|
||||
metadata = None
|
||||
|
||||
|
||||
class FakeServer(FakeBase):
|
||||
id = '1234'
|
||||
name = 'server1'
|
||||
config_drive = None
|
||||
flavor = {'id': '2'}
|
||||
image = {'id': '3333',
|
||||
'links': [{'href': 'http://p/7777/images/3333',
|
||||
'rel': 'bookmark'}]}
|
||||
key_name = 'testkey'
|
||||
addresses = []
|
||||
metadata = None
|
||||
|
||||
def __init__(self, server_id, **kwargs):
|
||||
self.id = server_id
|
||||
kwargs.setdefault('OS-DCF:diskConfig', 'MANUAL')
|
||||
kwargs.setdefault('os-extended-volumes:volumes_attached', [])
|
||||
super(FakeServer, self).__init__(**kwargs)
|
||||
|
||||
|
||||
class FakeFlavor(FakeBase):
|
||||
name = 'm1.tiny'
|
||||
id = '1'
|
||||
|
||||
|
||||
class FakeKeypair(FakeBase):
|
||||
name = 'key'
|
||||
id = 'key'
|
||||
public_key = 'ssh-rsa AAAAB3NzaC'
|
||||
|
||||
|
||||
class FakeSecurityGroup(FakeBase):
|
||||
id = '1'
|
||||
name = 'name'
|
||||
|
||||
|
||||
class FakeNeutronManager(object):
|
||||
|
||||
def __init__(self):
|
||||
self.groups = [{u'description': u'default',
|
||||
u'id': u'secgorup1',
|
||||
u'name': u'default',
|
||||
u'security_group_rules': [
|
||||
{u'direction': u'ingress',
|
||||
u'ethertype': u'IPv4',
|
||||
u'id': u'secgroup-rule1',
|
||||
u'port_range_max': 65535,
|
||||
u'port_range_min': 1,
|
||||
u'protocol': u'tcp',
|
||||
u'remote_group_id': None,
|
||||
u'remote_ip_prefix': u'0.0.0.0/0',
|
||||
u'security_group_id': u'secgorup1',
|
||||
u'tenant_id': u'tenant1'},
|
||||
],
|
||||
u'tenant_id': u'tenant1'}]
|
||||
|
||||
self.routers = [
|
||||
{u'admin_state_up': True,
|
||||
u'external_gateway_info': {u'enable_snat': True,
|
||||
u'network_id': u'network3'},
|
||||
u'id': u'router1',
|
||||
u'name': u'gw-internal-a',
|
||||
u'routes': [],
|
||||
u'status': u'ACTIVE',
|
||||
u'tenant_id': u'tenant1'},
|
||||
]
|
||||
|
||||
self.ports = [{u'admin_state_up': True,
|
||||
u'allowed_address_pairs': [],
|
||||
u'binding:vnic_type': u'normal',
|
||||
u'device_id': u'router1',
|
||||
u'device_owner': u'network:router_interface',
|
||||
u'extra_dhcp_opts': [],
|
||||
u'fixed_ips': [{u'ip_address': u'192.168.203.1',
|
||||
u'subnet_id': u'subnet3'}],
|
||||
u'id': u'port1',
|
||||
u'mac_address': u'fa:16:3e:fe:c1:b3',
|
||||
u'name': u'',
|
||||
u'network_id': u'network1',
|
||||
u'security_groups': [],
|
||||
u'status': u'ACTIVE',
|
||||
u'tenant_id': u'tenant1'},
|
||||
{u'admin_state_up': True,
|
||||
u'allowed_address_pairs': [],
|
||||
u'binding:vnic_type': u'normal',
|
||||
u'device_id': u'server3',
|
||||
u'device_owner': u'compute:nova',
|
||||
u'extra_dhcp_opts': [],
|
||||
u'fixed_ips': [{u'ip_address': u'192.168.203.5',
|
||||
u'subnet_id': u'subnet3'}],
|
||||
u'id': u'port2',
|
||||
u'mac_address': u'fa:16:3e:e4:44:7b',
|
||||
u'name': u'',
|
||||
u'network_id': u'network1',
|
||||
u'security_groups': [u'secgorup1'],
|
||||
u'status': u'ACTIVE',
|
||||
u'tenant_id': u'tenant1'},
|
||||
{u'admin_state_up': True,
|
||||
u'allowed_address_pairs': [],
|
||||
u'binding:vnic_type': u'normal',
|
||||
u'device_id': u'server2',
|
||||
u'device_owner': u'compute:nova',
|
||||
u'extra_dhcp_opts': [],
|
||||
u'fixed_ips': [{u'ip_address': u'192.168.203.4',
|
||||
u'subnet_id': u'subnet3'}],
|
||||
u'id': u'port3',
|
||||
u'mac_address': u'fa:16:3e:e8:e4:e2',
|
||||
u'name': u'',
|
||||
u'network_id': u'network1',
|
||||
u'security_groups': [u'secgorup1'],
|
||||
u'status': u'ACTIVE',
|
||||
u'tenant_id': u'tenant1'},
|
||||
{u'admin_state_up': True,
|
||||
u'allowed_address_pairs': [],
|
||||
u'binding:vnic_type': u'normal',
|
||||
u'device_id': u'dhcp1-network1',
|
||||
u'device_owner': u'network:dhcp',
|
||||
u'extra_dhcp_opts': [],
|
||||
u'fixed_ips': [{u'ip_address': u'192.168.203.3',
|
||||
u'subnet_id': u'subnet3'},
|
||||
{u'ip_address': u'192.168.204.2',
|
||||
u'subnet_id': u'subnet4'}],
|
||||
u'id': u'port4',
|
||||
u'mac_address': u'fa:16:3e:af:86:30',
|
||||
u'name': u'',
|
||||
u'network_id': u'network1',
|
||||
u'security_groups': [],
|
||||
u'status': u'ACTIVE',
|
||||
u'tenant_id': u'tenant1'},
|
||||
{u'admin_state_up': True,
|
||||
u'allowed_address_pairs': [],
|
||||
u'binding:vnic_type': u'normal',
|
||||
u'device_id': u'server1',
|
||||
u'device_owner': u'compute:nova',
|
||||
u'extra_dhcp_opts': [],
|
||||
u'fixed_ips': [{u'ip_address': u'192.168.203.2',
|
||||
u'subnet_id': u'subnet3'}],
|
||||
u'id': u'port6',
|
||||
u'mac_address': u'fa:16:3e:b0:9a:e2',
|
||||
u'name': u'',
|
||||
u'network_id': u'network1',
|
||||
u'security_groups': [u'secgorup1'],
|
||||
u'status': u'ACTIVE',
|
||||
u'tenant_id': u'tenant1'}
|
||||
]
|
||||
self.subnets = [{u'allocation_pools': [
|
||||
{u'end': u'172.19.0.254', u'start': u'172.19.0.2'}],
|
||||
u'cidr': u'172.19.0.0/24',
|
||||
u'dns_nameservers': [],
|
||||
u'enable_dhcp': True,
|
||||
u'gateway_ip': u'172.19.0.1',
|
||||
u'host_routes': [],
|
||||
u'id': u'subnet1',
|
||||
u'ip_version': 4,
|
||||
u'name': u'storage',
|
||||
u'network_id': u'network2',
|
||||
u'tenant_id': u'tenant1'},
|
||||
{u'allocation_pools': [
|
||||
{u'end': u'10.8.8.200',
|
||||
u'start': u'10.8.8.100'}],
|
||||
u'cidr': u'10.8.8.0/24',
|
||||
u'dns_nameservers': [],
|
||||
u'enable_dhcp': False,
|
||||
u'gateway_ip': u'10.8.8.254',
|
||||
u'host_routes': [],
|
||||
u'id': u'subnet2',
|
||||
u'ip_version': 4,
|
||||
u'name': u'ext-subnet',
|
||||
u'network_id': u'network3',
|
||||
u'tenant_id': u'tenant1'},
|
||||
{u'allocation_pools': [{u'end': u'192.168.203.254',
|
||||
u'start': u'192.168.203.2'}],
|
||||
u'cidr': u'192.168.203.0/24',
|
||||
u'dns_nameservers': [],
|
||||
u'enable_dhcp': True,
|
||||
u'gateway_ip': u'192.168.203.1',
|
||||
u'host_routes': [],
|
||||
u'id': u'subnet3',
|
||||
u'ip_version': 4,
|
||||
u'name': u'int-a-1',
|
||||
u'network_id': u'network1',
|
||||
u'tenant_id': u'tenant1'},
|
||||
{u'allocation_pools': [{u'end': u'192.168.204.254',
|
||||
u'start': u'192.168.204.2'}],
|
||||
u'cidr': u'192.168.204.0/24',
|
||||
u'dns_nameservers': [],
|
||||
u'enable_dhcp': True,
|
||||
u'gateway_ip': u'192.168.204.1',
|
||||
u'host_routes': [],
|
||||
u'id': u'subnet4',
|
||||
u'ip_version': 4,
|
||||
u'name': u'int-a-2',
|
||||
u'network_id': u'network1',
|
||||
u'tenant_id': u'tenant1'}]
|
||||
self.networks = [{u'admin_state_up': True,
|
||||
u'id': u'network1',
|
||||
u'name': u'internal',
|
||||
u'router:external': False,
|
||||
u'shared': False,
|
||||
u'status': u'ACTIVE',
|
||||
u'subnets': [u'subnet3',
|
||||
u'subnet4'],
|
||||
u'tenant_id': u'tenant1'},
|
||||
{u'admin_state_up': True,
|
||||
u'id': u'network2',
|
||||
u'name': u'storage',
|
||||
u'router:external': False,
|
||||
u'shared': False,
|
||||
u'status': u'ACTIVE',
|
||||
u'subnets': [u'subnet1'],
|
||||
u'tenant_id': u'tenant1'},
|
||||
{u'admin_state_up': True,
|
||||
u'id': u'network3',
|
||||
u'name': u'ext-net',
|
||||
u'router:external': True,
|
||||
u'shared': True,
|
||||
u'status': u'ACTIVE',
|
||||
u'subnets': [u'subnet2'],
|
||||
u'tenant_id': u'tenant1'}]
|
||||
|
||||
self.floatingips = [{u'fixed_ip_address': None,
|
||||
u'floating_ip_address': u'10.8.8.102',
|
||||
u'floating_network_id': u'network3',
|
||||
u'id': u'floating1',
|
||||
u'port_id': None,
|
||||
u'router_id': None,
|
||||
u'status': u'DOWN',
|
||||
u'tenant_id': u'tenant1'},
|
||||
{u'fixed_ip_address': None,
|
||||
u'floating_ip_address': u'10.8.8.101',
|
||||
u'floating_network_id': u'network3',
|
||||
u'id': u'floating2',
|
||||
u'port_id': None,
|
||||
u'router_id': None,
|
||||
u'status': u'DOWN',
|
||||
u'tenant_id': u'tenant1'},
|
||||
{u'fixed_ip_address': u'192.168.203.4',
|
||||
u'floating_ip_address': u'10.8.8.168',
|
||||
u'floating_network_id': u'network3',
|
||||
u'id': u'floating3',
|
||||
u'port_id': u'port3',
|
||||
u'router_id': u'router1',
|
||||
u'status': u'ACTIVE',
|
||||
u'tenant_id': u'tenant1'},
|
||||
{u'fixed_ip_address': None,
|
||||
u'floating_ip_address': u'10.8.8.118',
|
||||
u'floating_network_id': u'network3',
|
||||
u'id': u'floating4',
|
||||
u'port_id': None,
|
||||
u'router_id': None,
|
||||
u'status': u'DOWN',
|
||||
u'tenant_id': u'tenant1'}]
|
||||
|
||||
def subnet_list(self):
|
||||
return self.subnets
|
||||
|
||||
def network_list(self):
|
||||
return self.networks
|
||||
|
||||
def port_list(self):
|
||||
return self.ports
|
||||
|
||||
def router_list(self):
|
||||
return self.routers
|
||||
|
||||
def router_interfaces_list(self, router):
|
||||
return [port for port in self.ports
|
||||
if port['device_id'] == router['id']]
|
||||
|
||||
def secgroup_list(self):
|
||||
return self.groups
|
||||
|
||||
def floatingip_list(self):
|
||||
return self.floatingips
|
||||
|
||||
|
||||
class FakeNovaManager(object):
|
||||
|
||||
def __init__(self):
|
||||
self.servers = [FakeServer('server1'),
|
||||
FakeServer('server2'),
|
||||
FakeServer('server3')]
|
||||
self.servergroups = []
|
||||
self.flavors = [FakeFlavor(id='2', name='m1.small')]
|
||||
self.groups = {}
|
||||
self.keypairs = [FakeKeypair(name='testkey',
|
||||
public_key='ssh-rsa XXXX')]
|
||||
|
||||
def keypair_list(self):
|
||||
return self.keypairs
|
||||
|
||||
def flavor_list(self):
|
||||
return self.flavors
|
||||
|
||||
def server_list(self):
|
||||
return self.servers
|
||||
|
||||
def server_security_group_list(self, server):
|
||||
return self.groups.get(server.name, [])
|
||||
|
||||
def servergroup_list(self):
|
||||
return self.servergroups
|
||||
|
||||
|
||||
class FakeCinderManager(object):
|
||||
|
||||
def __init__(self):
|
||||
self.volumes = [FakeVolume(), ]
|
||||
|
||||
def volume_list(self):
|
||||
return self.volumes
|
||||
|
||||
|
||||
class ResourceTestCase(base.TestCase):
|
||||
|
||||
def test_template_resource(self):
|
||||
resource = flame.Resource('my-name',
|
||||
'my-type',
|
||||
properties='my-properties')
|
||||
|
||||
expected = {
|
||||
'my-name': {
|
||||
'type': 'my-type',
|
||||
'properties': 'my-properties',
|
||||
}
|
||||
}
|
||||
self.assertEqual(expected, resource.template_resource)
|
||||
|
||||
|
||||
class BaseTestCase(base.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(BaseTestCase, self).setUp()
|
||||
self.patch_neutron = mock.patch('flameclient.managers.NeutronManager')
|
||||
self.mock_neutron = self.patch_neutron.start()
|
||||
self.patch_nova = mock.patch('flameclient.managers.NovaManager')
|
||||
self.mock_nova = self.patch_nova.start()
|
||||
self.patch_cinder = mock.patch('flameclient.managers.CinderManager')
|
||||
self.mock_cinder = self.patch_cinder.start()
|
||||
|
||||
def tearDown(self):
|
||||
self.mock_neutron.stop()
|
||||
self.mock_nova.stop()
|
||||
self.mock_cinder.stop()
|
||||
super(BaseTestCase, self).tearDown()
|
||||
|
||||
def get_generator(self, exclude_servers, exclude_volumes,
|
||||
exclude_keypairs, generate_data, extract_ports):
|
||||
generator = flame.TemplateGenerator('x', 'x', 'x', 'x', True,
|
||||
'publicURL')
|
||||
generator.extract_vm_details(exclude_servers, exclude_volumes,
|
||||
exclude_keypairs, generate_data,
|
||||
extract_ports)
|
||||
return generator
|
||||
|
||||
def check_stackdata(self, resources, expected_resources):
|
||||
merged_resources = {}
|
||||
for resource in resources:
|
||||
merged_resources.update(resource.stack_resource)
|
||||
|
||||
self.assertEqual(expected_resources, merged_resources)
|
||||
|
||||
def check_template(self, resources, expected_resources,
|
||||
expected_parameters=None):
|
||||
|
||||
expected_parameters = expected_parameters or {}
|
||||
merged_resources = {}
|
||||
merged_parameters = {}
|
||||
for resource in resources:
|
||||
merged_resources.update(resource.template_resource)
|
||||
merged_parameters.update(resource.template_parameter)
|
||||
|
||||
self.assertEqual(expected_resources, merged_resources)
|
||||
self.assertEqual(expected_parameters, merged_parameters)
|
||||
|
||||
|
||||
class StackDataTests(BaseTestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(StackDataTests, self).setUp()
|
||||
self.mock_neutron.return_value = FakeNeutronManager()
|
||||
self.mock_nova.return_value = FakeNovaManager()
|
||||
self.mock_cinder.return_value = FakeCinderManager()
|
||||
|
||||
def test_routers_presents(self):
|
||||
generator = self.get_generator(False, False, False, True, True)
|
||||
extraction = generator._extract_routers()
|
||||
routers = {r.name: r for r in extraction}
|
||||
self.assertIn('router_0', routers)
|
||||
|
||||
def test_routers_resource_names(self):
|
||||
generator = self.get_generator(False, False, False, True, True)
|
||||
generator_output = generator._extract_routers()
|
||||
routers = (res for res in generator_output
|
||||
if res.type == "OS::Neutron::Router")
|
||||
for n, router in enumerate(routers):
|
||||
assert(router.name.startswith("router_"))
|
||||
|
||||
def test_ports_presents(self):
|
||||
generator = self.get_generator(False, False, False, True, True)
|
||||
extraction = generator._extract_ports()
|
||||
ports = {r.name: r for r in extraction}
|
||||
self.assertIn('port_1', ports)
|
||||
self.assertIn('port_2', ports)
|
||||
|
||||
def test_ports_resource_names_types(self):
|
||||
generator = self.get_generator(False, False, False, True, True)
|
||||
extraction = generator._extract_ports()
|
||||
for n, port in enumerate(extraction):
|
||||
props = port.properties
|
||||
assert(extraction[0].name.startswith("port_"))
|
||||
self.assertEqual("OS::Neutron::Port", port.type)
|
||||
self.assertIsInstance(props['admin_state_up'], bool)
|
||||
self.assertIsInstance(props['security_groups'], list)
|
||||
assert(props['device_owner'].startswith("compute:"))
|
||||
|
||||
def test_port_fixed_ip(self):
|
||||
reference = [{'ip_address': '192.168.203.2',
|
||||
'subnet_id': {'get_resource': 'subnet_2'}}]
|
||||
generator = self.get_generator(False, False, False, True, True)
|
||||
extraction = generator._extract_ports()
|
||||
# Get the right port for the test
|
||||
port = next((p for p in extraction if
|
||||
p.properties['mac_address'] == 'fa:16:3e:b0:9a:e2'))
|
||||
props = port.properties
|
||||
self.assertIsInstance(props['fixed_ips'], list)
|
||||
fixed_ips = props['fixed_ips']
|
||||
for ref in reference:
|
||||
self.assertIn(ref, fixed_ips)
|
||||
|
||||
def test_servers_ports_assignations(self):
|
||||
generator = self.get_generator(False, False, False, True, True)
|
||||
extraction = generator._extract_servers()
|
||||
used_ports = []
|
||||
for n, server in enumerate(extraction):
|
||||
props = server.properties
|
||||
self.assertIsInstance(props['networks'], list)
|
||||
for network in props['networks']:
|
||||
port = network['port']['get_resource']
|
||||
assert(port.startswith("port_"))
|
||||
# Port has not been used by another server
|
||||
self.assertNotIn(port, used_ports)
|
||||
used_ports.append(port)
|
||||
|
||||
def test_floating_association(self):
|
||||
generator = self.get_generator(False, False, False, True, True)
|
||||
extraction = generator._extract_floating()
|
||||
associations = (res for res in extraction
|
||||
if res.type == "OS::Neutron::FloatingIPAssociation")
|
||||
for association in associations:
|
||||
props = association.properties
|
||||
assert(props['floatingip_id']['get_resource'].
|
||||
startswith('floatingip_'))
|
||||
assert(props['port_id']['get_resource'].
|
||||
startswith('port_'))
|
||||
|
||||
|
||||
class GenerationTests(BaseTestCase):
|
||||
resource_ref = set(['floatingip_association_2',
|
||||
'subnet_2', 'subnet_3', 'subnet_0',
|
||||
'port_2', 'port_1', 'port_4',
|
||||
'server_2', 'server_1', 'server_0',
|
||||
'router_0',
|
||||
'router_0_interface_0',
|
||||
'router_0_gateway',
|
||||
'key_0',
|
||||
'network_0', 'network_1',
|
||||
'floatingip_0', 'floatingip_1',
|
||||
'floatingip_2', 'floatingip_3',
|
||||
'volume_0'])
|
||||
|
||||
params_ref = set(['volume_0_volume_type',
|
||||
'external_network_for_floating_ip_3',
|
||||
'external_network_for_floating_ip_2',
|
||||
'external_network_for_floating_ip_1',
|
||||
'external_network_for_floating_ip_0',
|
||||
'port_4_default_security_group',
|
||||
'port_1_default_security_group',
|
||||
'port_2_default_security_group',
|
||||
'router_0_external_network',
|
||||
'server_1_image',
|
||||
'server_1_flavor',
|
||||
'server_1_key',
|
||||
'server_2_image',
|
||||
'server_2_flavor',
|
||||
'server_2_key',
|
||||
'server_0_image',
|
||||
'server_0_flavor',
|
||||
'server_0_key'])
|
||||
|
||||
data_ref = set(['floatingip_0', 'floatingip_1', 'floatingip_2',
|
||||
'floatingip_3',
|
||||
'floatingip_association_2',
|
||||
'key_0',
|
||||
'network_0', 'network_1',
|
||||
'port_1', 'port_2', 'port_4',
|
||||
'router_0',
|
||||
'router_0_gateway',
|
||||
'router_0_interface_0',
|
||||
'server_0', 'server_1', 'server_2',
|
||||
'subnet_0', 'subnet_2', 'subnet_3',
|
||||
'volume_0'])
|
||||
|
||||
def filter_set(self, filtered_set, exclude):
|
||||
excluded_set = set()
|
||||
for exc in exclude:
|
||||
excluded_set.update(
|
||||
set([e for e in filtered_set if re.search(exc, e)])
|
||||
)
|
||||
return filtered_set.difference(excluded_set)
|
||||
|
||||
def setUp(self):
|
||||
super(GenerationTests, self).setUp()
|
||||
self.mock_neutron.return_value = FakeNeutronManager()
|
||||
self.mock_nova.return_value = FakeNovaManager()
|
||||
self.mock_cinder.return_value = FakeCinderManager()
|
||||
|
||||
def test_generation(self):
|
||||
|
||||
exclusion_table = [
|
||||
{'call_params': (False, False, False, True, True),
|
||||
'resource_filter': [],
|
||||
'params_filter': ['^server_\d+_key$'],
|
||||
'data_filter': []},
|
||||
# No server
|
||||
{'call_params': (True, False, False, True, True),
|
||||
'resource_filter': ['^server'],
|
||||
'params_filter': ['^server'],
|
||||
'data_filter': ['^server']},
|
||||
# No volumes
|
||||
{'call_params': (False, True, False, True, True),
|
||||
'resource_filter': ['^volume'],
|
||||
'params_filter': [r'^volume_\d+_volume_type$',
|
||||
'^server_\d+_key$'],
|
||||
'data_filter': ['^volume']},
|
||||
# No keys
|
||||
{'call_params': (False, False, True, True, True),
|
||||
'resource_filter': ['^key_\d+$'],
|
||||
'params_filter': [],
|
||||
'data_filter': ['^key', 'server_\d+_key']},
|
||||
# No ports
|
||||
{'call_params': (False, False, False, True, False),
|
||||
'resource_filter': ['^port_\d+$'],
|
||||
'params_filter': ['^port_\d+_default_security_group$',
|
||||
'server_\d+_key$'],
|
||||
'data_filter': ['^port_\d+', '^floatingip_association_\d+$']},
|
||||
]
|
||||
|
||||
for exclusion in exclusion_table:
|
||||
generator = self.get_generator(*exclusion['call_params'])
|
||||
resource_ref = self.filter_set(self.resource_ref,
|
||||
exclusion['resource_filter'])
|
||||
params_ref = self.filter_set(self.params_ref,
|
||||
exclusion['params_filter'])
|
||||
data_ref = self.filter_set(self.data_ref,
|
||||
exclusion['data_filter'])
|
||||
|
||||
generator.extract_data()
|
||||
# All the resources, params and datas are present
|
||||
self.assertEqual(resource_ref,
|
||||
set(generator.template['resources'].keys()),
|
||||
"Called with : %r" % (exclusion['call_params'],))
|
||||
self.assertEqual(params_ref,
|
||||
set(generator.template['parameters'].keys()),
|
||||
"Called with : %r" % (exclusion['call_params'],))
|
||||
self.assertEqual(data_ref,
|
||||
set(generator.stack_data['resources'].keys()),
|
||||
"Called with : %r" % (exclusion['call_params'],))
|
||||
|
||||
def test_floating_association_data(self):
|
||||
generator = self.get_generator(False, False, False, True, True)
|
||||
generator.extract_data()
|
||||
# Look for floating ips
|
||||
assoc_name = 'floatingip_association_2'
|
||||
association_data = generator.stack_data['resources'][assoc_name]
|
||||
reference = {'action': 'CREATE',
|
||||
'metadata': {},
|
||||
'name': 'floatingip_association_2',
|
||||
'resource_data': {},
|
||||
'resource_id': u'floating3:port3',
|
||||
'status': 'COMPLETE',
|
||||
'type': 'OS::Neutron::FloatingIPAssociation'}
|
||||
self.assertEqual(reference, association_data)
|
||||
|
||||
def test_port_data(self):
|
||||
generator = self.get_generator(False, False, False, True, True)
|
||||
generator.extract_data()
|
||||
# Look for floating ips
|
||||
assoc_name = 'port_2'
|
||||
association_data = generator.stack_data['resources'][assoc_name]
|
||||
reference = {'action': 'CREATE',
|
||||
'metadata': {},
|
||||
'name': 'port_2',
|
||||
'resource_data': {},
|
||||
'resource_id': u'port3',
|
||||
'status': 'COMPLETE',
|
||||
'type': 'OS::Neutron::Port'}
|
||||
self.assertEqual(reference, association_data)
|
59
flameclient/tests/test_utils.py
Normal file
59
flameclient/tests/test_utils.py
Normal file
@ -0,0 +1,59 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# This software is released under the MIT License.
|
||||
#
|
||||
# Copyright (c) 2018 Orange Cloud for Business / Cloudwatt
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
from flameclient.tests import unittest
|
||||
from flameclient import utils
|
||||
|
||||
|
||||
class TestUtils(unittest.TestCase):
|
||||
def test_camel_to_snake(self):
|
||||
for inp, outp in (
|
||||
('camelcase', 'camelcase'),
|
||||
('Camelcase', 'camelcase'),
|
||||
('camelCase', 'camel_case'),
|
||||
('CamelCase', 'camel_case'),
|
||||
('camelCCase', 'camel_c_case'),
|
||||
('CCamelCase', 'c_camel_case'),
|
||||
('CCCCamelCase', 'ccc_camel_case'),
|
||||
('CCCcamelCase', 'cc_ccamel_case'),
|
||||
('Camel123case', 'camel_123case'),
|
||||
('Camel123Case', 'camel_123_case'),
|
||||
):
|
||||
self.assertEqual(utils.camel_to_snake(inp), outp)
|
||||
|
||||
def test_format_option(self):
|
||||
for option, formated in (
|
||||
('--foo-bar', 'foo_bar'),
|
||||
('--this-is-a-long-option', 'this_is_a_long_option')
|
||||
):
|
||||
self.assertEqual(
|
||||
formated, utils.format_option(option)
|
||||
)
|
||||
|
||||
def test_format_option_kwargs(self):
|
||||
self.assertEqual(
|
||||
{'foo_bar': 'value'}, utils.format_option_kwargs(
|
||||
{'--foo-bar': 'value'}
|
||||
)
|
||||
)
|
44
flameclient/tests/utils.py
Normal file
44
flameclient/tests/utils.py
Normal file
@ -0,0 +1,44 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# This software is released under the MIT License.
|
||||
#
|
||||
# Copyright (c) 2018 Orange Cloud for Business / Cloudwatt
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
import six
|
||||
|
||||
import openstack
|
||||
|
||||
from flameclient.tests import mock
|
||||
from flameclient.utils import get_deep_attr
|
||||
from flameclient.utils import munchify
|
||||
|
||||
|
||||
def get_mocked_openstackcloud():
|
||||
from flameclient.tests.fixtures import openstackcloud
|
||||
|
||||
cloud = mock.Mock(spec_set=openstack.connection.Connection)
|
||||
# for each self.conn.`fixture_module.NAME`() call we will return
|
||||
# fixture_module.FIXTURES
|
||||
for fixture_module in six.itervalues(openstackcloud.FIXTURES):
|
||||
get_deep_attr(
|
||||
cloud, fixture_module.NAME
|
||||
).return_value = munchify(fixture_module.FIXTURES)
|
||||
return cloud
|
363
flameclient/utils.py
Normal file
363
flameclient/utils.py
Normal file
@ -0,0 +1,363 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# This software is released under the MIT License.
|
||||
#
|
||||
# Copyright (c) 2018 Orange Cloud for Business / Cloudwatt
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
import argparse
|
||||
import re
|
||||
from threading import Lock
|
||||
|
||||
import importlib
|
||||
import os
|
||||
import pkgutil
|
||||
import sys
|
||||
|
||||
import munch
|
||||
import pkg_resources
|
||||
import six
|
||||
|
||||
from flameclient import collections_abc
|
||||
|
||||
|
||||
CS2STR1 = re.compile('(.)([A-Z][a-z]+)')
|
||||
CS2STR2 = re.compile('(.)([0-9]+)')
|
||||
CS2STR3 = re.compile('([a-z0-9])([A-Z])')
|
||||
REPLSTR = r'\1_\2'
|
||||
|
||||
|
||||
def camel_to_snake(string):
|
||||
"""Transform camel_case string to snake_case string"""
|
||||
return CS2STR3.sub(
|
||||
REPLSTR, CS2STR2.sub(REPLSTR, CS2STR1.sub(REPLSTR, string))
|
||||
).lower()
|
||||
|
||||
|
||||
def sys_path_to_module(path):
|
||||
full_path = os.path.realpath(os.path.abspath(path))
|
||||
path = full_path
|
||||
while True:
|
||||
if path in sys.path:
|
||||
break
|
||||
path = os.path.dirname(path)
|
||||
if path == '/':
|
||||
return ''
|
||||
return path
|
||||
|
||||
|
||||
def get_module_name_from_file(filename):
|
||||
filename = os.path.realpath(os.path.abspath(filename))
|
||||
sys_path = '%s/' % sys_path_to_module(filename)
|
||||
package_path = filename.split(sys_path, 1)[1]
|
||||
package_path = package_path.rsplit('.py', 1)[0]
|
||||
return package_path.replace('/', '.')
|
||||
|
||||
|
||||
def load_resource_modules(base_file_or_dir, exclude=tuple()):
|
||||
"""Load packages in a directory
|
||||
|
||||
base_file_or_dir: the base file or dir where we will load packages.
|
||||
prefix: the prefix to add to module names.
|
||||
"""
|
||||
modules = {}
|
||||
if isinstance(exclude, six.string_types):
|
||||
exclude = (exclude, )
|
||||
full_path = os.path.realpath(os.path.abspath(base_file_or_dir))
|
||||
if os.path.isdir(full_path):
|
||||
pkg_dir = full_path
|
||||
elif os.path.isfile(full_path):
|
||||
pkg_dir = os.path.dirname(full_path)
|
||||
else:
|
||||
raise ImportError('Can not find "%s"' % full_path)
|
||||
prefix = "%s." % get_module_name_from_file(pkg_dir)
|
||||
for _, name, ispkg in pkgutil.iter_modules([pkg_dir], prefix):
|
||||
# `name` has the form "foo.bar.plop"
|
||||
# We do not want to load "foo.bar.test*" modules to not load unittest
|
||||
# files.
|
||||
# We also do not want to load files starting with an underscore.
|
||||
if (
|
||||
not name.split('.')[-1].startswith('test') and
|
||||
not name.split('.')[-1].startswith('_') and
|
||||
name not in exclude and
|
||||
not ispkg
|
||||
):
|
||||
modules[name] = importlib.import_module(name)
|
||||
return modules
|
||||
|
||||
|
||||
def load_resource_entry_points(name='openstack_flame'):
|
||||
entry_points = {}
|
||||
for entry_point in pkg_resources.iter_entry_points(name):
|
||||
entry_points[entry_point.name] = entry_point.load()
|
||||
return entry_points
|
||||
|
||||
|
||||
def munchify(obj, iterator_type=list, remunch=False):
|
||||
"""Transforms an object into a `munch.Munch` object when possible.
|
||||
|
||||
The difference with `munch.munchify` is that when an object has a
|
||||
`_to_munch` method, we call this method which was designed for it.
|
||||
|
||||
This method is useful when we have `openstack.resource.Resource` objects
|
||||
because they have a `_to_munch` method.
|
||||
|
||||
The purpose is to have the same type of objects whether we use
|
||||
`openstack.connection.Connection` methods or
|
||||
`shade.openstackcloud.OpenStackCloud` specific methods.
|
||||
|
||||
`openstack.connection.Connection` methods return
|
||||
`openstack.resource.Resource` subclasses and
|
||||
`shade.openstackcloud.OpenStackCloud` methods return `munch.Munch` objects.
|
||||
|
||||
:param bool remunch: If True we return a deep copy of the object if it's
|
||||
already a `munch.Munch` instance. By default we
|
||||
return the `munch.Munch` object as is.
|
||||
|
||||
|
||||
:param function iterator_type: If we have an iterator instead of an
|
||||
iterable object we return a list by default.
|
||||
You can change this behaviour by passing the
|
||||
callable to the type you want (ex.: tuple).
|
||||
This only affects Iterators and not
|
||||
iterables for which we keep the same type.
|
||||
You get an iterator when you have an
|
||||
`openstack.connection.Connection` instance
|
||||
and do e.g.: `conn.compute.servers()`.
|
||||
So if you call
|
||||
`munchify(conn.compute.servers())` you will
|
||||
get the iterator_type (a list by default).
|
||||
"""
|
||||
|
||||
# Check
|
||||
# https://docs.python.org/2/library/collections.html#collections-abstract-base-classes # noqa
|
||||
# or
|
||||
# https://docs.python.org/3/library/collections.abc.html#collections-abstract-base-classes # noqa
|
||||
# To know in which order to test.
|
||||
if not remunch and isinstance(obj, munch.Munch):
|
||||
return obj
|
||||
if hasattr(obj, '_to_munch'):
|
||||
return obj._to_munch()
|
||||
elif isinstance(obj, collections_abc.Mapping): # Test for `dict` likes.
|
||||
# Mappings (dicts, OrderedDict, etc...) are iterable so it
|
||||
# needs to be tested before iterable types.
|
||||
return munch.Munch(
|
||||
(key, munchify(value)) for key, value in six.iteritems(obj)
|
||||
)
|
||||
elif isinstance(obj, six.string_types):
|
||||
# Strings are iterable so this needs to be tested before the
|
||||
# iterable types.
|
||||
return obj
|
||||
elif isinstance(obj, collections_abc.Iterator):
|
||||
# `Iterator` is a subclass of `Iterable` so we need to test it first.
|
||||
return iterator_type(munchify(elt) for elt in obj)
|
||||
elif isinstance(obj, collections_abc.Iterable):
|
||||
# At last, check if we have an iterable object.
|
||||
return type(obj)(munchify(elt) for elt in obj)
|
||||
else:
|
||||
return munch.munchify(obj)
|
||||
|
||||
|
||||
def data_list_to_dict(data_list, enum=True):
|
||||
data_dict = munch.Munch()
|
||||
for num, data in enumerate(data_list):
|
||||
data_dict[data.id] = munchify(data)
|
||||
if enum:
|
||||
data_dict[data.id].enum = num
|
||||
return data_dict
|
||||
|
||||
|
||||
def clean_dict(obj, clean_list=True, super_clean=False, iterator_type=list):
|
||||
"""Returns a dict copy with only values which are not None
|
||||
|
||||
:param bool clean_list: whether to suppress or not None values from lists
|
||||
:param bool super_clean: whether to suppress or not values which evaluate
|
||||
to False (not only None).
|
||||
:param function iterator_type: cast function for iterator types.
|
||||
|
||||
"""
|
||||
|
||||
if isinstance(obj, six.string_types):
|
||||
return obj
|
||||
elif isinstance(obj, collections_abc.Mapping):
|
||||
if super_clean:
|
||||
return type(obj)(
|
||||
(key, clean_dict(
|
||||
value, clean_list=clean_list, super_clean=super_clean))
|
||||
for key, value in six.iteritems(obj) if value
|
||||
)
|
||||
return type(obj)(
|
||||
(key, clean_dict(
|
||||
value, clean_list=clean_list, super_clean=super_clean))
|
||||
for key, value in six.iteritems(obj)if value is not None
|
||||
)
|
||||
elif isinstance(obj, collections_abc.Iterator):
|
||||
if super_clean:
|
||||
return iterator_type(
|
||||
clean_dict(elt, clean_list=clean_list, super_clean=super_clean)
|
||||
for elt in obj if elt or not clean_list
|
||||
)
|
||||
return iterator_type(
|
||||
clean_dict(elt, clean_list=clean_list, super_clean=super_clean)
|
||||
for elt in obj if elt is not None or not clean_list
|
||||
)
|
||||
elif isinstance(obj, collections_abc.Iterable):
|
||||
# At last, check if we have an iterable object.
|
||||
if super_clean:
|
||||
return type(obj)(
|
||||
clean_dict(elt, clean_list=clean_list, super_clean=super_clean)
|
||||
for elt in obj if elt or not clean_list
|
||||
)
|
||||
return type(obj)(
|
||||
clean_dict(elt, clean_list=clean_list, super_clean=super_clean)
|
||||
for elt in obj if elt is not None or not clean_list
|
||||
)
|
||||
else:
|
||||
return obj
|
||||
|
||||
|
||||
def format_option(option_str):
|
||||
option_str = option_str.lstrip('-')
|
||||
option_str = option_str.replace('-', '_')
|
||||
return option_str
|
||||
|
||||
|
||||
def format_option_kwargs(kwargs):
|
||||
"""Format a dictionary with option names to dict keys.
|
||||
|
||||
This will allow further keyword arguments passing of argparse options.
|
||||
|
||||
example:
|
||||
change `{'--foo-bar': 'value'}` to `{'foo_bar': 'value'}` etc...
|
||||
|
||||
"""
|
||||
return {
|
||||
format_option(key): value for key, value in six.iteritems(kwargs)
|
||||
}
|
||||
|
||||
|
||||
def dict_to_options(kwargs):
|
||||
if kwargs is not None:
|
||||
if isinstance(kwargs, argparse.Namespace):
|
||||
return kwargs
|
||||
return argparse.Namespace(**format_option_kwargs(kwargs))
|
||||
return None
|
||||
|
||||
|
||||
def rename_os_kwargs(kwargs, clean=False):
|
||||
"""Clean Openstack kwargs from the 'os_' prefix.
|
||||
|
||||
envvars return 'os_username', 'os_auth_url', etc... variables.
|
||||
we want to remove the 'os_' prefix
|
||||
|
||||
:param dict kwargs: the dictionary to clean
|
||||
|
||||
:param bool clean: If true, the returned dictionary will not have keys
|
||||
with empty values.
|
||||
|
||||
"""
|
||||
new_kwargs = {}
|
||||
for key, value in six.iteritems(kwargs):
|
||||
if value or not clean:
|
||||
if key.startswith('os_'):
|
||||
new_kwargs[key.split('os_')[1]] = value
|
||||
else:
|
||||
new_kwargs[key] = value
|
||||
return new_kwargs
|
||||
|
||||
|
||||
def rename_os_options(options, clean=False):
|
||||
"""Clean Openstack envvars from the 'os_' prefix.
|
||||
|
||||
envvars return 'os_username', 'os_auth_url', etc... variables.
|
||||
we want to remove the 'os_' prefix
|
||||
|
||||
:param argparse.Namespace options: the options to clean
|
||||
|
||||
:param bool clean: If true, the returned options will not have
|
||||
attributes with empty values.
|
||||
"""
|
||||
kwargs = vars(options)
|
||||
renamed_kwargs = rename_os_kwargs(kwargs, clean=clean)
|
||||
return argparse.Namespace(**renamed_kwargs)
|
||||
|
||||
|
||||
def hash_func_call(func, *args, **kwargs):
|
||||
"""hash a function call"""
|
||||
# kwargs is a dict, and dicts are not hashable.
|
||||
kwargs_tuple = tuple((key, value) for key, value in six.iteritems(kwargs))
|
||||
return hash((func, args, kwargs_tuple))
|
||||
|
||||
|
||||
def get_deep_attr(obj, value):
|
||||
"""Get deep attribute
|
||||
|
||||
example, `getattr(some_object, 'attr.subattr')` does not work.
|
||||
With get_deep_attr it works.
|
||||
|
||||
"""
|
||||
subelts = value.split('.', 1)
|
||||
if len(subelts) == 1:
|
||||
return getattr(obj, value)
|
||||
else:
|
||||
return get_deep_attr(getattr(obj, subelts[0]), subelts[1])
|
||||
|
||||
|
||||
def memoized_property(func):
|
||||
"""Decorator to set properties which will be computed only once
|
||||
|
||||
"""
|
||||
attr_name = '__%s' % func.__name__
|
||||
lock = Lock()
|
||||
|
||||
class FixedProperty(object):
|
||||
def __get__(self, instance, owner):
|
||||
if instance:
|
||||
with lock:
|
||||
try:
|
||||
return getattr(instance, attr_name)
|
||||
except AttributeError:
|
||||
result = func(instance)
|
||||
setattr(instance, attr_name, result)
|
||||
return result
|
||||
|
||||
return self
|
||||
|
||||
def __set__(self, instance, value):
|
||||
with lock:
|
||||
setattr(instance, attr_name, value)
|
||||
|
||||
def __delete__(self, instance):
|
||||
with lock:
|
||||
delattr(instance, attr_name)
|
||||
|
||||
return FixedProperty()
|
||||
|
||||
|
||||
class ClassProperty(classmethod):
|
||||
|
||||
def __get__(self, instance, owner):
|
||||
return self.__func__(owner)
|
||||
|
||||
def __set__(self, instance, value):
|
||||
setattr(instance, self.__func__.__name__, value)
|
||||
|
||||
def __delete__(self, instance):
|
||||
delattr(instance, self.__func__)
|
110
pylintrc
Normal file
110
pylintrc
Normal file
@ -0,0 +1,110 @@
|
||||
[MASTER]
|
||||
profile=no
|
||||
persistent=yes
|
||||
ignore=migrations
|
||||
|
||||
|
||||
[MESSAGES CONTROL]
|
||||
# C0103 Invalid %s name "%s"
|
||||
# C0111 Missing docstring
|
||||
# C0302 Too many lines in module
|
||||
# C0330 Wrong hanging indentation before block (We let pep8 check this)
|
||||
# E0611 No name %r in module %r
|
||||
# E1101 %s %r has no %r member
|
||||
# E1102 %s is not callable
|
||||
# E1133 Non-iterable value %s is used in an iterating context # (caused by flameclient.utils.memoized_property)
|
||||
# E1135 Value '%s' doesn't support membership test # (caused by flameclient.utils.memoized_property)
|
||||
# E1136 %s is unsubscriptable # (caused by flameclient.utils.fixed_property)
|
||||
# F0401 Unable to import %s
|
||||
# I0011 Warning locally suppressed using disable-msg
|
||||
# I0012 Warning locally suppressed using disable-msg
|
||||
# R0123 Comparison to literal
|
||||
# R0201 Method could be a function
|
||||
# R0901 Too many ancestors
|
||||
# R0902 Too many instance attributes
|
||||
# R0904 Too many public methods
|
||||
# R0911 Too many return statements
|
||||
# R0912 Too many branches
|
||||
# R0914 Too many local variables
|
||||
# R0915 Too many statements
|
||||
# R1705 Unnecessary "else" after "return"
|
||||
# R1710 inconsistent-return-statements
|
||||
# W0142 Used * or * magic* Used when a function or method is called using *args or **kwargs to dispatch arguments.
|
||||
# W0212 Access to a protected member %s of a client class
|
||||
# W0223 Method %r is abstract in class %r but is not overridden
|
||||
# W0232 Class has no __init__ method Used when a class has no __init__ method, neither its parent classes.
|
||||
# W0403 Relative import '%s', should be '%s'
|
||||
# W0511 Used when a warning note as FIXME or XXX is detected.
|
||||
# W0613 Unused argument %r Used when a function or method argument is not used.
|
||||
# W0702 No exception's type specified Used when an except clause doesn't specify exceptions type to catch.
|
||||
# W0704 Except doesn't do anything Used when an except clause does nothing but "pass" and there is no "else" clause
|
||||
# W1113 keyword-arg-before-vararg
|
||||
# example:
|
||||
# disable=C0111,I0011,I0012,R0201,W0142,W0212,W0232,W0613,W0702,W0704
|
||||
# or:
|
||||
# disable=I0011,I0012,W0142,W0212,W0232
|
||||
disable=C0103,C0111,C0302,C0330,E0611,E1101,E1102,E1133,E1135,E1136,I0011,I0012,R0123,R0901,R0902,R0904,R0911,R0912,R0914,R0915,R1705,R1710,W0142,W0212,W0223,W0403,W0511,W0613,W0702,W0704,W1113
|
||||
|
||||
|
||||
[REPORTS]
|
||||
include-ids=yes
|
||||
output-format=parseable
|
||||
#reports=yes
|
||||
|
||||
|
||||
[BASIC]
|
||||
#no-docstring-rgx=__.*__|_.*
|
||||
const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__)|logger|register|urlpatterns)$
|
||||
method-rgx=([a-z_][a-z0-9_]{2,30}|setUp|tearDown|test_[a-z0-9_]{2,60}|assert[a-zA-Z0-9]{2,30})$
|
||||
#good-names=_,i,j,k,e,v,db,qs,pk
|
||||
good-names=_,i,j,k,e,v,by,fp,td,tr
|
||||
|
||||
|
||||
[TYPECHECK]
|
||||
ignore-mixin-members=yes
|
||||
#ignored-classes=SQLObject,WSGIRequest
|
||||
#zope=no
|
||||
#generated-members=objects,DoesNotExist,id,pk,_meta,base_fields,context
|
||||
|
||||
|
||||
[VARIABLES]
|
||||
#init-import=no
|
||||
#dummy-variables-rgx=_|dummy
|
||||
#additional-builtins=
|
||||
|
||||
|
||||
[SIMILARITIES]
|
||||
min-similarity-lines=6
|
||||
#ignore-comments=yes
|
||||
#ignore-docstrings=yes
|
||||
ignore-imports=yes
|
||||
|
||||
|
||||
[MISCELLANEOUS]
|
||||
notes=FIXME,XXX,TODO
|
||||
|
||||
|
||||
[FORMAT]
|
||||
max-line-length=1000
|
||||
max-module-lines=500
|
||||
indent-string=' '
|
||||
|
||||
|
||||
[CLASSES]
|
||||
#defining-attr-methods=__init__,__new__,setUp
|
||||
|
||||
|
||||
[DESIGN]
|
||||
max-args=10
|
||||
max-locals=15
|
||||
max-returns=6
|
||||
max-branchs=12
|
||||
max-statements=50
|
||||
max-parents=7
|
||||
max-attributes=7
|
||||
min-public-methods=0
|
||||
max-public-methods=50
|
||||
|
||||
|
||||
[IMPORTS]
|
||||
#deprecated-modules=regsub,TERMIOS,Bastion,rexec
|
@ -1,10 +1,20 @@
|
||||
pbr>=1.6
|
||||
Babel>=1.3
|
||||
futures
|
||||
|
||||
netaddr>=0.7.12,!=0.7.16
|
||||
python-keystoneclient
|
||||
python-neutronclient
|
||||
python-novaclient
|
||||
python-cinderclient
|
||||
PyYAML
|
||||
certifi==2018.8.24
|
||||
futures>=3.1.1,<=3.2.0
|
||||
keystoneauth1==3.11.0
|
||||
ndg-httpsclient==0.5.1
|
||||
netaddr==0.7.19
|
||||
openstacksdk==0.17.2
|
||||
os-client-config==1.31.2
|
||||
pbr==4.2.0
|
||||
pyasn1==0.4.4
|
||||
pyOpenSSL==18.0.0
|
||||
python-cinderclient==4.0.1
|
||||
python-glanceclient==2.12.1
|
||||
python-heatclient==1.16.1
|
||||
python-keystoneclient==3.17.0
|
||||
python-neutronclient==6.10.0
|
||||
python-novaclient==11.0.0
|
||||
python-openstackclient==3.16.1
|
||||
python-swiftclient==3.6.0
|
||||
PyYAML==3.13
|
||||
shade==1.29.0
|
||||
|
@ -3,7 +3,7 @@ name = python-flameclient
|
||||
summary = Automatic Heat template generation
|
||||
description-file =
|
||||
README.rst
|
||||
author = CloudWatt
|
||||
author = Orange Cloud for Business / CloudWatt
|
||||
author-email = info@cloudwatt.com
|
||||
home-page = http://www.cloudwatt.com/
|
||||
classifier =
|
||||
|
@ -1,13 +1,17 @@
|
||||
hacking>=0.10.2,<0.11
|
||||
|
||||
futures
|
||||
coverage>=3.6
|
||||
discover
|
||||
mock>=1.2
|
||||
fixtures>=1.3.1
|
||||
python-subunit
|
||||
sphinx>=1.1.2,!=1.2.0,!=1.3b1,<1.3
|
||||
oslosphinx
|
||||
testrepository>=0.0.18
|
||||
testscenarios>=0.4
|
||||
testtools>=1.4.0
|
||||
coverage==4.5.1
|
||||
discover==0.4.0
|
||||
fixtures==3.0.0
|
||||
hacking==1.1.0
|
||||
mccabe<0.6,>=0.2.1
|
||||
mock==2.0.0
|
||||
oslosphinx==4.18.0
|
||||
os-testr==1.0.0
|
||||
pycodestyle==2.0.0
|
||||
pylint==1.9.3
|
||||
python-subunit==1.3.0
|
||||
sphinx==1.8.0
|
||||
stestr==2.1.1
|
||||
testrepository==0.0.20
|
||||
testscenarios==0.5.0
|
||||
testtools==2.3.0
|
||||
tox==3.4.0
|
||||
|
11
tox.ini
11
tox.ini
@ -1,11 +1,11 @@
|
||||
[tox]
|
||||
minversion = 1.6
|
||||
envlist = py33,py27,pypy,pep8
|
||||
envlist = py37,py36,py35,py34,py27,pypy,pep8,pylint
|
||||
skipsdist = True
|
||||
|
||||
[testenv]
|
||||
usedevelop = True
|
||||
install_command = pip install -U {opts} {packages}
|
||||
install_command = pip install -c {toxinidir}/upper-constraints.txt -U {opts} {packages}
|
||||
setenv =
|
||||
VIRTUAL_ENV={envdir}
|
||||
deps = -r{toxinidir}/requirements.txt
|
||||
@ -13,7 +13,10 @@ deps = -r{toxinidir}/requirements.txt
|
||||
commands = python setup.py testr --slowest --testr-args='{posargs}'
|
||||
|
||||
[testenv:pep8]
|
||||
commands = flake8
|
||||
commands = python -m flake8 flameclient
|
||||
|
||||
[testenv:pylint]
|
||||
commands = python -m pylint --rcfile=pylintrc --reports=yes flameclient
|
||||
|
||||
[testenv:venv]
|
||||
commands = {posargs}
|
||||
@ -30,4 +33,4 @@ commands = python setup.py build_sphinx
|
||||
show-source = True
|
||||
ignore = H803
|
||||
builtins = _
|
||||
exclude=.venv,.git,.tox,dist,doc,*openstack/common*,*lib/python*,*egg,build
|
||||
exclude=.venv,.git,.tox,dist,doc,*openstack/common*,*lib/python*,*egg,build,flameclient/tests/fixtures/openstackcloud/*
|
||||
|
552
upper-constraints.txt
Normal file
552
upper-constraints.txt
Normal file
@ -0,0 +1,552 @@
|
||||
ntlm-auth===1.2.0
|
||||
voluptuous===0.11.5
|
||||
chardet===3.0.4
|
||||
rsa===3.4.2
|
||||
restructuredtext-lint===1.1.3
|
||||
netmiko===2.2.2
|
||||
instack-undercloud===9.3.0
|
||||
PasteDeploy===1.5.2
|
||||
typing===3.6.6
|
||||
python-saharaclient===2.0.0
|
||||
python-hnvclient===0.1.0
|
||||
Routes===2.4.1
|
||||
rtslib-fb===2.1.66
|
||||
XStatic-Angular-Bootstrap===2.2.0.0
|
||||
paunch===3.2.0
|
||||
WebOb===1.8.2
|
||||
sphinxcontrib-actdiag===0.8.5
|
||||
docopt===0.6.2
|
||||
pecan===1.3.2
|
||||
ryu===4.27
|
||||
os-api-ref===1.5.0
|
||||
python-ldap===3.1.0
|
||||
oslo.concurrency===3.27.0
|
||||
websocket-client===0.53.0
|
||||
osprofiler===2.3.0
|
||||
tabulate===0.8.2
|
||||
python-ironic-inspector-client===3.3.0
|
||||
lxml===4.2.5
|
||||
python-kingbirdclient===0.2.1
|
||||
setproctitle===1.1.10
|
||||
pytest===3.8.0
|
||||
python-etcd===0.4.5
|
||||
raven===6.9.0
|
||||
cursive===0.2.2
|
||||
oslo.service===1.32.0
|
||||
django-appconf===1.0.2
|
||||
pykerberos===1.2.1
|
||||
certifi===2018.8.24
|
||||
sphinxcontrib-nwdiag===0.9.5
|
||||
requests-aws===0.1.8
|
||||
alabaster===0.7.11
|
||||
pbr===4.2.0
|
||||
munch===2.3.2
|
||||
attrs===18.2.0
|
||||
microversion-parse===0.2.1
|
||||
Pint===0.8.1
|
||||
oslo.i18n===3.21.0
|
||||
jsonpath-rw-ext===1.1.3
|
||||
python-mistralclient===3.7.0
|
||||
oslo.context===2.21.0
|
||||
python-senlinclient===1.8.0
|
||||
rcssmin===1.0.6
|
||||
pycadf===2.8.0
|
||||
grpcio===1.15.0
|
||||
skydive-client===0.4.5
|
||||
pysendfile===2.0.1
|
||||
fixtures===3.0.0
|
||||
neutron-lib===1.18.0
|
||||
XStatic-FileSaver===1.3.2.0
|
||||
pystache===0.5.4
|
||||
XStatic-Font-Awesome===4.7.0.0
|
||||
nose===1.3.7
|
||||
nosehtmloutput===0.0.5
|
||||
waitress===1.1.0
|
||||
os-refresh-config===9.1.0
|
||||
pysnmp===4.4.6
|
||||
sphinxcontrib-websupport===1.1.0
|
||||
Mako===1.0.7
|
||||
XStatic-angular-ui-router===0.3.1.2
|
||||
pyScss===1.3.4
|
||||
XStatic-jQuery===1.10.2.1
|
||||
jsonmodels===2.3
|
||||
ddt===1.2.0
|
||||
pyserial===3.4
|
||||
ipaddress===1.0.22;python_version=='2.7'
|
||||
python-freezerclient===1.7.0
|
||||
os-xenapi===0.3.4
|
||||
python-vitrageclient===2.3.0
|
||||
nosexcover===1.0.11
|
||||
krest===1.3.1
|
||||
psycopg2===2.7.5
|
||||
networkx===2.1
|
||||
bashate===0.6.0
|
||||
XStatic-Angular===1.5.8.0
|
||||
pyngus===2.2.4
|
||||
Pillow===5.2.0
|
||||
zuul-sphinx===0.2.5
|
||||
python-mimeparse===1.6.0
|
||||
tripleo-common===9.3.0
|
||||
Tempita===0.5.2
|
||||
ply===3.11
|
||||
requests-toolbelt===0.8.0
|
||||
simplejson===3.16.0
|
||||
suds-jurko===0.6
|
||||
python-swiftclient===3.6.0
|
||||
pyOpenSSL===18.0.0
|
||||
monasca-common===2.11.0
|
||||
scipy===1.1.0
|
||||
rsd-lib===0.2.2
|
||||
XStatic-Jasmine===2.4.1.1
|
||||
python-glanceclient===2.12.1
|
||||
pyinotify===0.9.6
|
||||
debtcollector===1.20.0
|
||||
requests-unixsocket===0.1.5
|
||||
asn1crypto===0.24.0
|
||||
croniter===0.3.25
|
||||
python-watcherclient===2.1.0
|
||||
MarkupSafe===1.0
|
||||
pypowervm===1.1.18
|
||||
doc8===0.8.0
|
||||
pymongo===3.7.1
|
||||
sqlparse===0.2.4
|
||||
oslotest===3.6.0
|
||||
jsonpointer===2.0
|
||||
defusedxml===0.5.0
|
||||
netaddr===0.7.19
|
||||
pyghmi===1.2.14
|
||||
sphinxcontrib-blockdiag===1.5.5
|
||||
thrift===0.11.0
|
||||
gnocchiclient===7.0.5
|
||||
wcwidth===0.1.7
|
||||
sphinxcontrib.datatemplates===0.1.0
|
||||
jsonpath-rw===1.4.0
|
||||
prettytable===0.7.2
|
||||
vine===1.1.4
|
||||
taskflow===3.2.0
|
||||
traceback2===1.4.0
|
||||
semantic-version===2.6.0
|
||||
virtualbmc===1.4.0
|
||||
deprecation===2.0.5
|
||||
SQLAlchemy===1.2.11
|
||||
pyroute2===0.5.2
|
||||
google-auth===1.5.1
|
||||
kazoo===2.5.0
|
||||
XStatic-roboto-fontface===0.5.0.0
|
||||
pyudev===0.21.0
|
||||
eventlet===0.24.1
|
||||
openstack-doc-tools===1.8.0
|
||||
frozendict===1.2
|
||||
oslo.messaging===8.1.0
|
||||
jira===2.0.0
|
||||
extras===1.0.0
|
||||
PyJWT===1.6.4
|
||||
zVMCloudConnector===1.2.4
|
||||
paramiko===2.4.1
|
||||
reno===2.11.0
|
||||
unicodecsv===0.14.1;python_version=='2.7'
|
||||
imagesize===1.1.0
|
||||
pydot===1.2.4
|
||||
pathlib===1.0.1;python_version=='2.7'
|
||||
urllib3===1.23
|
||||
graphviz===0.9
|
||||
PyKMIP===0.8.0
|
||||
whereto===0.4.0
|
||||
python-subunit===1.3.0
|
||||
tornado===4.5.3
|
||||
pycparser===2.18
|
||||
mock===2.0.0
|
||||
PyYAML===3.13
|
||||
beautifulsoup4===4.6.3
|
||||
os-net-config===9.2.0
|
||||
ovs===2.9.2
|
||||
cryptography===2.3.1
|
||||
adal===1.1.0
|
||||
backports.ssl-match-hostname===3.5.0.1;python_version=='2.7'
|
||||
openstack-release-test===1.1.0
|
||||
pylxd===2.2.7
|
||||
ruamel.ordereddict===0.4.13;python_version=='2.7'
|
||||
pycryptodomex===3.6.6
|
||||
anyjson===0.3.3
|
||||
requests-mock===1.5.2
|
||||
os-apply-config===9.1.0
|
||||
oslosphinx===4.18.0
|
||||
mox3===0.26.0
|
||||
gunicorn===19.9.0
|
||||
textfsm===0.4.1
|
||||
unittest2===1.1.0
|
||||
django-compressor===2.2
|
||||
libvirt-python===4.6.0
|
||||
python-zunclient===2.1.0
|
||||
asyncio===3.4.3;python_version=='3.4'
|
||||
asyncio===3.4.3;python_version=='3.5'
|
||||
asyncio===3.4.3;python_version=='3.6'
|
||||
tzlocal===1.5.1
|
||||
python-novaclient===11.0.0
|
||||
bcrypt===3.1.4
|
||||
fixtures-git===0.1.0
|
||||
os-client-config===1.31.2
|
||||
XStatic-Angular-Gettext===2.3.8.0
|
||||
XStatic-Hogan===2.0.0.2
|
||||
XStatic-objectpath===1.2.1.0
|
||||
python-manilaclient===1.24.1
|
||||
requests===2.19.1
|
||||
snowballstemmer===1.2.1
|
||||
Jinja2===2.10
|
||||
XStatic-Bootstrap-SCSS===3.3.7.1
|
||||
pyzabbix===0.7.4
|
||||
ptyprocess===0.6.0
|
||||
threadloop===1.0.2
|
||||
amqp===2.3.2
|
||||
ruamel.yaml===0.15.66
|
||||
websockify===0.8.0
|
||||
XStatic-JQuery.quicksearch===2.0.3.1
|
||||
mpmath===1.0.0
|
||||
django-debreach===1.5.2
|
||||
sphinx-feature-classification===0.3.0
|
||||
XStatic-JQuery-Migrate===1.2.1.1
|
||||
appdirs===1.4.3
|
||||
tinyrpc===0.9.3
|
||||
google-auth-httplib2===0.0.3
|
||||
Flask-SQLAlchemy===2.3.2
|
||||
daiquiri===1.5.0
|
||||
influxdb===5.1.0
|
||||
funcparserlib===0.3.6
|
||||
passlib===1.7.1
|
||||
dib-utils===0.0.11
|
||||
cliff===2.13.0
|
||||
os-brick===2.5.3
|
||||
ansible-runner===1.1.1
|
||||
trollius===2.2;python_version=='2.7'
|
||||
scp===0.11.0
|
||||
python-zaqarclient===1.10.0
|
||||
funcsigs===1.0.2;python_version=='2.7'
|
||||
zhmcclient===0.19.0
|
||||
lockfile===0.12.2
|
||||
dnspython3===1.15.0;python_version=='3.4'
|
||||
dnspython3===1.15.0;python_version=='3.5'
|
||||
dnspython3===1.15.0;python_version=='3.6'
|
||||
ldappool===2.3.0
|
||||
termcolor===1.1.0
|
||||
hiredis===0.2.0
|
||||
google-api-python-client===1.7.4
|
||||
castellan===0.19.0
|
||||
oslo.versionedobjects===1.33.3
|
||||
webcolors===1.8.1
|
||||
aodhclient===1.1.1
|
||||
autobahn===18.9.2
|
||||
SQLAlchemy-Utils===0.33.4
|
||||
pluggy===0.7.1
|
||||
coverage===4.5.1
|
||||
freezegun===0.3.10
|
||||
python-pytun===2.2.1
|
||||
pyperclip===1.6.4
|
||||
cassandra-driver===3.15.1
|
||||
mox===0.5.3
|
||||
XStatic-Angular-Schema-Form===0.8.13.0
|
||||
gabbi===1.44.0
|
||||
nwdiag===1.0.4
|
||||
XStatic-bootswatch===3.3.7.0
|
||||
XStatic-JS-Yaml===3.8.1.0
|
||||
XStatic-term.js===0.0.7.0
|
||||
oslo.log===3.39.0
|
||||
nodeenv===1.3.2
|
||||
pylev===1.3.0
|
||||
python-searchlightclient===1.3.0
|
||||
oslo.middleware===3.36.0
|
||||
XStatic-mdi===1.4.57.0
|
||||
django-pyscss===2.0.2
|
||||
uritemplate===3.0.0
|
||||
django-babel===0.6.2
|
||||
docutils===0.14
|
||||
notifier===1.0.3
|
||||
ujson===1.35
|
||||
selenium===3.14.0
|
||||
python-glareclient===0.5.3
|
||||
mypy===0.620;python_version=='3.4'
|
||||
mypy===0.620;python_version=='3.5'
|
||||
mypy===0.620;python_version=='3.6'
|
||||
mistral-lib===1.0.0
|
||||
dogtag-pki===10.3.5.1
|
||||
XStatic-Angular-UUID===0.0.4.0
|
||||
sphinxcontrib-seqdiag===0.8.5
|
||||
os-win===4.0.1
|
||||
dictdiffer===0.7.1
|
||||
retrying===1.3.3
|
||||
shade===1.29.0
|
||||
pathlib2===2.3.2
|
||||
pydotplus===2.0.2
|
||||
flask-oslolog===0.1
|
||||
jeepney===0.3.1;python_version=='3.4'
|
||||
jeepney===0.3.1;python_version=='3.5'
|
||||
jeepney===0.3.1;python_version=='3.6'
|
||||
stestr===2.1.1
|
||||
singledispatch===3.4.0.3;python_version=='2.7'
|
||||
oslo.serialization===2.27.0
|
||||
warlock===1.3.0
|
||||
exabgp===4.0.8
|
||||
sphinxcontrib-httpdomain===1.7.0
|
||||
metalsmith===0.7.0
|
||||
thriftpy===0.3.9;python_version=='2.7'
|
||||
text-unidecode===1.2
|
||||
murano-pkg-check===0.3.0
|
||||
oslo.vmware===2.31.0
|
||||
sqlalchemy-migrate===0.11.0
|
||||
python-monascaclient===1.12.1
|
||||
ldap3===2.5.1
|
||||
requests-ntlm===1.1.0
|
||||
python-string-utils===0.6.0
|
||||
automaton===1.15.0
|
||||
os-service-types===1.3.0
|
||||
keyring===15.1.0
|
||||
testscenarios===0.5.0
|
||||
sphinxcontrib-pecanwsme===0.9.0
|
||||
sadisplay===0.4.9
|
||||
enum34===1.1.6
|
||||
packaging===17.1
|
||||
flask-keystone===0.2
|
||||
nose-exclude===0.5.0
|
||||
psutil===5.4.7
|
||||
py===1.6.0
|
||||
txaio===18.8.1
|
||||
python-qinlingclient===2.0.0
|
||||
elasticsearch===2.4.1
|
||||
django-nose===1.4.5
|
||||
XStatic-JQuery.TableSorter===2.14.5.1
|
||||
pifpaf===2.1.1
|
||||
pysmi===0.3.1
|
||||
blockdiag===1.5.4
|
||||
testtools===2.3.0
|
||||
Parsley===1.3
|
||||
XStatic-tv4===1.2.7.0
|
||||
XStatic-JSEncrypt===2.3.1.1
|
||||
python-cinderclient===4.0.1
|
||||
keystonemiddleware===5.2.0
|
||||
django-formtools===2.1
|
||||
python-ceilometerclient===2.9.0
|
||||
XStatic-Spin===1.2.5.2
|
||||
openshift===0.7.1
|
||||
tap-as-a-service===3.0.0
|
||||
os-traits===0.9.0
|
||||
SecretStorage===2.3.1;python_version=='2.7'
|
||||
SecretStorage===3.1.0;python_version=='3.4'
|
||||
SecretStorage===3.1.0;python_version=='3.5'
|
||||
SecretStorage===3.1.0;python_version=='3.6'
|
||||
opentracing===1.3.0
|
||||
XStatic-Rickshaw===1.5.0.0
|
||||
iso8601===0.1.12
|
||||
tooz===1.62.0
|
||||
linecache2===1.0.0
|
||||
oauth2client===4.1.3
|
||||
idna===2.7
|
||||
python-karborclient===1.1.0
|
||||
weakrefmethod===1.0.3;python_version=='2.7'
|
||||
PuLP===1.6.8
|
||||
crc16===0.1.1
|
||||
protobuf===3.6.1
|
||||
os-dpm===1.1.0
|
||||
sushy===1.6.0
|
||||
python-neutronclient===6.10.0
|
||||
pika===0.12.0
|
||||
oslo.cache===1.30.1
|
||||
WebTest===2.0.30
|
||||
openstack.nose-plugin===0.11
|
||||
os-collect-config===9.2.0
|
||||
python-qpid-proton===0.23.0
|
||||
python-octaviaclient===1.6.0
|
||||
pysaml2===4.6.2
|
||||
requests-oauthlib===1.0.0
|
||||
oslo.reports===1.28.0
|
||||
ceilometermiddleware===1.3.0
|
||||
python-nss===1.0.1
|
||||
testrepository===0.0.20
|
||||
sympy===1.3
|
||||
sphinxmark===0.1.19
|
||||
PyNaCl===1.2.1
|
||||
osc-lib===1.11.1
|
||||
python-consul===1.1.0
|
||||
Faker===0.9.1
|
||||
more-itertools===4.3.0
|
||||
seqdiag===0.9.6
|
||||
numpy===1.15.1
|
||||
msgpack===0.5.6
|
||||
Sphinx===1.8.0
|
||||
oslo.config===6.4.0
|
||||
tempest===19.0.0
|
||||
django-floppyforms===1.7.0
|
||||
openstackdocstheme===1.23.2
|
||||
osc-placement===1.3.0
|
||||
zake===0.2.2
|
||||
python-rsdclient===0.1.3
|
||||
python-magic===0.4.15
|
||||
python-solumclient===2.7.1
|
||||
PyMySQL===0.9.2
|
||||
kubernetes===7.0.0
|
||||
httplib2===0.11.3
|
||||
bottle===0.12.13
|
||||
betamax===0.8.1
|
||||
construct===2.8.22
|
||||
pyparsing===2.2.0
|
||||
dogpile.cache===0.6.7
|
||||
python-barbicanclient===4.7.0
|
||||
tricircleclient===0.4.0
|
||||
WSME===0.9.3
|
||||
proboscis===1.2.6.0
|
||||
fortiosclient===0.0.3
|
||||
stevedore===1.29.0
|
||||
botocore===1.12.4
|
||||
xmltodict===0.11.0
|
||||
pyasn1===0.4.4
|
||||
oslo.rootwrap===5.14.1
|
||||
Django===1.11.15;python_version=='2.7'
|
||||
Django===2.0.8;python_version=='3.4'
|
||||
Django===2.0.8;python_version=='3.5'
|
||||
Django===2.0.8;python_version=='3.6'
|
||||
pexpect===4.6.0
|
||||
cmd2===0.8.9;python_version=='2.7'
|
||||
cmd2===0.9.4;python_version=='3.4'
|
||||
cmd2===0.9.4;python_version=='3.5'
|
||||
cmd2===0.9.4;python_version=='3.6'
|
||||
redis===2.10.6
|
||||
jmespath===0.9.3
|
||||
click===6.7
|
||||
atomicwrites===1.2.1
|
||||
docker-pycreds===0.3.0
|
||||
XStatic-smart-table===1.4.13.2
|
||||
kuryr-lib===0.8.0
|
||||
scrypt===0.8.6
|
||||
jsonpatch===1.23
|
||||
python-daemon===2.2.0
|
||||
typed-ast===1.1.0;python_version=='3.4'
|
||||
typed-ast===1.1.0;python_version=='3.5'
|
||||
typed-ast===1.1.0;python_version=='3.6'
|
||||
os-testr===1.0.0
|
||||
cotyledon===1.7.1
|
||||
stomp.py===4.1.21
|
||||
xattr===0.9.6
|
||||
systemd-python===234
|
||||
python-memcached===1.59
|
||||
openstacksdk===0.17.2
|
||||
six===1.11.0
|
||||
dulwich===0.19.6
|
||||
pykafka===2.7.0
|
||||
kombu===4.2.1
|
||||
distro===1.3.0
|
||||
betamax-matchers===0.4.0
|
||||
yaql===1.1.3
|
||||
requestsexceptions===1.4.0
|
||||
testresources===2.0.1
|
||||
falcon===1.4.1
|
||||
subprocess32===3.5.2;python_version=='2.7'
|
||||
etcd3gw===0.2.4
|
||||
Flask-RESTful===0.3.6
|
||||
GitPython===2.1.11
|
||||
python-ironicclient===2.5.0
|
||||
XStatic===1.0.1
|
||||
XStatic-Angular-FileUpload===12.0.4.0
|
||||
python-openstackclient===3.16.1
|
||||
pyzmq===17.1.2
|
||||
oslo.db===4.40.0
|
||||
simplegeneric===0.8.1
|
||||
python-pcre===0.7
|
||||
abclient===0.2.3
|
||||
pymemcache===2.0.0
|
||||
wrapt===1.10.11
|
||||
oslo.privsep===1.29.0
|
||||
sphinxcontrib-apidoc===0.2.1
|
||||
oslo.policy===1.38.1
|
||||
python-muranoclient===1.1.1
|
||||
pyeclib===1.5.0
|
||||
wsgi-intercept===1.8.0
|
||||
ndg-httpsclient===0.5.1;python_version=='2.7'
|
||||
repoze.lru===0.7
|
||||
rfc3986===1.1.0
|
||||
tenacity===5.0.2
|
||||
python-designateclient===2.10.0
|
||||
future===0.16.0
|
||||
Paste===2.0.3
|
||||
jaeger-client===3.11.0
|
||||
XStatic-Json2yaml===0.1.1.0
|
||||
boto===2.49.0
|
||||
functools32===3.2.3.post2;python_version=='2.7'
|
||||
os-vif===1.11.1
|
||||
python-masakariclient===5.2.0
|
||||
Werkzeug===0.14.1
|
||||
pyasn1-modules===0.2.2
|
||||
entrypoints===0.2.3
|
||||
APScheduler===3.5.3
|
||||
monotonic===1.5
|
||||
python-smaugclient===0.0.8
|
||||
python-troveclient===2.16.0
|
||||
etcd3===0.8.1
|
||||
XStatic-Bootstrap-Datepicker===1.3.1.0
|
||||
CouchDB===1.2
|
||||
netifaces===0.10.7
|
||||
cachetools===2.1.0
|
||||
ws4py===0.5.1
|
||||
backports-abc===0.5;python_version=='2.7'
|
||||
keystoneauth1===3.11.0
|
||||
statsd===3.3.0
|
||||
XenAPI===1.2
|
||||
python-keystoneclient===3.17.0
|
||||
ceilometer===11.0.0
|
||||
demjson===2.2.4
|
||||
diskimage-builder===2.17.0
|
||||
heat-translator===1.1.0
|
||||
python-magnumclient===2.10.0
|
||||
docker===3.5.0
|
||||
qpid-python===1.36.0.post1;python_version=='2.7'
|
||||
contextlib2===0.5.5
|
||||
XStatic-Angular-lrdragndrop===1.0.2.2
|
||||
python-congressclient===1.11.0
|
||||
ovsdbapp===0.12.1
|
||||
aniso8601===3.0.2
|
||||
rjsmin===1.0.12
|
||||
icalendar===4.0.2
|
||||
configparser===3.5.0;python_version=='2.7'
|
||||
decorator===4.3.0
|
||||
cffi===1.11.5
|
||||
futurist===1.7.0
|
||||
jsonschema===2.6.0
|
||||
python-blazarclient===2.0.1
|
||||
alembic===1.0.0
|
||||
glance-store===0.26.1
|
||||
sphinxcontrib-programoutput===0.11
|
||||
sphinx-testing===0.7.2
|
||||
dnspython===1.15.0
|
||||
oauthlib===2.1.0
|
||||
Babel===2.6.0
|
||||
logutils===0.3.5
|
||||
scandir===1.9.0;python_version=='2.7'
|
||||
sphinxcontrib-fulltoc===1.2.0
|
||||
smmap2===2.0.4
|
||||
greenlet===0.4.15
|
||||
XStatic-Angular-Vis===4.16.0.0
|
||||
confluent-kafka===0.11.5
|
||||
xvfbwrapper===0.2.9
|
||||
futures===3.2.0;python_version=='2.7'
|
||||
tosca-parser===1.1.0
|
||||
Flask===1.0.2
|
||||
happybase===1.1.0;python_version=='2.7'
|
||||
marathon===0.10.0
|
||||
fasteners===0.14.1
|
||||
sortedcontainers===2.0.5
|
||||
python-tackerclient===0.14.0
|
||||
python-heatclient===1.16.1
|
||||
kafka-python===1.4.3
|
||||
oslo.utils===3.37.0
|
||||
python-editor===1.0.3
|
||||
gitdb2===2.0.4
|
||||
requests-kerberos===0.12.0
|
||||
itsdangerous===0.24
|
||||
XStatic-jquery-ui===1.12.0.1
|
||||
monasca-statsd===1.10.1
|
||||
python-dateutil===2.7.3
|
||||
virtualenv===16.0.0
|
||||
colorama===0.3.9
|
||||
ironic-lib===2.14.0
|
||||
pytz===2018.5
|
||||
XStatic-D3===3.5.17.0
|
||||
actdiag===0.5.4
|
||||
sysv-ipc===1.0.0
|
||||
scikit-learn===0.19.2
|
Loading…
Reference in New Issue
Block a user