Retire ec2-api: remove repo content
ec2-api project is retiring - https://review.opendev.org/c/openstack/governance/+/919394/1 this commit remove the content of this project repo Depends-On: https://review.opendev.org/c/openstack/project-config/+/919396/1 Change-Id: I038271038b8c64a5a6a4adda2171ee5e44663e44
This commit is contained in:
parent
1036f53ae8
commit
31495609a8
|
@ -1,59 +0,0 @@
|
|||
*.py[cod]
|
||||
|
||||
# C extensions
|
||||
*.so
|
||||
|
||||
# Packages
|
||||
*.egg*
|
||||
*.egg-info
|
||||
dist
|
||||
build
|
||||
eggs
|
||||
parts
|
||||
bin
|
||||
var
|
||||
sdist
|
||||
develop-eggs
|
||||
.installed.cfg
|
||||
lib
|
||||
lib64
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
|
||||
# Unit test / coverage reports
|
||||
cover/
|
||||
.coverage*
|
||||
!.coveragerc
|
||||
.tox
|
||||
nosetests.xml
|
||||
.testrepository
|
||||
.stestr
|
||||
.venv
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
|
||||
# Mr Developer
|
||||
.mr.developer.cfg
|
||||
.project
|
||||
.pydevproject
|
||||
|
||||
# Complexity
|
||||
output/*.html
|
||||
output/*/index.html
|
||||
|
||||
# Sphinx
|
||||
doc/build
|
||||
|
||||
# pbr generates these
|
||||
AUTHORS
|
||||
ChangeLog
|
||||
|
||||
# Editors
|
||||
*~
|
||||
.*.swp
|
||||
.*sw?
|
||||
|
||||
# Files created by releasenotes build
|
||||
releasenotes/build
|
70
.zuul.yaml
70
.zuul.yaml
|
@ -1,70 +0,0 @@
|
|||
- project:
|
||||
queue: ec2-api
|
||||
templates:
|
||||
- openstack-python3-zed-jobs
|
||||
- check-requirements
|
||||
check:
|
||||
jobs:
|
||||
- ec2api-tempest-plugin-functional
|
||||
- ec2api-tempest-plugin-functional-2023-1
|
||||
- ec2api-tempest-plugin-functional-zed
|
||||
- ec2api-tempest-plugin-functional-yoga
|
||||
- ec2api-tempest-plugin-functional-xena
|
||||
gate:
|
||||
jobs:
|
||||
- ec2api-tempest-plugin-functional
|
||||
experimental:
|
||||
jobs:
|
||||
- ec2api-tempest-plugin-functional-full
|
||||
|
||||
- job:
|
||||
name: ec2api-tempest-plugin-functional
|
||||
parent: devstack-tempest
|
||||
timeout: 7800
|
||||
required-projects:
|
||||
- opendev.org/openstack/ec2-api
|
||||
- opendev.org/openstack/ec2api-tempest-plugin
|
||||
- opendev.org/openstack/neutron
|
||||
- opendev.org/openstack/neutron-vpnaas
|
||||
- opendev.org/openstack/neutron-tempest-plugin
|
||||
vars:
|
||||
devstack_localrc:
|
||||
KEYSTONE_ADMIN_ENDPOINT: true
|
||||
devstack_services:
|
||||
tls-proxy: false
|
||||
tox_envlist: all
|
||||
tempest_test_regex: ec2api_tempest_plugin
|
||||
tempest_concurrency: 2
|
||||
devstack_plugins:
|
||||
ec2-api: https://opendev.org/openstack/ec2-api
|
||||
neutron-tempest-plugin: https://opendev.org/openstack/neutron-tempest-plugin
|
||||
tempest_plugins:
|
||||
- ec2api-tempest-plugin
|
||||
|
||||
- job:
|
||||
name: ec2api-tempest-plugin-functional-2023-1
|
||||
parent: ec2api-tempest-plugin-functional
|
||||
nodeset: openstack-single-node-jammy
|
||||
override-checkout: stable/2023.1
|
||||
- job:
|
||||
name: ec2api-tempest-plugin-functional-zed
|
||||
parent: ec2api-tempest-plugin-functional
|
||||
nodeset: openstack-single-node-focal
|
||||
override-checkout: stable/zed
|
||||
- job:
|
||||
name: ec2api-tempest-plugin-functional-yoga
|
||||
parent: ec2api-tempest-plugin-functional
|
||||
nodeset: openstack-single-node-focal
|
||||
override-checkout: stable/yoga
|
||||
- job:
|
||||
name: ec2api-tempest-plugin-functional-xena
|
||||
parent: ec2api-tempest-plugin-functional
|
||||
nodeset: openstack-single-node-focal
|
||||
override-checkout: stable/xena
|
||||
|
||||
- job:
|
||||
name: ec2api-tempest-plugin-functional-full
|
||||
parent: ec2api-tempest-plugin-functional
|
||||
vars:
|
||||
devstack_localrc:
|
||||
RUN_LONG_TESTS: 1
|
|
@ -1,19 +0,0 @@
|
|||
The source repository for this project can be found at:
|
||||
|
||||
https://opendev.org/openstack/ec2api-tempest-plugin
|
||||
|
||||
Pull requests submitted through GitHub are not monitored.
|
||||
|
||||
To start contributing to OpenStack, follow the steps in the contribution guide
|
||||
to set up and use Gerrit:
|
||||
|
||||
https://docs.openstack.org/contributors/code-and-documentation/quick-start.html
|
||||
|
||||
Bugs should be filed on Launchpad:
|
||||
|
||||
https://bugs.launchpad.net/ec2-api
|
||||
|
||||
For more specific information about contributing to this repository, see the
|
||||
ec2api-tempest-plugin contributor guide:
|
||||
|
||||
https://docs.openstack.org/ec2-api/latest/contributor/contributing.html
|
|
@ -1,4 +0,0 @@
|
|||
openstack Style Commandments
|
||||
===============================================
|
||||
|
||||
Read the OpenStack Style Commandments https://docs.openstack.org/hacking/latest/
|
176
LICENSE
176
LICENSE
|
@ -1,176 +0,0 @@
|
|||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
25
README.rst
25
README.rst
|
@ -1,19 +1,10 @@
|
|||
=====================
|
||||
ec2api tempest plugin
|
||||
=====================
|
||||
This project is no longer maintained.
|
||||
|
||||
Tempest plugin ec2api_tempest_plugin
|
||||
The contents of this repository are still available in the Git
|
||||
source code management system. To see the contents of this
|
||||
repository before it reached its end of life, please check out the
|
||||
previous commit with "git checkout HEAD^1".
|
||||
|
||||
Please fill here a long description which must be at least 3 lines wrapped on
|
||||
80 cols, so that distribution package maintainers can use it in their packages.
|
||||
Note that this is a hard requirement.
|
||||
|
||||
* Free software: Apache license
|
||||
* Documentation: https://docs.openstack.org/ec2-api/latest
|
||||
* Source: https://opendev.org/openstack/ec2api-tempest-plugin
|
||||
* Bugs: https://bugs.launchpad.net/ec2-api
|
||||
|
||||
Features
|
||||
--------
|
||||
|
||||
* TODO
|
||||
For any further questions, please email
|
||||
openstack-discuss@lists.openstack.org or join #openstack-dev on
|
||||
OFTC.
|
||||
|
|
|
@ -1,437 +0,0 @@
|
|||
# Copyright 2014 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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 time
|
||||
|
||||
import botocore.exceptions
|
||||
from oslo_log import log
|
||||
from tempest.lib import decorators
|
||||
import testtools
|
||||
|
||||
from ec2api_tempest_plugin import base
|
||||
from ec2api_tempest_plugin import config
|
||||
|
||||
CONF = config.CONF
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
|
||||
class AddressTest(base.EC2TestCase):
|
||||
|
||||
@base.skip_without_vpc()
|
||||
@decorators.idempotent_id('218a4b6b-c3a9-44b0-8148-4bd0bc36bd7d')
|
||||
def test_create_delete_vpc_address(self):
|
||||
kwargs = {
|
||||
'Domain': 'vpc',
|
||||
}
|
||||
data = self.client.allocate_address(*[], **kwargs)
|
||||
id = data['AllocationId']
|
||||
res_clean = self.addResourceCleanUp(self.client.release_address,
|
||||
AllocationId=id)
|
||||
self.assertEqual('vpc', data['Domain'])
|
||||
|
||||
data = self.client.release_address(AllocationId=id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
|
||||
@base.skip_without_ec2()
|
||||
@decorators.idempotent_id('285b8b4e-5aef-4e7f-be9e-37e6475be21b')
|
||||
def test_create_delete_standard_address(self):
|
||||
data = self.client.allocate_address()
|
||||
ip = data['PublicIp']
|
||||
res_clean = self.addResourceCleanUp(self.client.release_address,
|
||||
PublicIp=ip)
|
||||
|
||||
data = self.client.release_address(PublicIp=ip)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
|
||||
@base.skip_without_vpc()
|
||||
@decorators.idempotent_id('5be3ad8d-b071-472b-b92a-7199c82334a2')
|
||||
def test_invalid_delete_vpc_address(self):
|
||||
kwargs = {
|
||||
'Domain': 'vpc',
|
||||
}
|
||||
data = self.client.allocate_address(*[], **kwargs)
|
||||
ip = data['PublicIp']
|
||||
id = data['AllocationId']
|
||||
res_clean = self.addResourceCleanUp(self.client.release_address,
|
||||
AllocationId=id)
|
||||
self.assertEqual('vpc', data['Domain'])
|
||||
|
||||
self.assertRaises('InvalidParameterCombination',
|
||||
self.client.release_address,
|
||||
PublicIp=ip, AllocationId=id)
|
||||
|
||||
self.assertRaises('InvalidParameterValue',
|
||||
self.client.release_address,
|
||||
PublicIp=ip)
|
||||
|
||||
data = self.client.release_address(AllocationId=id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
|
||||
if CONF.aws.run_incompatible_tests:
|
||||
self.assertRaises('AuthFailure',
|
||||
self.client.release_address,
|
||||
PublicIp=ip)
|
||||
|
||||
self.assertRaises('InvalidAllocationID.NotFound',
|
||||
self.client.release_address,
|
||||
AllocationId=id)
|
||||
|
||||
kwargs = {
|
||||
"AllocationId": 'eipalloc-00000000',
|
||||
}
|
||||
self.assertRaises('InvalidAllocationID.NotFound',
|
||||
self.client.release_address,
|
||||
**kwargs)
|
||||
|
||||
if CONF.aws.run_incompatible_tests:
|
||||
self.assertRaises('InvalidParameterValue',
|
||||
self.client.release_address,
|
||||
PublicIp='ip')
|
||||
|
||||
@decorators.idempotent_id('e8171637-9ccd-471a-97da-c78a36ba3c4b')
|
||||
def test_invalid_create_address(self):
|
||||
kwargs = {
|
||||
'Domain': 'invalid',
|
||||
}
|
||||
try:
|
||||
data = self.client.allocate_address(*[], **kwargs)
|
||||
allocation_id = data.get('AllocationId')
|
||||
if allocation_id:
|
||||
self.client.release_address(AllocationId=allocation_id)
|
||||
else:
|
||||
public_ip = data.get('PublicIp')
|
||||
self.client.release_address(PublicIp=public_ip)
|
||||
except botocore.exceptions.ClientError as e:
|
||||
self.assertEqual('InvalidParameterValue',
|
||||
e.response['Error']['Code'])
|
||||
|
||||
@base.skip_without_vpc()
|
||||
@decorators.idempotent_id('b0d0b498-1fe2-479e-995c-80ace2f339a7')
|
||||
def test_describe_vpc_addresses(self):
|
||||
kwargs = {
|
||||
'Domain': 'vpc',
|
||||
}
|
||||
data = self.client.allocate_address(*[], **kwargs)
|
||||
ip = data['PublicIp']
|
||||
id = data['AllocationId']
|
||||
res_clean = self.addResourceCleanUp(self.client.release_address,
|
||||
AllocationId=id)
|
||||
|
||||
data = self.client.describe_addresses(*[], **{})
|
||||
for address in data['Addresses']:
|
||||
if address.get('AllocationId') == id:
|
||||
self.assertEqual('vpc', address['Domain'])
|
||||
self.assertEqual(ip, address['PublicIp'])
|
||||
break
|
||||
else:
|
||||
self.fail('Created address could not be found')
|
||||
|
||||
kwargs = {
|
||||
'PublicIps': [ip],
|
||||
}
|
||||
data = self.client.describe_addresses(*[], **kwargs)
|
||||
self.assertEqual(1, len(data['Addresses']))
|
||||
self.assertEqual(id, data['Addresses'][0]['AllocationId'])
|
||||
|
||||
kwargs = {
|
||||
'AllocationIds': [id],
|
||||
}
|
||||
data = self.client.describe_addresses(*[], **kwargs)
|
||||
self.assertEqual(1, len(data['Addresses']))
|
||||
self.assertEqual(ip, data['Addresses'][0]['PublicIp'])
|
||||
|
||||
kwargs = {
|
||||
'PublicIps': ['invalidIp'],
|
||||
}
|
||||
self.assertRaises('InvalidParameterValue',
|
||||
self.client.describe_addresses,
|
||||
**kwargs)
|
||||
|
||||
kwargs = {
|
||||
'AllocationIds': ['eipalloc-00000000'],
|
||||
}
|
||||
self.assertRaises('InvalidAllocationID.NotFound',
|
||||
self.client.describe_addresses,
|
||||
**kwargs)
|
||||
|
||||
kwargs = {
|
||||
'Domain': 'vpc',
|
||||
}
|
||||
data = self.client.allocate_address(*[], **kwargs)
|
||||
id2 = data['AllocationId']
|
||||
res_clean2 = self.addResourceCleanUp(self.client.release_address,
|
||||
AllocationId=id2)
|
||||
|
||||
kwargs = {
|
||||
'PublicIps': [ip],
|
||||
'AllocationIds': [id2],
|
||||
}
|
||||
data = self.client.describe_addresses(*[], **kwargs)
|
||||
self.assertEqual(2, len(data['Addresses']))
|
||||
|
||||
# NOTE(andrey-mp): wait abit before releasing
|
||||
time.sleep(3)
|
||||
|
||||
self.client.release_address(AllocationId=id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
|
||||
self.client.release_address(AllocationId=id2)
|
||||
self.cancelResourceCleanUp(res_clean2)
|
||||
|
||||
@base.skip_without_ec2()
|
||||
@decorators.idempotent_id('a5c09f47-3be3-4d46-b59d-25195d67e6d5')
|
||||
def test_describe_standard_addresses(self):
|
||||
data = self.client.allocate_address(*[], **{})
|
||||
ip = data['PublicIp']
|
||||
res_clean = self.addResourceCleanUp(self.client.release_address,
|
||||
PublicIp=ip)
|
||||
|
||||
data = self.client.describe_addresses(*[], **{})
|
||||
for address in data['Addresses']:
|
||||
if address['PublicIp'] == ip:
|
||||
self.assertEqual('standard', address['Domain'])
|
||||
break
|
||||
else:
|
||||
self.fail('Created address could not be found')
|
||||
|
||||
kwargs = {
|
||||
'PublicIps': [ip],
|
||||
}
|
||||
data = self.client.describe_addresses(*[], **kwargs)
|
||||
self.assertEqual(1, len(data['Addresses']))
|
||||
self.assertEqual(ip, data['Addresses'][0]['PublicIp'])
|
||||
|
||||
kwargs = {
|
||||
'PublicIps': ['invalidIp'],
|
||||
}
|
||||
self.assertRaises('InvalidParameterValue',
|
||||
self.client.describe_addresses,
|
||||
PublicIps=['invalidIp'])
|
||||
|
||||
# NOTE(andrey-mp): wait abit before releasing
|
||||
time.sleep(3)
|
||||
|
||||
self.client.release_address(PublicIp=ip)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
|
||||
@base.skip_without_vpc()
|
||||
@decorators.idempotent_id('6f154e48-f260-4d8d-b1d1-a1cf174f58fa')
|
||||
@testtools.skip("flaky test")
|
||||
# @testtools.skipUnless(CONF.aws.image_id, "image id is not defined")
|
||||
def test_associate_disassociate_vpc_addresses(self):
|
||||
aws_zone = CONF.aws.aws_zone
|
||||
|
||||
base_net = '10.3.0.0'
|
||||
data = self.client.create_vpc(CidrBlock=base_net + '/20')
|
||||
vpc_id = data['Vpc']['VpcId']
|
||||
clean_vpc = self.addResourceCleanUp(self.client.delete_vpc,
|
||||
VpcId=vpc_id)
|
||||
self.get_vpc_waiter().wait_available(vpc_id)
|
||||
|
||||
cidr = base_net + '/24'
|
||||
data = self.client.create_subnet(VpcId=vpc_id, CidrBlock=cidr,
|
||||
AvailabilityZone=aws_zone)
|
||||
subnet_id = data['Subnet']['SubnetId']
|
||||
clean_subnet = self.addResourceCleanUp(self.client.delete_subnet,
|
||||
SubnetId=subnet_id)
|
||||
|
||||
instance_id = self.run_instance(SubnetId=subnet_id)
|
||||
|
||||
data = self.client.allocate_address(Domain='vpc')
|
||||
alloc_id = data['AllocationId']
|
||||
clean_a = self.addResourceCleanUp(self.client.release_address,
|
||||
AllocationId=alloc_id)
|
||||
|
||||
self.assertRaises('Gateway.NotAttached',
|
||||
self.client.associate_address,
|
||||
InstanceId=instance_id, AllocationId=alloc_id)
|
||||
|
||||
# Create internet gateway and try to associate again
|
||||
data = self.client.create_internet_gateway()
|
||||
gw_id = data['InternetGateway']['InternetGatewayId']
|
||||
clean_ig = self.addResourceCleanUp(self.client.delete_internet_gateway,
|
||||
InternetGatewayId=gw_id)
|
||||
data = self.client.attach_internet_gateway(VpcId=vpc_id,
|
||||
InternetGatewayId=gw_id)
|
||||
clean_aig = self.addResourceCleanUp(
|
||||
self.client.detach_internet_gateway,
|
||||
VpcId=vpc_id,
|
||||
InternetGatewayId=gw_id)
|
||||
|
||||
self.prepare_route(vpc_id, gw_id)
|
||||
|
||||
data = self.client.associate_address(InstanceId=instance_id,
|
||||
AllocationId=alloc_id)
|
||||
assoc_id = data['AssociationId']
|
||||
clean_aa = self.addResourceCleanUp(self.client.disassociate_address,
|
||||
AssociationId=assoc_id)
|
||||
self.get_address_assoc_waiter().wait_available(
|
||||
{'AllocationId': alloc_id})
|
||||
|
||||
kwargs = {
|
||||
'AllocationIds': [alloc_id],
|
||||
}
|
||||
data = self.client.describe_addresses(*[], **kwargs)
|
||||
self.assertEqual(instance_id, data['Addresses'][0]['InstanceId'])
|
||||
|
||||
data = self.client.disassociate_address(AssociationId=assoc_id)
|
||||
self.cancelResourceCleanUp(clean_aa)
|
||||
self.get_address_assoc_waiter().wait_delete({'AllocationId': alloc_id})
|
||||
|
||||
# NOTE(andrey-mp): cleanup
|
||||
time.sleep(3)
|
||||
|
||||
self.client.detach_internet_gateway(VpcId=vpc_id,
|
||||
InternetGatewayId=gw_id)
|
||||
self.cancelResourceCleanUp(clean_aig)
|
||||
|
||||
self.client.delete_internet_gateway(InternetGatewayId=gw_id)
|
||||
self.cancelResourceCleanUp(clean_ig)
|
||||
|
||||
self.client.release_address(AllocationId=alloc_id)
|
||||
self.cancelResourceCleanUp(clean_a)
|
||||
|
||||
self.client.terminate_instances(InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_delete(instance_id)
|
||||
|
||||
self.client.delete_subnet(SubnetId=subnet_id)
|
||||
self.cancelResourceCleanUp(clean_subnet)
|
||||
self.get_subnet_waiter().wait_delete(subnet_id)
|
||||
|
||||
self.client.delete_vpc(VpcId=vpc_id)
|
||||
self.cancelResourceCleanUp(clean_vpc)
|
||||
self.get_vpc_waiter().wait_delete(vpc_id)
|
||||
|
||||
@decorators.idempotent_id('4aaf01d2-ade5-4e8b-b24a-ab22448b3236')
|
||||
@testtools.skipUnless(CONF.aws.image_id, "image id is not defined")
|
||||
# skip this test for nova network due to bug #1607350
|
||||
@base.skip_without_vpc()
|
||||
# this is a correct skip
|
||||
@base.skip_without_ec2()
|
||||
def test_associate_disassociate_standard_addresses(self):
|
||||
instance_id = self.run_instance()
|
||||
|
||||
data = self.client.allocate_address(*[], **{})
|
||||
ip = data['PublicIp']
|
||||
clean_a = self.addResourceCleanUp(self.client.release_address,
|
||||
PublicIp=ip)
|
||||
|
||||
data = self.client.associate_address(InstanceId=instance_id,
|
||||
PublicIp=ip)
|
||||
clean_aa = self.addResourceCleanUp(self.client.disassociate_address,
|
||||
PublicIp=ip)
|
||||
self.get_address_assoc_waiter().wait_available({'PublicIp': ip})
|
||||
|
||||
kwargs = {
|
||||
'PublicIps': [ip],
|
||||
}
|
||||
data = self.client.describe_addresses(*[], **kwargs)
|
||||
self.assertEqual(instance_id, data['Addresses'][0]['InstanceId'])
|
||||
|
||||
data = self.client.disassociate_address(PublicIp=ip)
|
||||
self.cancelResourceCleanUp(clean_aa)
|
||||
self.get_address_assoc_waiter().wait_delete({'PublicIp': ip})
|
||||
|
||||
time.sleep(3)
|
||||
|
||||
data = self.client.release_address(PublicIp=ip)
|
||||
self.cancelResourceCleanUp(clean_a)
|
||||
|
||||
data = self.client.terminate_instances(InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_delete(instance_id)
|
||||
|
||||
@base.skip_without_vpc()
|
||||
@decorators.idempotent_id('3c0ab7f5-ee9c-4966-8d43-e89f5520f245')
|
||||
def test_disassociate_not_associated_vpc_addresses(self):
|
||||
aws_zone = CONF.aws.aws_zone
|
||||
|
||||
base_net = '10.3.0.0'
|
||||
data = self.client.create_vpc(CidrBlock=base_net + '/20')
|
||||
vpc_id = data['Vpc']['VpcId']
|
||||
clean_vpc = self.addResourceCleanUp(self.client.delete_vpc,
|
||||
VpcId=vpc_id)
|
||||
self.get_vpc_waiter().wait_available(vpc_id)
|
||||
|
||||
cidr = base_net + '/24'
|
||||
data = self.client.create_subnet(VpcId=vpc_id, CidrBlock=cidr,
|
||||
AvailabilityZone=aws_zone)
|
||||
subnet_id = data['Subnet']['SubnetId']
|
||||
clean_subnet = self.addResourceCleanUp(self.client.delete_subnet,
|
||||
SubnetId=subnet_id)
|
||||
|
||||
data = self.client.allocate_address(Domain='vpc')
|
||||
alloc_id = data['AllocationId']
|
||||
ip = data['PublicIp']
|
||||
clean_a = self.addResourceCleanUp(self.client.release_address,
|
||||
AllocationId=alloc_id)
|
||||
|
||||
assoc_id = 'eipassoc-00000001'
|
||||
self.assertRaises('InvalidAssociationID.NotFound',
|
||||
self.client.disassociate_address,
|
||||
AssociationId=assoc_id)
|
||||
|
||||
self.assertRaises('InvalidParameterValue',
|
||||
self.client.disassociate_address,
|
||||
PublicIp=ip)
|
||||
|
||||
self.client.release_address(AllocationId=alloc_id)
|
||||
self.cancelResourceCleanUp(clean_a)
|
||||
|
||||
self.client.delete_subnet(SubnetId=subnet_id)
|
||||
self.cancelResourceCleanUp(clean_subnet)
|
||||
self.get_subnet_waiter().wait_delete(subnet_id)
|
||||
|
||||
self.client.delete_vpc(VpcId=vpc_id)
|
||||
self.cancelResourceCleanUp(clean_vpc)
|
||||
self.get_vpc_waiter().wait_delete(vpc_id)
|
||||
|
||||
@base.skip_without_ec2()
|
||||
@decorators.idempotent_id('a70babef-18ec-4340-a3a2-63388cfc3cb5')
|
||||
def test_disassociate_not_associated_standard_addresses(self):
|
||||
data = self.client.allocate_address(Domain='standard')
|
||||
ip = data['PublicIp']
|
||||
clean_a = self.addResourceCleanUp(self.client.release_address,
|
||||
PublicIp=ip)
|
||||
|
||||
data = self.client.disassociate_address(PublicIp=ip)
|
||||
|
||||
data = self.client.release_address(PublicIp=ip)
|
||||
self.cancelResourceCleanUp(clean_a)
|
||||
|
||||
@base.skip_without_vpc()
|
||||
@decorators.idempotent_id('91b971f5-2674-478e-84df-115fef506c5b')
|
||||
@testtools.skipUnless(CONF.aws.run_incompatible_tests,
|
||||
'preliminary address association is not supported')
|
||||
def test_preliminary_associate_address(self):
|
||||
# NOTE(ft): AWS can associate an address to a subnet IP if the subnet
|
||||
# has no internet access
|
||||
vpc_id, subnet_id = self.create_vpc_and_subnet('10.3.0.0/20')
|
||||
self.create_and_attach_internet_gateway(vpc_id)
|
||||
data = self.client.allocate_address(Domain='vpc')
|
||||
alloc_id = data['AllocationId']
|
||||
self.addResourceCleanUp(self.client.release_address,
|
||||
AllocationId=alloc_id)
|
||||
|
||||
data = self.client.create_network_interface(SubnetId=subnet_id)
|
||||
ni_id = data['NetworkInterface']['NetworkInterfaceId']
|
||||
self.addResourceCleanUp(self.client.delete_network_interface,
|
||||
NetworkInterfaceId=ni_id)
|
||||
self.get_network_interface_waiter().wait_available(ni_id)
|
||||
|
||||
data = self.client.associate_address(
|
||||
AllocationId=alloc_id, NetworkInterfaceId=ni_id)
|
||||
assoc_id = data['AssociationId']
|
||||
self.addResourceCleanUp(self.client.disassociate_address,
|
||||
AssociationId=assoc_id)
|
|
@ -1,57 +0,0 @@
|
|||
# Copyright 2014 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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 botocore.exceptions
|
||||
from tempest.lib import decorators
|
||||
|
||||
from ec2api_tempest_plugin import base
|
||||
from ec2api_tempest_plugin import config
|
||||
|
||||
CONF = config.CONF
|
||||
|
||||
|
||||
class CustomerGatewayTest(base.EC2TestCase):
|
||||
|
||||
CUSTOMER_GATEWAY_IP = '198.51.100.77'
|
||||
|
||||
@classmethod
|
||||
@base.safe_setup
|
||||
def setUpClass(cls):
|
||||
super(CustomerGatewayTest, cls).setUpClass()
|
||||
if not base.TesterStateHolder().get_vpc_enabled():
|
||||
raise cls.skipException('VPC is disabled')
|
||||
base.check_vpnaas_enabled()
|
||||
|
||||
@decorators.idempotent_id('54a40b66-1675-44b1-938d-0cad2eb6afe4')
|
||||
def test_create_delete_customer_gateway(self):
|
||||
data = self.client.create_customer_gateway(
|
||||
Type='ipsec.1', PublicIp=self.CUSTOMER_GATEWAY_IP, BgpAsn=65000)
|
||||
cgw_id = data['CustomerGateway']['CustomerGatewayId']
|
||||
cgw_clean = self.addResourceCleanUp(
|
||||
self.client.delete_customer_gateway, CustomerGatewayId=cgw_id)
|
||||
self.assertEqual(self.CUSTOMER_GATEWAY_IP,
|
||||
data['CustomerGateway']['IpAddress'])
|
||||
|
||||
self.client.delete_customer_gateway(CustomerGatewayId=cgw_id)
|
||||
self.cancelResourceCleanUp(cgw_clean)
|
||||
|
||||
try:
|
||||
data = self.client.describe_customer_gateways(
|
||||
CustomerGatewayIds=[cgw_id])
|
||||
self.assertEqual(1, len(data['CustomerGateways']))
|
||||
self.assertEqual('deleted', data['CustomerGateways'][0]['State'])
|
||||
except botocore.exceptions.ClientError as ex:
|
||||
self.assertEqual('InvalidCustomerGatewayID.NotFound',
|
||||
ex.response['Error']['Code'])
|
|
@ -1,182 +0,0 @@
|
|||
# Copyright 2014 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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 time
|
||||
|
||||
from oslo_log import log
|
||||
from tempest.lib import decorators
|
||||
|
||||
from ec2api_tempest_plugin import base
|
||||
from ec2api_tempest_plugin import config
|
||||
|
||||
CONF = config.CONF
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
|
||||
class DhcpOptionsTest(base.EC2TestCase):
|
||||
|
||||
@classmethod
|
||||
@base.safe_setup
|
||||
def setUpClass(cls):
|
||||
super(DhcpOptionsTest, cls).setUpClass()
|
||||
if not base.TesterStateHolder().get_vpc_enabled():
|
||||
raise cls.skipException('VPC is disabled')
|
||||
|
||||
@decorators.idempotent_id('2331fc49-50e0-4df3-8c45-bd6f61cc86bf')
|
||||
def test_create_delete_dhcp_options(self):
|
||||
kwargs = {
|
||||
'DhcpConfigurations': [
|
||||
{'Key': 'domain-name',
|
||||
'Values': ['my.com', 'it.com']},
|
||||
{'Key': 'domain-name-servers',
|
||||
'Values': ['8.8.8.8', '8.8.4.4']},
|
||||
{'Key': 'ntp-servers',
|
||||
'Values': ['1.2.3.4']},
|
||||
{'Key': 'netbios-name-servers',
|
||||
'Values': ['4.3.2.1']},
|
||||
{'Key': 'netbios-node-type',
|
||||
'Values': ['2']},
|
||||
],
|
||||
}
|
||||
data = self.client.create_dhcp_options(*[], **kwargs)
|
||||
options = data['DhcpOptions']
|
||||
id = options['DhcpOptionsId']
|
||||
res_clean = self.addResourceCleanUp(self.client.delete_dhcp_options,
|
||||
DhcpOptionsId=id)
|
||||
self.assertEqual(5, len(options['DhcpConfigurations']))
|
||||
for cfg in options['DhcpConfigurations']:
|
||||
self.assertEqual(2, len(cfg))
|
||||
if cfg['Key'] == 'domain-name':
|
||||
self.assertEqual(2, len(cfg['Values']))
|
||||
values = [i['Value'] for i in cfg['Values']]
|
||||
self.assertIn('my.com', values)
|
||||
self.assertIn('it.com', values)
|
||||
elif cfg['Key'] == 'domain-name-servers':
|
||||
self.assertEqual(2, len(cfg['Values']))
|
||||
values = [i['Value'] for i in cfg['Values']]
|
||||
self.assertIn('8.8.8.8', values)
|
||||
self.assertIn('8.8.4.4', values)
|
||||
elif cfg['Key'] == 'ntp-servers':
|
||||
self.assertEqual(1, len(cfg['Values']))
|
||||
self.assertEqual('1.2.3.4', cfg['Values'][0]['Value'])
|
||||
elif cfg['Key'] == 'netbios-name-servers':
|
||||
self.assertEqual(1, len(cfg['Values']))
|
||||
self.assertEqual('4.3.2.1', cfg['Values'][0]['Value'])
|
||||
elif cfg['Key'] == 'netbios-node-type':
|
||||
self.assertEqual(1, len(cfg['Values']))
|
||||
self.assertEqual('2', cfg['Values'][0]['Value'])
|
||||
else:
|
||||
self.fail('Unknown key name in result - %s' % cfg['Key'])
|
||||
|
||||
data = self.client.delete_dhcp_options(DhcpOptionsId=id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
|
||||
@decorators.idempotent_id('ff1d4f6e-97fc-4053-b98f-ff59e7e8d061')
|
||||
def test_invalid_create_delete(self):
|
||||
def _rollback(fn_data):
|
||||
self.client.delete_dhcp_options(
|
||||
DhcpOptionsId=fn_data['DhcpOptions']['DhcpOptionsId'])
|
||||
|
||||
kwargs = {
|
||||
'DhcpConfigurations': [
|
||||
],
|
||||
}
|
||||
self.assertRaises('MissingParameter',
|
||||
self.client.create_dhcp_options,
|
||||
**kwargs)
|
||||
|
||||
kwargs = {
|
||||
'DhcpConfigurations': [{'Key': 'aaa', 'Values': []}],
|
||||
}
|
||||
self.assertRaises('InvalidParameterValue',
|
||||
self.client.create_dhcp_options, rollback_fn=_rollback,
|
||||
**kwargs)
|
||||
|
||||
kwargs = {
|
||||
'DhcpConfigurations': [{'Key': 'domain-name', 'Values': []}],
|
||||
}
|
||||
self.assertRaises('InvalidParameterValue',
|
||||
self.client.create_dhcp_options, rollback_fn=_rollback,
|
||||
**kwargs)
|
||||
|
||||
@decorators.idempotent_id('1c3e8ff9-bb3b-40ba-889e-d2306a92f418')
|
||||
def test_describe_dhcp_options(self):
|
||||
kwargs = {
|
||||
'DhcpConfigurations': [
|
||||
{'Key': 'domain-name',
|
||||
'Values': ['my.com']},
|
||||
],
|
||||
}
|
||||
data = self.client.create_dhcp_options(*[], **kwargs)
|
||||
options = data['DhcpOptions']
|
||||
id = options['DhcpOptionsId']
|
||||
res_clean = self.addResourceCleanUp(self.client.delete_dhcp_options,
|
||||
DhcpOptionsId=id)
|
||||
|
||||
time.sleep(10)
|
||||
|
||||
kwargs = {
|
||||
'DhcpOptionsIds': [id],
|
||||
}
|
||||
data = self.client.describe_dhcp_options(*[], **kwargs)
|
||||
self.assertEqual(1, len(data['DhcpOptions']))
|
||||
options = data['DhcpOptions'][0]
|
||||
self.assertEqual(id, options['DhcpOptionsId'])
|
||||
self.assertEqual(1, len(options['DhcpConfigurations']))
|
||||
cfg = options['DhcpConfigurations'][0]
|
||||
self.assertEqual(2, len(cfg))
|
||||
self.assertEqual('domain-name', cfg['Key'])
|
||||
self.assertEqual(1, len(cfg['Values']))
|
||||
self.assertIn('my.com', cfg['Values'][0]['Value'])
|
||||
|
||||
data = self.client.delete_dhcp_options(DhcpOptionsId=id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
|
||||
@decorators.idempotent_id('1b4d678a-c2a2-4c73-9e62-789fe2f6b173')
|
||||
def test_associate_dhcp_options(self):
|
||||
kwargs = {
|
||||
'DhcpConfigurations': [
|
||||
{'Key': 'domain-name',
|
||||
'Values': ['my.com']},
|
||||
],
|
||||
}
|
||||
data = self.client.create_dhcp_options(*[], **kwargs)
|
||||
options = data['DhcpOptions']
|
||||
id = options['DhcpOptionsId']
|
||||
res_clean = self.addResourceCleanUp(self.client.delete_dhcp_options,
|
||||
DhcpOptionsId=id)
|
||||
|
||||
cidr = '10.0.0.0/24'
|
||||
data = self.client.create_vpc(CidrBlock=cidr)
|
||||
vpc_id = data['Vpc']['VpcId']
|
||||
dv_clean = self.addResourceCleanUp(self.client.delete_vpc,
|
||||
VpcId=vpc_id)
|
||||
|
||||
kwargs = {
|
||||
'DhcpOptionsId': id,
|
||||
'VpcId': vpc_id,
|
||||
}
|
||||
data = self.client.associate_dhcp_options(*[], **kwargs)
|
||||
|
||||
self.assertRaises('DependencyViolation',
|
||||
self.client.delete_dhcp_options,
|
||||
DhcpOptionsId=id)
|
||||
|
||||
data = self.client.delete_vpc(VpcId=vpc_id)
|
||||
self.cancelResourceCleanUp(dv_clean)
|
||||
self.get_vpc_waiter().wait_delete(vpc_id)
|
||||
|
||||
data = self.client.delete_dhcp_options(DhcpOptionsId=id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
|
@ -1,360 +0,0 @@
|
|||
# Copyright 2014 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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.
|
||||
|
||||
from tempest.lib.common.utils import data_utils
|
||||
from tempest.lib import decorators
|
||||
import testtools
|
||||
|
||||
from ec2api_tempest_plugin import base
|
||||
from ec2api_tempest_plugin import config
|
||||
|
||||
CONF = config.CONF
|
||||
|
||||
|
||||
class ImageTest(base.EC2TestCase):
|
||||
|
||||
@decorators.idempotent_id('19a2fda6-0b78-4544-a6c5-ac16f39811c8')
|
||||
@testtools.skipUnless(CONF.aws.ebs_image_id, "EBS image id is not defined")
|
||||
def test_check_ebs_image_type(self):
|
||||
image_id = CONF.aws.ebs_image_id
|
||||
data = self.client.describe_images(ImageIds=[image_id])
|
||||
self.assertEqual(1, len(data['Images']))
|
||||
image = data['Images'][0]
|
||||
self.assertEqual("ebs", image['RootDeviceType'],
|
||||
"Image is not EBS image")
|
||||
|
||||
@decorators.idempotent_id('d45be578-5968-4189-8f25-56bf8ef23d20')
|
||||
@testtools.skipUnless(CONF.aws.ebs_image_id, "EBS image id is not defined")
|
||||
def test_check_ebs_image_volume_properties(self):
|
||||
image_id = CONF.aws.ebs_image_id
|
||||
data = self.client.describe_images(ImageIds=[image_id])
|
||||
self.assertEqual(1, len(data['Images']))
|
||||
image = data['Images'][0]
|
||||
self.assertTrue(image['RootDeviceName'])
|
||||
self.assertTrue(image['BlockDeviceMappings'])
|
||||
device_name = image['RootDeviceName']
|
||||
bdm = image['BlockDeviceMappings']
|
||||
bdm = [v for v in bdm if v['DeviceName'] == device_name]
|
||||
self.assertEqual(1, len(bdm))
|
||||
bdm = bdm[0]
|
||||
self.assertIn('Ebs', bdm)
|
||||
ebs = bdm['Ebs']
|
||||
self.assertIsNotNone(ebs.get('SnapshotId'))
|
||||
self.assertIsNotNone(ebs.get('DeleteOnTermination'))
|
||||
self.assertIsNotNone(ebs.get('VolumeSize'))
|
||||
if CONF.aws.run_incompatible_tests:
|
||||
self.assertIsNotNone(ebs.get('Encrypted'))
|
||||
self.assertFalse(ebs.get('Encrypted'))
|
||||
self.assertIsNotNone(ebs.get('VolumeType'))
|
||||
|
||||
@decorators.idempotent_id('a139f5ea-45fd-4b3e-9a52-32de0f8c3bca')
|
||||
@testtools.skip("flaky test")
|
||||
@testtools.skipUnless(CONF.aws.ebs_image_id, "EBS image id is not defined")
|
||||
def test_describe_image_with_filters(self):
|
||||
image_id = CONF.aws.ebs_image_id
|
||||
data = self.client.describe_images(ImageIds=[image_id])
|
||||
self.assertEqual(1, len(data['Images']))
|
||||
|
||||
data = self.client.describe_images(
|
||||
# NOTE(ft): limit output to prevent timeout over AWS
|
||||
Filters=[{'Name': 'image-type', 'Values': ['kernel', 'ramdisk']}])
|
||||
if len(data['Images']) < 2:
|
||||
self.skipTest("Insufficient images to check filters")
|
||||
data = self.client.describe_images(
|
||||
Filters=[{'Name': 'image-id', 'Values': [image_id]}])
|
||||
self.assertEqual(1, len(data['Images']))
|
||||
self.assertEqual(image_id, data['Images'][0]['ImageId'])
|
||||
|
||||
@decorators.idempotent_id('743e1f87-e0b6-4787-ab22-176379030007')
|
||||
@testtools.skipUnless(CONF.aws.image_id, "Image id is not defined")
|
||||
def test_check_image_operations_negative(self):
|
||||
# NOTE(andrey-mp): image_id is a public image created by admin
|
||||
image_id = CONF.aws.image_id
|
||||
|
||||
self.assertRaises('InvalidRequest',
|
||||
self.client.describe_image_attribute,
|
||||
ImageId=image_id, Attribute='unsupported')
|
||||
|
||||
self.assertRaises('AuthFailure',
|
||||
self.client.describe_image_attribute,
|
||||
ImageId=image_id, Attribute='description')
|
||||
|
||||
self.assertRaises('InvalidParameterCombination',
|
||||
self.client.modify_image_attribute,
|
||||
ImageId=image_id, Attribute='unsupported')
|
||||
|
||||
self.assertRaises('InvalidParameter',
|
||||
self.client.modify_image_attribute,
|
||||
ImageId=image_id, Attribute='blockDeviceMapping')
|
||||
|
||||
self.assertRaises('InvalidParameterCombination',
|
||||
self.client.modify_image_attribute,
|
||||
ImageId=image_id)
|
||||
|
||||
self.assertRaises('AuthFailure',
|
||||
self.client.modify_image_attribute,
|
||||
ImageId=image_id, Description={'Value': 'fake'})
|
||||
|
||||
self.assertRaises('AuthFailure',
|
||||
self.client.modify_image_attribute,
|
||||
ImageId=image_id, LaunchPermission={'Add': [{'Group': 'all'}]})
|
||||
|
||||
self.assertRaises('MissingParameter',
|
||||
self.client.modify_image_attribute,
|
||||
ImageId=image_id, Attribute='description')
|
||||
|
||||
self.assertRaises('InvalidParameterCombination',
|
||||
self.client.modify_image_attribute,
|
||||
ImageId=image_id, Attribute='launchPermission')
|
||||
|
||||
self.assertRaises('InvalidRequest',
|
||||
self.client.reset_image_attribute,
|
||||
ImageId=image_id, Attribute='fake')
|
||||
|
||||
self.assertRaises('AuthFailure',
|
||||
self.client.reset_image_attribute,
|
||||
ImageId=image_id, Attribute='launchPermission')
|
||||
|
||||
self.assertRaises('AuthFailure',
|
||||
self.client.deregister_image,
|
||||
ImageId=image_id)
|
||||
|
||||
@decorators.idempotent_id('a948dad1-9128-446b-86ee-82db13342054')
|
||||
@testtools.skipUnless(CONF.aws.image_id, 'image id is not defined')
|
||||
def test_create_image_from_non_ebs_instance(self):
|
||||
image_id = CONF.aws.image_id
|
||||
data = self.client.describe_images(ImageIds=[image_id])
|
||||
image = data['Images'][0]
|
||||
if 'RootDeviceType' in image and 'ebs' in image['RootDeviceType']:
|
||||
raise self.skipException('image_id should not be EBS image.')
|
||||
|
||||
instance_id = self.run_instance(ImageId=image_id)
|
||||
|
||||
def _rollback(fn_data):
|
||||
self.client.deregister_image(ImageId=fn_data['ImageId'])
|
||||
|
||||
self.assertRaises('InvalidParameterValue',
|
||||
self.client.create_image, rollback_fn=_rollback,
|
||||
InstanceId=instance_id, Name='name', Description='desc')
|
||||
|
||||
data = self.client.terminate_instances(InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_delete(instance_id)
|
||||
|
||||
def _create_image(self, name, desc, extra_run_instance_args={}):
|
||||
image_id = CONF.aws.ebs_image_id
|
||||
data = self.client.describe_images(ImageIds=[image_id])
|
||||
image = data['Images'][0]
|
||||
self.assertTrue('RootDeviceType' in image
|
||||
and 'ebs' in image['RootDeviceType'])
|
||||
|
||||
instance_id = self.run_instance(ImageId=image_id,
|
||||
**extra_run_instance_args)
|
||||
instance = self.get_instance(instance_id)
|
||||
for bdm in instance.get('BlockDeviceMappings', []):
|
||||
if 'Ebs' in bdm:
|
||||
self.addResourceCleanUp(self.client.delete_volume,
|
||||
VolumeId=bdm['Ebs']['VolumeId'])
|
||||
|
||||
data = self.client.create_image(InstanceId=instance_id,
|
||||
Name=name, Description=desc)
|
||||
image_id = data['ImageId']
|
||||
image_clean = self.addResourceCleanUp(self.client.deregister_image,
|
||||
ImageId=image_id)
|
||||
self.get_image_waiter().wait_available(image_id)
|
||||
|
||||
data = self.client.describe_images(ImageIds=[image_id])
|
||||
for bdm in data['Images'][0].get('BlockDeviceMappings', []):
|
||||
if 'Ebs' in bdm and 'SnapshotId' in bdm['Ebs']:
|
||||
snapshot_id = bdm['Ebs']['SnapshotId']
|
||||
self.addResourceCleanUp(self.client.delete_snapshot,
|
||||
SnapshotId=snapshot_id)
|
||||
|
||||
data = self.client.terminate_instances(InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_delete(instance_id)
|
||||
|
||||
return image_id, image_clean
|
||||
|
||||
@decorators.idempotent_id('f4fbb311-8a59-443d-a60a-11779917c757')
|
||||
@testtools.skipUnless(CONF.aws.ebs_image_id, "EBS image id is not defined")
|
||||
def test_create_image_from_ebs_instance(self):
|
||||
name = data_utils.rand_name('image')
|
||||
desc = data_utils.rand_name('description')
|
||||
image_id, image_clean = self._create_image(name, desc)
|
||||
|
||||
data = self.client.describe_images(ImageIds=[image_id])
|
||||
self.assertEqual(1, len(data['Images']))
|
||||
image = data['Images'][0]
|
||||
|
||||
self.assertIsNotNone(image['CreationDate'])
|
||||
self.assertEqual("ebs", image['RootDeviceType'])
|
||||
self.assertFalse(image['Public'])
|
||||
self.assertEqual(name, image['Name'])
|
||||
self.assertEqual(desc, image['Description'])
|
||||
self.assertEqual('machine', image['ImageType'])
|
||||
self.assertNotEmpty(image['BlockDeviceMappings'])
|
||||
for bdm in image['BlockDeviceMappings']:
|
||||
self.assertIn('DeviceName', bdm)
|
||||
|
||||
data = self.client.deregister_image(ImageId=image_id)
|
||||
self.cancelResourceCleanUp(image_clean)
|
||||
|
||||
@decorators.idempotent_id('b9aba1f7-0a7e-4717-b879-efe3bbea74e2')
|
||||
@testtools.skipUnless(CONF.aws.ebs_image_id, "EBS image id is not defined")
|
||||
def test_check_simple_image_attributes(self):
|
||||
data = self.client.describe_images(ImageIds=[CONF.aws.ebs_image_id])
|
||||
base_image = data['Images'][0]
|
||||
|
||||
name = data_utils.rand_name('image')
|
||||
desc = data_utils.rand_name('desc for image')
|
||||
image_id, image_clean = self._create_image(name, desc)
|
||||
|
||||
data = self.client.describe_image_attribute(
|
||||
ImageId=image_id, Attribute='kernel')
|
||||
if 'KernelId' in base_image:
|
||||
self.assertIn('KernelId', data)
|
||||
else:
|
||||
self.assertNotIn('KernelId', data)
|
||||
|
||||
data = self.client.describe_image_attribute(
|
||||
ImageId=image_id, Attribute='ramdisk')
|
||||
if 'RamdiskId' in base_image:
|
||||
self.assertIn('RamdiskId', data)
|
||||
else:
|
||||
self.assertNotIn('RamdiskId', data)
|
||||
|
||||
# description
|
||||
data = self.client.describe_image_attribute(
|
||||
ImageId=image_id, Attribute='description')
|
||||
self.assertIn('Description', data)
|
||||
self.assertIn('Value', data['Description'])
|
||||
self.assertEqual(desc, data['Description']['Value'])
|
||||
|
||||
def _modify_description(**kwargs):
|
||||
self.client.modify_image_attribute(ImageId=image_id, **kwargs)
|
||||
data = self.client.describe_image_attribute(
|
||||
ImageId=image_id, Attribute='description')
|
||||
self.assertEqual(new_desc, data['Description']['Value'])
|
||||
|
||||
new_desc = data_utils.rand_name('new desc')
|
||||
_modify_description(Attribute='description', Value=new_desc)
|
||||
_modify_description(Description={'Value': new_desc})
|
||||
|
||||
data = self.client.deregister_image(ImageId=image_id)
|
||||
self.cancelResourceCleanUp(image_clean)
|
||||
|
||||
@decorators.idempotent_id('680963cf-84f2-488d-bcdb-fc6f9b39f78c')
|
||||
@testtools.skipUnless(CONF.aws.ebs_image_id, "EBS image id is not defined")
|
||||
def test_check_bdm_in_image(self):
|
||||
image_id = CONF.aws.ebs_image_id
|
||||
data = self.client.describe_images(ImageIds=[image_id])
|
||||
root_device_name = data['Images'][0]['RootDeviceName']
|
||||
device_name_prefix = base.get_device_name_prefix(root_device_name)
|
||||
device_name = device_name_prefix + 'h'
|
||||
|
||||
name = data_utils.rand_name('image')
|
||||
desc = data_utils.rand_name('description')
|
||||
image_id, image_clean = self._create_image(
|
||||
name, desc,
|
||||
extra_run_instance_args={
|
||||
'BlockDeviceMappings': [{'DeviceName': device_name,
|
||||
'Ebs': {'VolumeSize': 1}}]})
|
||||
|
||||
data = self.client.describe_images(ImageIds=[image_id])
|
||||
image = data['Images'][0]
|
||||
|
||||
for bdm in image['BlockDeviceMappings']:
|
||||
self.assertTrue('DeviceName', bdm)
|
||||
|
||||
data = self.client.deregister_image(ImageId=image_id)
|
||||
self.cancelResourceCleanUp(image_clean)
|
||||
|
||||
@decorators.idempotent_id('1c244c9a-af3e-47f0-bc85-034e24b051e4')
|
||||
@testtools.skipUnless(CONF.aws.run_incompatible_tests,
|
||||
'By default glance is configured as "publicize_image": "role:admin"')
|
||||
@testtools.skipUnless(CONF.aws.run_incompatible_tests,
|
||||
'skip due to bug #1439819')
|
||||
@testtools.skipUnless(CONF.aws.ebs_image_id, "EBS image id is not defined")
|
||||
def test_check_launch_permission_attribute(self):
|
||||
name = data_utils.rand_name('image')
|
||||
desc = data_utils.rand_name('desc for image')
|
||||
image_id, image_clean = self._create_image(name, desc)
|
||||
|
||||
# launch permission
|
||||
data = self.client.describe_image_attribute(
|
||||
ImageId=image_id, Attribute='launchPermission')
|
||||
self.assertIn('LaunchPermissions', data)
|
||||
self.assertEmpty(data['LaunchPermissions'])
|
||||
|
||||
def _modify_launch_permission(**kwargs):
|
||||
self.client.modify_image_attribute(ImageId=image_id, **kwargs)
|
||||
data = self.client.describe_image_attribute(
|
||||
ImageId=image_id, Attribute='launchPermission')
|
||||
self.assertIn('LaunchPermissions', data)
|
||||
self.assertNotEmpty(data['LaunchPermissions'])
|
||||
self.assertIn('Group', data['LaunchPermissions'][0])
|
||||
self.assertEqual('all', data['LaunchPermissions'][0]['Group'])
|
||||
data = self.client.describe_images(ImageIds=[image_id])
|
||||
self.assertTrue(data['Images'][0]['Public'])
|
||||
|
||||
self.client.reset_image_attribute(
|
||||
ImageId=image_id, Attribute='launchPermission')
|
||||
data = self.client.describe_image_attribute(
|
||||
ImageId=image_id, Attribute='launchPermission')
|
||||
self.assertEmpty(data['LaunchPermissions'])
|
||||
data = self.client.describe_images(ImageIds=[image_id])
|
||||
self.assertFalse(data['Images'][0]['Public'])
|
||||
|
||||
_modify_launch_permission(Attribute='launchPermission',
|
||||
OperationType='add', UserGroups=['all'])
|
||||
_modify_launch_permission(LaunchPermission={'Add': [{'Group': 'all'}]})
|
||||
|
||||
data = self.client.deregister_image(ImageId=image_id)
|
||||
self.cancelResourceCleanUp(image_clean)
|
||||
|
||||
|
||||
class ImageRegisterTest(base.EC2TestCase):
|
||||
|
||||
valid_image_state = set(('available', 'pending', 'failed'))
|
||||
|
||||
@classmethod
|
||||
@base.safe_setup
|
||||
def setUpClass(cls):
|
||||
super(ImageRegisterTest, cls).setUpClass()
|
||||
cls.image_location = CONF.aws.ami_image_location
|
||||
if not cls.image_location:
|
||||
raise cls.skipException('Image materials are not ready in S3')
|
||||
|
||||
@decorators.idempotent_id('3e25269d-c8a2-4438-ab25-c343cb53db79')
|
||||
def test_register_get_deregister_ami_image(self):
|
||||
image_name = data_utils.rand_name("ami-name")
|
||||
data = self.client.register_image(
|
||||
Name=image_name, ImageLocation=self.image_location)
|
||||
image_id = data['ImageId']
|
||||
image_clean = self.addResourceCleanUp(self.client.deregister_image,
|
||||
ImageId=image_id)
|
||||
self.assertEqual(image_id[0:3], "ami")
|
||||
|
||||
data = self.client.describe_images(ImageIds=[image_id])
|
||||
self.assertEqual(1, len(data['Images']))
|
||||
image = data['Images'][0]
|
||||
self.assertEqual(image_name, image['Name'])
|
||||
self.assertEqual(image_id, image['ImageId'])
|
||||
self.assertIn(image['State'], self.valid_image_state)
|
||||
|
||||
self.get_image_waiter().wait_available(image_id)
|
||||
|
||||
self.client.deregister_image(ImageId=image_id)
|
||||
self.cancelResourceCleanUp(image_clean)
|
||||
self.get_image_waiter().wait_delete(image_id)
|
|
@ -1,365 +0,0 @@
|
|||
# Copyright 2014 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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 time
|
||||
|
||||
from oslo_log import log
|
||||
from tempest.lib.common.utils import data_utils
|
||||
from tempest.lib import decorators
|
||||
import testtools
|
||||
|
||||
from ec2api_tempest_plugin import base
|
||||
from ec2api_tempest_plugin import config
|
||||
|
||||
CONF = config.CONF
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
|
||||
class InstanceAttributeTest(base.EC2TestCase):
|
||||
|
||||
@decorators.idempotent_id('485107d8-f65f-4441-9558-2ff783e52e22')
|
||||
@testtools.skipUnless(CONF.aws.ebs_image_id, "EBS image id is not defined")
|
||||
def test_describe_instance_attributes(self):
|
||||
instance_id = self.run_instance(ImageId=CONF.aws.ebs_image_id)
|
||||
|
||||
data = self.client.describe_instance_attribute(
|
||||
InstanceId=instance_id, Attribute='blockDeviceMapping')
|
||||
bdms = data.get('BlockDeviceMappings', [])
|
||||
self.assertNotEmpty(bdms)
|
||||
self.assertEqual(1, len(bdms))
|
||||
self.assertIn('DeviceName', bdms[0])
|
||||
self.assertIn('Ebs', bdms[0])
|
||||
|
||||
data = self.client.describe_instance_attribute(
|
||||
InstanceId=instance_id, Attribute='disableApiTermination')
|
||||
self.assertIn('DisableApiTermination', data)
|
||||
self.assertIn('Value', data['DisableApiTermination'])
|
||||
self.assertFalse(data['DisableApiTermination']['Value'])
|
||||
|
||||
data = self.client.describe_instance_attribute(
|
||||
InstanceId=instance_id, Attribute='groupSet')
|
||||
self.assertIn('Groups', data)
|
||||
self.assertNotEmpty(data['Groups'], data)
|
||||
self.assertTrue('GroupId' in data['Groups'][0]
|
||||
or 'GroupName' in data['Groups'][0])
|
||||
self.assertTrue(data['Groups'][0].get('GroupId')
|
||||
or data['Groups'][0].get('GroupName'))
|
||||
|
||||
data = self.client.describe_instance_attribute(
|
||||
InstanceId=instance_id, Attribute='instanceType')
|
||||
self.assertIn('InstanceType', data)
|
||||
self.assertIn('Value', data['InstanceType'])
|
||||
self.assertEqual(CONF.aws.instance_type, data['InstanceType']['Value'])
|
||||
|
||||
data = self.client.describe_instance_attribute(
|
||||
InstanceId=instance_id, Attribute='kernel')
|
||||
self.assertIn('KernelId', data)
|
||||
|
||||
data = self.client.describe_instance_attribute(
|
||||
InstanceId=instance_id, Attribute='ramdisk')
|
||||
self.assertIn('RamdiskId', data)
|
||||
|
||||
data = self.client.describe_instance_attribute(
|
||||
InstanceId=instance_id, Attribute='rootDeviceName')
|
||||
self.assertIn('RootDeviceName', data)
|
||||
self.assertIn('Value', data['RootDeviceName'])
|
||||
self.assertTrue(data['RootDeviceName']['Value'])
|
||||
|
||||
self.client.terminate_instances(InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_delete(instance_id)
|
||||
|
||||
@decorators.idempotent_id('391f6645-d014-42c7-a727-f3a6e7a13a4c')
|
||||
@testtools.skipUnless(CONF.aws.image_id, "image id is not defined")
|
||||
def test_disable_api_termination_attribute(self):
|
||||
instance_id = self.run_instance(DisableApiTermination=True)
|
||||
res_clean = self.addResourceCleanUp(
|
||||
self.client.modify_instance_attribute,
|
||||
InstanceId=instance_id,
|
||||
DisableApiTermination={'Value': False})
|
||||
|
||||
data = self.client.describe_instance_attribute(
|
||||
InstanceId=instance_id, Attribute='disableApiTermination')
|
||||
self.assertIn('DisableApiTermination', data)
|
||||
self.assertIn('Value', data['DisableApiTermination'])
|
||||
self.assertTrue(data['DisableApiTermination']['Value'])
|
||||
|
||||
data = self.client.modify_instance_attribute(InstanceId=instance_id,
|
||||
Attribute='disableApiTermination', Value='False')
|
||||
data = self.client.describe_instance_attribute(
|
||||
InstanceId=instance_id, Attribute='disableApiTermination')
|
||||
self.assertFalse(data['DisableApiTermination']['Value'])
|
||||
|
||||
data = self.client.modify_instance_attribute(InstanceId=instance_id,
|
||||
Attribute='disableApiTermination', Value='True')
|
||||
data = self.client.describe_instance_attribute(
|
||||
InstanceId=instance_id, Attribute='disableApiTermination')
|
||||
self.assertTrue(data['DisableApiTermination']['Value'])
|
||||
|
||||
self.assertRaises('OperationNotPermitted',
|
||||
self.client.terminate_instances,
|
||||
InstanceIds=[instance_id])
|
||||
|
||||
data = self.client.modify_instance_attribute(InstanceId=instance_id,
|
||||
DisableApiTermination={'Value': False})
|
||||
data = self.client.describe_instance_attribute(
|
||||
InstanceId=instance_id, Attribute='disableApiTermination')
|
||||
self.assertFalse(data['DisableApiTermination']['Value'])
|
||||
|
||||
self.client.terminate_instances(InstanceIds=[instance_id])
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
self.get_instance_waiter().wait_delete(instance_id)
|
||||
|
||||
@decorators.idempotent_id('50671a21-99bf-4514-acb0-97617f92e868')
|
||||
@testtools.skipUnless(CONF.aws.image_id, "image id is not defined")
|
||||
def test_instance_attributes_negative(self):
|
||||
instance_id = self.run_instance()
|
||||
|
||||
self.assertRaises('InvalidParameterValue',
|
||||
self.client.describe_instance_attribute,
|
||||
InstanceId=instance_id, Attribute='fake_attribute')
|
||||
self.assertRaises('InvalidInstanceID.NotFound',
|
||||
self.client.describe_instance_attribute,
|
||||
InstanceId='i-0', Attribute='disableApiTermination')
|
||||
if base.TesterStateHolder().get_ec2_enabled():
|
||||
self.assertRaises('InvalidParameterCombination',
|
||||
self.client.describe_instance_attribute,
|
||||
InstanceId=instance_id, Attribute='sourceDestCheck')
|
||||
|
||||
self.assertRaises('InvalidParameterValue',
|
||||
self.client.modify_instance_attribute,
|
||||
InstanceId=instance_id, Attribute='fake_attribute')
|
||||
self.assertRaises('MissingParameter',
|
||||
self.client.modify_instance_attribute,
|
||||
InstanceId=instance_id, Attribute='disableApiTermination')
|
||||
self.assertRaises('InvalidParameterCombination',
|
||||
self.client.modify_instance_attribute,
|
||||
InstanceId=instance_id)
|
||||
self.assertRaises('InvalidParameterCombination',
|
||||
self.client.modify_instance_attribute,
|
||||
InstanceId=instance_id, Attribute='disableApiTermination',
|
||||
Value='True', DisableApiTermination={'Value': False})
|
||||
|
||||
ex_str = ('InvalidParameterCombination'
|
||||
if base.TesterStateHolder().get_ec2_enabled() else
|
||||
'InvalidGroup.NotFound')
|
||||
self.assertRaises(ex_str,
|
||||
self.client.modify_instance_attribute,
|
||||
InstanceId=instance_id, Groups=['sg-0'])
|
||||
if base.TesterStateHolder().get_ec2_enabled():
|
||||
self.assertRaises('InvalidParameterCombination',
|
||||
self.client.modify_instance_attribute,
|
||||
InstanceId=instance_id, Attribute='sourceDestCheck',
|
||||
Value='False')
|
||||
|
||||
self.assertRaises('InvalidParameterValue',
|
||||
self.client.reset_instance_attribute,
|
||||
InstanceId=instance_id, Attribute='fake_attribute')
|
||||
self.assertRaises('InvalidParameterValue',
|
||||
self.client.reset_instance_attribute,
|
||||
InstanceId=instance_id, Attribute='disableApiTermination')
|
||||
self.assertRaises('InvalidParameterValue',
|
||||
self.client.reset_instance_attribute,
|
||||
InstanceId='i-0', Attribute='disableApiTermination')
|
||||
self.assertRaises('InvalidParameterValue',
|
||||
self.client.reset_instance_attribute,
|
||||
InstanceId=instance_id, Attribute='groupSet')
|
||||
self.assertRaises('InvalidParameterValue',
|
||||
self.client.reset_instance_attribute,
|
||||
InstanceId=instance_id, Attribute='instanceType')
|
||||
|
||||
if base.TesterStateHolder().get_ec2_enabled():
|
||||
self.assertRaises('InvalidParameterCombination',
|
||||
self.client.reset_instance_attribute,
|
||||
InstanceId=instance_id, Attribute='sourceDestCheck')
|
||||
|
||||
self.assertRaises('IncorrectInstanceState',
|
||||
self.client.modify_instance_attribute,
|
||||
InstanceId=instance_id, Attribute='instanceType',
|
||||
Value=CONF.aws.instance_type)
|
||||
self.assertRaises('IncorrectInstanceState',
|
||||
self.client.modify_instance_attribute,
|
||||
InstanceId=instance_id,
|
||||
InstanceType={'Value': CONF.aws.instance_type})
|
||||
|
||||
self.client.terminate_instances(InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_delete(instance_id)
|
||||
|
||||
@base.skip_without_vpc()
|
||||
@decorators.idempotent_id('6fd2c8eb-f7f9-420d-a8ae-5d5af3a49a35')
|
||||
@testtools.skipUnless(CONF.aws.image_id, "image id is not defined")
|
||||
def test_attributes_for_multiple_interfaces_negative(self):
|
||||
vpc_id, subnet_id = self.create_vpc_and_subnet('10.30.0.0/24')
|
||||
|
||||
name = data_utils.rand_name('sgName')
|
||||
desc = data_utils.rand_name('sgDesc')
|
||||
data = self.client.create_security_group(VpcId=vpc_id, GroupName=name,
|
||||
Description=desc)
|
||||
group_id = data['GroupId']
|
||||
self.addResourceCleanUp(self.client.delete_security_group,
|
||||
GroupId=group_id)
|
||||
time.sleep(2)
|
||||
data = self.client.create_network_interface(SubnetId=subnet_id,
|
||||
Groups=[group_id])
|
||||
ni_id2 = data['NetworkInterface']['NetworkInterfaceId']
|
||||
self.addResourceCleanUp(self.client.delete_network_interface,
|
||||
NetworkInterfaceId=ni_id2)
|
||||
self.get_network_interface_waiter().wait_available(ni_id2)
|
||||
|
||||
instance_id = self.run_instance(SubnetId=subnet_id)
|
||||
|
||||
kwargs = {
|
||||
'DeviceIndex': 2,
|
||||
'InstanceId': instance_id,
|
||||
'NetworkInterfaceId': ni_id2
|
||||
}
|
||||
data = self.client.attach_network_interface(*[], **kwargs)
|
||||
|
||||
self.assertRaises('InvalidInstanceID',
|
||||
self.client.describe_instance_attribute,
|
||||
InstanceId=instance_id, Attribute='groupSet')
|
||||
self.assertRaises('InvalidInstanceID',
|
||||
self.client.modify_instance_attribute,
|
||||
InstanceId=instance_id, Groups=['sg-0'])
|
||||
|
||||
self.assertRaises('InvalidInstanceID',
|
||||
self.client.describe_instance_attribute,
|
||||
InstanceId=instance_id, Attribute='sourceDestCheck')
|
||||
self.assertRaises('InvalidInstanceID',
|
||||
self.client.modify_instance_attribute,
|
||||
InstanceId=instance_id, SourceDestCheck={'Value': False})
|
||||
self.assertRaises('InvalidInstanceID',
|
||||
self.client.reset_instance_attribute,
|
||||
InstanceId=instance_id, Attribute='sourceDestCheck')
|
||||
|
||||
self.client.terminate_instances(InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_delete(instance_id)
|
||||
|
||||
@base.skip_without_vpc()
|
||||
@decorators.idempotent_id('da26cc0d-6c2d-4638-97f1-1abfae8f00b5')
|
||||
@testtools.skipUnless(CONF.aws.image_id, "image id is not defined")
|
||||
def test_group_set_attribute(self):
|
||||
vpc_id, subnet_id = self.create_vpc_and_subnet('10.30.0.0/24')
|
||||
|
||||
instance_id = self.run_instance(SubnetId=subnet_id)
|
||||
|
||||
data = self.client.describe_instance_attribute(
|
||||
InstanceId=instance_id, Attribute='groupSet')
|
||||
self.assertIn('Groups', data)
|
||||
self.assertEqual(1, len(data['Groups']))
|
||||
default_group_id = data['Groups'][0]['GroupId']
|
||||
|
||||
name = data_utils.rand_name('sgName')
|
||||
desc = data_utils.rand_name('sgDesc')
|
||||
data = self.client.create_security_group(VpcId=vpc_id, GroupName=name,
|
||||
Description=desc)
|
||||
group_id = data['GroupId']
|
||||
self.addResourceCleanUp(self.client.delete_security_group,
|
||||
GroupId=group_id)
|
||||
time.sleep(2)
|
||||
|
||||
try:
|
||||
data = self.client.modify_instance_attribute(
|
||||
InstanceId=instance_id, Groups=[group_id])
|
||||
data = self.client.describe_instance_attribute(
|
||||
InstanceId=instance_id, Attribute='groupSet')
|
||||
self.assertIn('Groups', data)
|
||||
self.assertEqual(1, len(data['Groups']))
|
||||
self.assertNotEqual(default_group_id, data['Groups'][0]['GroupId'])
|
||||
|
||||
self.assertRaises('DependencyViolation',
|
||||
self.client.delete_security_group,
|
||||
GroupId=group_id)
|
||||
finally:
|
||||
self.client.modify_instance_attribute(InstanceId=instance_id,
|
||||
Groups=[default_group_id])
|
||||
|
||||
data = self.client.describe_instance_attribute(
|
||||
InstanceId=instance_id, Attribute='groupSet')
|
||||
self.assertIn('Groups', data)
|
||||
self.assertEqual(1, len(data['Groups']))
|
||||
self.assertEqual(default_group_id, data['Groups'][0]['GroupId'])
|
||||
|
||||
self.client.terminate_instances(InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_delete(instance_id)
|
||||
|
||||
@base.skip_without_vpc()
|
||||
@decorators.idempotent_id('8e7b37b5-1f2d-4c38-b51e-dcd0e726edb3')
|
||||
@testtools.skipUnless(CONF.aws.image_id, "image id is not defined")
|
||||
def test_source_dest_check_attribute(self):
|
||||
vpc_id, subnet_id = self.create_vpc_and_subnet('10.30.0.0/24')
|
||||
|
||||
instance_id = self.run_instance(SubnetId=subnet_id)
|
||||
|
||||
def do_check(value):
|
||||
data = self.client.describe_instance_attribute(
|
||||
InstanceId=instance_id, Attribute='sourceDestCheck')
|
||||
self.assertIn('SourceDestCheck', data)
|
||||
self.assertEqual(value, data['SourceDestCheck'].get('Value'))
|
||||
|
||||
do_check(True)
|
||||
|
||||
self.client.modify_instance_attribute(
|
||||
InstanceId=instance_id, Attribute='sourceDestCheck',
|
||||
Value='False')
|
||||
do_check(False)
|
||||
|
||||
self.client.reset_instance_attribute(
|
||||
InstanceId=instance_id, Attribute='sourceDestCheck')
|
||||
do_check(True)
|
||||
|
||||
self.client.modify_instance_attribute(
|
||||
InstanceId=instance_id, Attribute='sourceDestCheck',
|
||||
Value='False')
|
||||
do_check(False)
|
||||
|
||||
self.client.terminate_instances(InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_delete(instance_id)
|
||||
|
||||
@decorators.idempotent_id('a2640ab1-6aaa-4626-9f23-4aba52e3b88a')
|
||||
@testtools.skipUnless(CONF.aws.ebs_image_id, "EBS image id is not defined")
|
||||
@testtools.skipUnless(CONF.aws.instance_type_alt,
|
||||
"Alternative instance type is not defined")
|
||||
@testtools.skipUnless(CONF.aws.instance_type_alt != CONF.aws.instance_type,
|
||||
"Alternative instance type is not defined")
|
||||
def test_instance_type_attribute(self):
|
||||
instance_id = self.run_instance(ImageId=CONF.aws.ebs_image_id)
|
||||
|
||||
self.client.stop_instances(InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_available(instance_id,
|
||||
final_set=('stopped'))
|
||||
instance = self.get_instance(instance_id)
|
||||
self.assertEqual(CONF.aws.instance_type, instance['InstanceType'])
|
||||
|
||||
self.client.modify_instance_attribute(
|
||||
InstanceId=instance_id, Attribute='instanceType',
|
||||
Value=CONF.aws.instance_type)
|
||||
instance = self.get_instance(instance_id)
|
||||
self.assertEqual(CONF.aws.instance_type, instance['InstanceType'])
|
||||
|
||||
self.client.modify_instance_attribute(
|
||||
InstanceId=instance_id,
|
||||
InstanceType={'Value': CONF.aws.instance_type_alt})
|
||||
instance = self.get_instance(instance_id)
|
||||
self.assertEqual(CONF.aws.instance_type_alt, instance['InstanceType'])
|
||||
|
||||
self.client.start_instances(InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_available(instance_id,
|
||||
final_set=('running'))
|
||||
|
||||
instance = self.get_instance(instance_id)
|
||||
self.assertEqual(CONF.aws.instance_type_alt, instance['InstanceType'])
|
||||
|
||||
self.client.terminate_instances(InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_delete(instance_id)
|
|
@ -1,252 +0,0 @@
|
|||
# Copyright 2014 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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.
|
||||
|
||||
from oslo_log import log
|
||||
from tempest.lib.common.utils import data_utils
|
||||
from tempest.lib import decorators
|
||||
import testtools
|
||||
|
||||
from ec2api_tempest_plugin import base
|
||||
from ec2api_tempest_plugin import config
|
||||
|
||||
CONF = config.CONF
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
|
||||
class InstanceTest(base.EC2TestCase):
|
||||
|
||||
@classmethod
|
||||
@base.safe_setup
|
||||
def setUpClass(cls):
|
||||
super(InstanceTest, cls).setUpClass()
|
||||
if not CONF.aws.image_id:
|
||||
raise cls.skipException('aws image_id does not provided')
|
||||
cls.zone = CONF.aws.aws_zone
|
||||
|
||||
@decorators.idempotent_id('5604e461-c36a-4fea-84bc-eddfe702ae4f')
|
||||
def test_create_delete_instance(self):
|
||||
instance_type = CONF.aws.instance_type
|
||||
image_id = CONF.aws.image_id
|
||||
data = self.client.run_instances(
|
||||
ImageId=image_id, InstanceType=instance_type,
|
||||
Placement={'AvailabilityZone': self.zone}, MinCount=1, MaxCount=1)
|
||||
instance_id = data['Instances'][0]['InstanceId']
|
||||
res_clean = self.addResourceCleanUp(self.client.terminate_instances,
|
||||
InstanceIds=[instance_id])
|
||||
self.assertEqual(1, len(data['Instances']))
|
||||
self.get_instance_waiter().wait_available(instance_id,
|
||||
final_set=('running'))
|
||||
|
||||
data = self.client.describe_instances(InstanceIds=[instance_id])
|
||||
reservations = data.get('Reservations', [])
|
||||
self.assertNotEmpty(reservations)
|
||||
instances = reservations[0].get('Instances', [])
|
||||
self.assertEqual(1, len(instances))
|
||||
self.assertEqual(1, len(instances[0]['SecurityGroups']))
|
||||
groups = reservations[0].get('Groups', [])
|
||||
if base.TesterStateHolder().get_ec2_enabled():
|
||||
self.assertEqual(1, len(groups))
|
||||
self.assertEqual(groups[0]['GroupName'],
|
||||
instances[0]['SecurityGroups'][0]['GroupName'])
|
||||
else:
|
||||
self.assertEqual(0, len(groups))
|
||||
|
||||
self.client.terminate_instances(InstanceIds=[instance_id])
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
self.get_instance_waiter().wait_delete(instance_id)
|
||||
|
||||
# NOTE(andrey-mp): There is difference between Openstack and Amazon.
|
||||
# Amazon returns instance in 'terminated' state some time after
|
||||
# instance deletion. But Openstack doesn't return such instance.
|
||||
|
||||
@decorators.idempotent_id('40b273e5-3d43-4529-99b0-da5dd7e6764e')
|
||||
def test_create_idempotent_instance(self):
|
||||
client_token = data_utils.rand_name('t')
|
||||
instance_type = CONF.aws.instance_type
|
||||
image_id = CONF.aws.image_id
|
||||
data = self.client.run_instances(
|
||||
ImageId=image_id, InstanceType=instance_type,
|
||||
Placement={'AvailabilityZone': self.zone}, MinCount=1, MaxCount=1,
|
||||
ClientToken=client_token)
|
||||
instance_id = data['Instances'][0]['InstanceId']
|
||||
res_clean = self.addResourceCleanUp(self.client.terminate_instances,
|
||||
InstanceIds=[instance_id])
|
||||
self.assertEqual(1, len(data['Instances']))
|
||||
reservation_id = data['ReservationId']
|
||||
self.get_instance_waiter().wait_available(instance_id,
|
||||
final_set=('running'))
|
||||
|
||||
data = self.client.run_instances(
|
||||
ImageId=image_id, InstanceType=instance_type,
|
||||
Placement={'AvailabilityZone': self.zone}, MinCount=1, MaxCount=1,
|
||||
ClientToken=client_token)
|
||||
|
||||
# NOTE(andrey-mp): if idempotent run will fail this will terminate
|
||||
# second instance
|
||||
self.addResourceCleanUp(self.client.terminate_instances,
|
||||
InstanceIds=[data['Instances'][0]['InstanceId']])
|
||||
|
||||
self.assertEqual(1, len(data['Instances']))
|
||||
self.assertEqual(reservation_id, data['ReservationId'])
|
||||
self.assertEqual(instance_id, data['Instances'][0]['InstanceId'])
|
||||
|
||||
self.client.terminate_instances(InstanceIds=[instance_id])
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
self.get_instance_waiter().wait_delete(instance_id)
|
||||
|
||||
@decorators.idempotent_id('4c3c709a-72e2-4c87-bab2-e3a16fc5d1fe')
|
||||
def test_describe_instances_filter(self):
|
||||
instance_type = CONF.aws.instance_type
|
||||
image_id = CONF.aws.image_id
|
||||
data = self.client.run_instances(
|
||||
ImageId=image_id, InstanceType=instance_type,
|
||||
Placement={'AvailabilityZone': self.zone}, MinCount=1, MaxCount=1)
|
||||
instance_id = data['Instances'][0]['InstanceId']
|
||||
res_clean = self.addResourceCleanUp(self.client.terminate_instances,
|
||||
InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_available(instance_id,
|
||||
final_set=('running'))
|
||||
|
||||
# NOTE(andrey-mp): by real id
|
||||
data = self.client.describe_instances(InstanceIds=[instance_id])
|
||||
self._assert_instance(data, instance_id)
|
||||
instances = data['Reservations'][0]['Instances']
|
||||
private_dns = instances[0]['PrivateDnsName']
|
||||
private_ip = instances[0]['PrivateIpAddress']
|
||||
|
||||
# NOTE(andrey-mp): by fake id
|
||||
self.assertRaises('InvalidInstanceID.NotFound',
|
||||
self.client.describe_instances,
|
||||
InstanceIds=['i-0'])
|
||||
|
||||
# NOTE(andrey-mp): by private ip
|
||||
data = self.client.describe_instances(
|
||||
Filters=[{'Name': 'private-ip-address', 'Values': ['1.2.3.4']}])
|
||||
self.assertEqual(0, len(data['Reservations']))
|
||||
|
||||
data = self.client.describe_instances(
|
||||
Filters=[{'Name': 'private-ip-address', 'Values': [private_ip]}])
|
||||
self._assert_instance(data, instance_id)
|
||||
|
||||
# NOTE(andrey-mp): by private dns
|
||||
data = self.client.describe_instances(
|
||||
Filters=[{'Name': 'private-dns-name', 'Values': ['fake.com']}])
|
||||
self.assertEqual(0, len(data['Reservations']))
|
||||
|
||||
data = self.client.describe_instances(
|
||||
Filters=[{'Name': 'private-dns-name', 'Values': [private_dns]}])
|
||||
self._assert_instance(data, instance_id)
|
||||
|
||||
self.client.terminate_instances(InstanceIds=[instance_id])
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
self.get_instance_waiter().wait_delete(instance_id)
|
||||
|
||||
def _assert_instance(self, data, instance_id):
|
||||
reservations = data.get('Reservations', [])
|
||||
self.assertNotEmpty(reservations)
|
||||
instances = reservations[0].get('Instances', [])
|
||||
self.assertNotEmpty(instances)
|
||||
self.assertEqual(instance_id, instances[0]['InstanceId'])
|
||||
|
||||
@decorators.idempotent_id('d40bf881-4220-46a9-b04a-fca9054c9731')
|
||||
def test_get_password_data_and_console_output(self):
|
||||
instance_type = CONF.aws.instance_type
|
||||
image_id = CONF.aws.image_id
|
||||
data = self.client.run_instances(
|
||||
ImageId=image_id, InstanceType=instance_type,
|
||||
Placement={'AvailabilityZone': self.zone}, MinCount=1, MaxCount=1)
|
||||
instance_id = data['Instances'][0]['InstanceId']
|
||||
res_clean = self.addResourceCleanUp(self.client.terminate_instances,
|
||||
InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_available(instance_id,
|
||||
final_set=('running'))
|
||||
|
||||
data = self.client.get_password_data(InstanceId=instance_id)
|
||||
self.assertEqual(instance_id, data['InstanceId'])
|
||||
self.assertIsNotNone(data['Timestamp'])
|
||||
self.assertIn('PasswordData', data)
|
||||
|
||||
def _wait_for_output(*args, **kwargs):
|
||||
data = self.client.get_console_output(*args, **kwargs)
|
||||
self.assertIn('Output', data)
|
||||
|
||||
waiter = base.EC2Waiter(_wait_for_output)
|
||||
waiter.wait_no_exception(InstanceId=instance_id)
|
||||
|
||||
data = self.client.get_console_output(InstanceId=instance_id)
|
||||
self.assertEqual(instance_id, data['InstanceId'])
|
||||
self.assertIsNotNone(data['Timestamp'])
|
||||
self.assertIn('Output', data)
|
||||
|
||||
self.client.terminate_instances(InstanceIds=[instance_id])
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
self.get_instance_waiter().wait_delete(instance_id)
|
||||
|
||||
@decorators.idempotent_id('5947ccaa-a519-46f4-9d58-ceb79042266a')
|
||||
@testtools.skipUnless(CONF.aws.ebs_image_id, "EBS image id is not defined")
|
||||
def test_stop_instance(self):
|
||||
instance_type = CONF.aws.instance_type
|
||||
image_id = CONF.aws.ebs_image_id
|
||||
data = self.client.run_instances(
|
||||
ImageId=image_id, InstanceType=instance_type,
|
||||
Placement={'AvailabilityZone': self.zone}, MinCount=1, MaxCount=1)
|
||||
instance_id = data['Instances'][0]['InstanceId']
|
||||
res_clean = self.addResourceCleanUp(self.client.terminate_instances,
|
||||
InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_available(instance_id,
|
||||
final_set=('running'))
|
||||
|
||||
data = self.client.stop_instances(InstanceIds=[instance_id])
|
||||
if CONF.aws.run_incompatible_tests:
|
||||
instances = data['StoppingInstances']
|
||||
self.assertEqual(1, len(instances))
|
||||
instance = instances[0]
|
||||
self.assertEqual(instance_id, instance['InstanceId'])
|
||||
self.assertEqual('running', instance['PreviousState']['Name'])
|
||||
self.assertEqual('stopping', instance['CurrentState']['Name'])
|
||||
|
||||
self.get_instance_waiter().wait_available(instance_id,
|
||||
final_set=('stopped'))
|
||||
|
||||
self.client.terminate_instances(InstanceIds=[instance_id])
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
self.get_instance_waiter().wait_delete(instance_id)
|
||||
|
||||
@decorators.idempotent_id('0f29affb-eae5-42be-9b52-d28a17ba7107')
|
||||
@testtools.skipUnless(CONF.aws.run_incompatible_tests,
|
||||
"Openstack doesn't assign public ip automatically for new instance")
|
||||
def test_public_ip_is_assigned(self):
|
||||
"""Is public IP assigned to launched instnace?"""
|
||||
instance_type = CONF.aws.instance_type
|
||||
image_id = CONF.aws.image_id
|
||||
data = self.client.run_instances(
|
||||
ImageId=image_id, InstanceType=instance_type,
|
||||
Placement={'AvailabilityZone': self.zone}, MinCount=1, MaxCount=1)
|
||||
self.assertEqual(1, len(data['Instances']))
|
||||
instance_id = data['Instances'][0]['InstanceId']
|
||||
res_clean = self.addResourceCleanUp(self.client.terminate_instances,
|
||||
InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_available(instance_id,
|
||||
final_set=('running'))
|
||||
|
||||
instance = self.get_instance(instance_id)
|
||||
self.assertIsNotNone(instance.get('PublicIpAddress'))
|
||||
self.assertIsNotNone(instance.get('PrivateIpAddress'))
|
||||
self.assertNotEqual(instance.get('PublicIpAddress'),
|
||||
instance.get('PrivateIpAddress'))
|
||||
|
||||
self.client.terminate_instances(InstanceIds=[instance_id])
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
self.get_instance_waiter().wait_delete(instance_id)
|
|
@ -1,92 +0,0 @@
|
|||
# Copyright 2014 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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.
|
||||
|
||||
from oslo_log import log
|
||||
from tempest.lib import decorators
|
||||
import testtools
|
||||
|
||||
from ec2api_tempest_plugin import base
|
||||
from ec2api_tempest_plugin import config
|
||||
|
||||
CONF = config.CONF
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
|
||||
class InstanceWithEBSTest(base.EC2TestCase):
|
||||
|
||||
@decorators.idempotent_id('a5cad848-bed2-4dcb-8ba0-987bb7e9c487')
|
||||
@testtools.skipUnless(CONF.aws.ebs_image_id, "EBS image id is not defined")
|
||||
def test_create_get_delete_ebs_instance(self):
|
||||
"""Launch EBS-backed instance, check results, and terminate it."""
|
||||
instance_id = self.run_instance(ImageId=CONF.aws.ebs_image_id)
|
||||
instance = self.get_instance(instance_id)
|
||||
|
||||
self.assertEqual('ebs', instance.get('RootDeviceType'))
|
||||
self.assertIsNotNone(instance.get('RootDeviceName'))
|
||||
bdms = instance.get('BlockDeviceMappings')
|
||||
self.assertIsNotNone(bdms)
|
||||
rdn = instance['RootDeviceName']
|
||||
bdt = [bdt for bdt in bdms if bdt['DeviceName'] == rdn]
|
||||
self.assertEqual(1, len(bdt))
|
||||
ebs = bdt[0]['Ebs']
|
||||
self.assertIsNotNone(ebs)
|
||||
volume_id = ebs.get('VolumeId')
|
||||
self.assertIsNotNone(volume_id)
|
||||
self.assertEqual('attached', ebs.get('Status'))
|
||||
if CONF.aws.run_incompatible_tests:
|
||||
self.assertTrue(ebs.get('AttachTime'))
|
||||
self.assertTrue(ebs.get('DeleteOnTermination'))
|
||||
|
||||
data = self.client.describe_volumes(VolumeIds=[volume_id])
|
||||
self.assertEqual(1, len(data['Volumes']))
|
||||
|
||||
data = self.client.terminate_instances(InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_delete(instance_id)
|
||||
|
||||
@decorators.idempotent_id('b6226b7b-d965-4c3a-b2a8-48add794c194')
|
||||
@testtools.skipUnless(CONF.aws.ebs_image_id, "EBS image id is not defined")
|
||||
def test_create_root_volume_snapshot(self):
|
||||
"""Create snapshot of root volume of EBS-backed instance."""
|
||||
instance_id = self.run_instance(ImageId=CONF.aws.ebs_image_id)
|
||||
|
||||
bdt = self.get_instance_bdm(instance_id, None)
|
||||
self.assertIsNotNone(bdt)
|
||||
volume_id = bdt['Ebs'].get('VolumeId')
|
||||
self.assertIsNotNone(volume_id)
|
||||
|
||||
self.client.stop_instances(InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_available(instance_id,
|
||||
final_set=('stopped'))
|
||||
|
||||
data = self.client.describe_volumes(VolumeIds=[volume_id])
|
||||
self.assertEqual(1, len(data['Volumes']))
|
||||
|
||||
kwargs = {
|
||||
'VolumeId': data['Volumes'][0]['VolumeId'],
|
||||
'Description': 'Description'
|
||||
}
|
||||
data = self.client.create_snapshot(*[], **kwargs)
|
||||
snapshot_id = data['SnapshotId']
|
||||
res_clean_s = self.addResourceCleanUp(self.client.delete_snapshot,
|
||||
SnapshotId=snapshot_id)
|
||||
self.get_snapshot_waiter().wait_available(snapshot_id,
|
||||
final_set=('completed'))
|
||||
|
||||
data = self.client.delete_snapshot(SnapshotId=snapshot_id)
|
||||
self.cancelResourceCleanUp(res_clean_s)
|
||||
self.get_snapshot_waiter().wait_delete(snapshot_id)
|
||||
|
||||
data = self.client.terminate_instances(InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_delete(instance_id)
|
|
@ -1,282 +0,0 @@
|
|||
# Copyright 2014 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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.
|
||||
|
||||
from oslo_log import log
|
||||
from tempest.lib import decorators
|
||||
import testtools
|
||||
|
||||
from ec2api_tempest_plugin import base
|
||||
from ec2api_tempest_plugin import config
|
||||
|
||||
CONF = config.CONF
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
|
||||
class InstanceInVPCTest(base.EC2TestCase):
|
||||
|
||||
VPC_CIDR = '10.16.0.0/20'
|
||||
vpc_id = None
|
||||
SUBNET_CIDR = '10.16.0.0/24'
|
||||
subnet_id = None
|
||||
|
||||
@classmethod
|
||||
@base.safe_setup
|
||||
def setUpClass(cls):
|
||||
super(InstanceInVPCTest, cls).setUpClass()
|
||||
if not base.TesterStateHolder().get_vpc_enabled():
|
||||
raise cls.skipException('VPC is disabled')
|
||||
|
||||
data = cls.client.create_vpc(CidrBlock=cls.VPC_CIDR)
|
||||
cls.vpc_id = data['Vpc']['VpcId']
|
||||
cls.addResourceCleanUpStatic(cls.client.delete_vpc, VpcId=cls.vpc_id)
|
||||
cls.get_vpc_waiter().wait_available(cls.vpc_id)
|
||||
|
||||
aws_zone = CONF.aws.aws_zone
|
||||
data = cls.client.create_subnet(VpcId=cls.vpc_id,
|
||||
CidrBlock=cls.SUBNET_CIDR,
|
||||
AvailabilityZone=aws_zone)
|
||||
cls.subnet_id = data['Subnet']['SubnetId']
|
||||
cls.addResourceCleanUpStatic(cls.client.delete_subnet,
|
||||
SubnetId=cls.subnet_id)
|
||||
cls.get_subnet_waiter().wait_available(cls.subnet_id)
|
||||
|
||||
@decorators.idempotent_id('af8bd493-4a68-49e7-a3d1-326251b8d16e')
|
||||
@testtools.skipUnless(CONF.aws.image_id, "image id is not defined")
|
||||
def test_create_delete_instance(self):
|
||||
instance_id = self.run_instance(SubnetId=self.subnet_id)
|
||||
|
||||
data = self.client.describe_instances(InstanceIds=[instance_id])
|
||||
reservations = data.get('Reservations', [])
|
||||
self.assertNotEmpty(reservations)
|
||||
instances = reservations[0].get('Instances', [])
|
||||
self.assertNotEmpty(instances)
|
||||
instance = instances[0]
|
||||
self.assertEqual(self.vpc_id, instance['VpcId'])
|
||||
self.assertEqual(self.subnet_id, instance['SubnetId'])
|
||||
self.assertTrue(instance['SourceDestCheck'])
|
||||
self.assertEqual(1, len(instance['NetworkInterfaces']))
|
||||
ni = instance['NetworkInterfaces'][0]
|
||||
self.assertEqual(1, len(ni['Groups']))
|
||||
self.assertIsNotNone(ni['MacAddress'])
|
||||
self.assertIsNotNone(ni['PrivateIpAddress'])
|
||||
self.assertTrue(ni['SourceDestCheck'])
|
||||
self.assertEqual('in-use', ni['Status'])
|
||||
self.assertEqual(self.vpc_id, ni['VpcId'])
|
||||
self.assertEqual(self.subnet_id, ni['SubnetId'])
|
||||
|
||||
self.client.terminate_instances(InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_delete(instance_id)
|
||||
|
||||
# NOTE(andrey-mp): There is difference between Openstack and Amazon.
|
||||
# Amazon returns instance in 'terminated' state some time after
|
||||
# instance deletion. But Openstack doesn't return such instance.
|
||||
|
||||
@decorators.idempotent_id('17ba6206-3044-4e51-9e9b-f5d5728cc047')
|
||||
@testtools.skipUnless(CONF.aws.image_id, "image id is not defined")
|
||||
def test_describe_instances_filter(self):
|
||||
instance_id = self.run_instance(SubnetId=self.subnet_id)
|
||||
|
||||
data = self.client.describe_instances(InstanceIds=[instance_id])
|
||||
self.assert_instance(data, instance_id)
|
||||
instances = data['Reservations'][0]['Instances']
|
||||
private_dns = instances[0]['PrivateDnsName']
|
||||
private_ip = instances[0]['PrivateIpAddress']
|
||||
|
||||
# NOTE(andrey-mp): by private ip
|
||||
data = self.client.describe_instances(
|
||||
Filters=[{'Name': 'private-ip-address', 'Values': ['1.2.3.4']}])
|
||||
self.assertEqual(0, len(data['Reservations']))
|
||||
|
||||
data = self.client.describe_instances(
|
||||
Filters=[{'Name': 'private-ip-address', 'Values': [private_ip]}])
|
||||
self.assert_instance(data, instance_id)
|
||||
|
||||
# NOTE(andrey-mp): by private dns
|
||||
data = self.client.describe_instances(
|
||||
Filters=[{'Name': 'private-dns-name', 'Values': ['fake.com']}])
|
||||
self.assertEqual(0, len(data['Reservations']))
|
||||
|
||||
data = self.client.describe_instances(
|
||||
Filters=[{'Name': 'private-dns-name', 'Values': [private_dns]}])
|
||||
self.assert_instance(data, instance_id)
|
||||
|
||||
# NOTE(andrey-mp): by subnet id
|
||||
data = self.client.describe_instances(
|
||||
Filters=[{'Name': 'subnet-id', 'Values': ['subnet-0']}])
|
||||
self.assertEqual(0, len(data['Reservations']))
|
||||
|
||||
data = self.client.describe_instances(
|
||||
Filters=[{'Name': 'subnet-id', 'Values': [self.subnet_id]}])
|
||||
self.assert_instance(data, instance_id)
|
||||
|
||||
# NOTE(andrey-mp): by vpc id
|
||||
data = self.client.describe_instances(
|
||||
Filters=[{'Name': 'vpc-id', 'Values': ['vpc-0']}])
|
||||
self.assertEqual(0, len(data['Reservations']))
|
||||
|
||||
data = self.client.describe_instances(
|
||||
Filters=[{'Name': 'vpc-id', 'Values': [self.vpc_id]}])
|
||||
self.assert_instance(data, instance_id)
|
||||
|
||||
self.client.terminate_instances(InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_delete(instance_id)
|
||||
|
||||
def assert_instance(self, data, instance_id):
|
||||
reservations = data.get('Reservations', [])
|
||||
self.assertNotEmpty(reservations)
|
||||
instances = reservations[0].get('Instances', [])
|
||||
self.assertNotEmpty(instances)
|
||||
self.assertEqual(instance_id, instances[0]['InstanceId'])
|
||||
|
||||
@decorators.idempotent_id('60ceda8b-85ae-47a7-807b-c4a4dd05a13b')
|
||||
@testtools.skipUnless(CONF.aws.image_id, "image id is not defined")
|
||||
def test_create_instance_with_two_interfaces(self):
|
||||
kwargs = {
|
||||
'SubnetId': self.subnet_id,
|
||||
}
|
||||
data = self.client.create_network_interface(*[], **kwargs)
|
||||
ni_id1 = data['NetworkInterface']['NetworkInterfaceId']
|
||||
clean_ni1 = self.addResourceCleanUp(
|
||||
self.client.delete_network_interface, NetworkInterfaceId=ni_id1)
|
||||
self.get_network_interface_waiter().wait_available(ni_id1)
|
||||
|
||||
kwargs = {
|
||||
'SubnetId': self.subnet_id,
|
||||
}
|
||||
data = self.client.create_network_interface(*[], **kwargs)
|
||||
ni_id2 = data['NetworkInterface']['NetworkInterfaceId']
|
||||
clean_ni2 = self.addResourceCleanUp(
|
||||
self.client.delete_network_interface, NetworkInterfaceId=ni_id2)
|
||||
self.get_network_interface_waiter().wait_available(ni_id2)
|
||||
|
||||
instance_id = self.run_instance(
|
||||
NetworkInterfaces=[{'NetworkInterfaceId': ni_id1,
|
||||
'DeviceIndex': 0},
|
||||
{'NetworkInterfaceId': ni_id2,
|
||||
'DeviceIndex': 2}])
|
||||
|
||||
instance = self.get_instance(instance_id)
|
||||
nis = instance.get('NetworkInterfaces', [])
|
||||
self.assertEqual(2, len(nis))
|
||||
|
||||
self.client.terminate_instances(InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_delete(instance_id)
|
||||
|
||||
self.get_network_interface_waiter().wait_available(ni_id1)
|
||||
self.get_network_interface_waiter().wait_available(ni_id2)
|
||||
|
||||
self.client.delete_network_interface(
|
||||
NetworkInterfaceId=ni_id2)
|
||||
self.cancelResourceCleanUp(clean_ni2)
|
||||
self.get_network_interface_waiter().wait_delete(ni_id2)
|
||||
|
||||
self.client.delete_network_interface(
|
||||
NetworkInterfaceId=ni_id1)
|
||||
self.cancelResourceCleanUp(clean_ni1)
|
||||
self.get_network_interface_waiter().wait_delete(ni_id1)
|
||||
|
||||
@decorators.idempotent_id('a7dc520a-e828-4347-91e1-385c4e0e6070')
|
||||
@testtools.skipUnless(CONF.aws.image_id, "image id is not defined")
|
||||
def test_create_instance_with_private_ip(self):
|
||||
ip = '10.16.0.12'
|
||||
|
||||
instance_id = self.run_instance(SubnetId=self.subnet_id,
|
||||
PrivateIpAddress=ip)
|
||||
|
||||
instance = self.get_instance(instance_id)
|
||||
self.assertEqual(ip, instance['PrivateIpAddress'])
|
||||
|
||||
self.client.terminate_instances(InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_delete(instance_id)
|
||||
|
||||
@decorators.idempotent_id('582ac8ed-58e7-4f27-bd65-35b999241c63')
|
||||
@testtools.skipUnless(CONF.aws.image_id, "image id is not defined")
|
||||
def test_create_instance_with_invalid_params(self):
|
||||
def _rollback(fn_data):
|
||||
self.client.terminate_instances(
|
||||
InstanceIds=[fn_data['Instances'][0]['InstanceId']])
|
||||
|
||||
kwargs = {
|
||||
'ImageId': CONF.aws.image_id,
|
||||
'InstanceType': CONF.aws.instance_type,
|
||||
'MinCount': 1,
|
||||
'MaxCount': 1,
|
||||
'PrivateIpAddress': '10.16.1.2'
|
||||
}
|
||||
ex_str = ('InvalidParameterCombination'
|
||||
if base.TesterStateHolder().get_ec2_enabled() else
|
||||
'InvalidParameterValue')
|
||||
self.assertRaises(ex_str,
|
||||
self.client.run_instances, rollback_fn=_rollback,
|
||||
**kwargs)
|
||||
|
||||
kwargs = {
|
||||
'ImageId': CONF.aws.image_id,
|
||||
'InstanceType': CONF.aws.instance_type,
|
||||
'MinCount': 1,
|
||||
'MaxCount': 1,
|
||||
'SubnetId': self.subnet_id,
|
||||
'PrivateIpAddress': '10.16.1.12'
|
||||
}
|
||||
self.assertRaises('InvalidParameterValue',
|
||||
self.client.run_instances, rollback_fn=_rollback,
|
||||
**kwargs)
|
||||
|
||||
kwargs = {
|
||||
'SubnetId': self.subnet_id,
|
||||
}
|
||||
data = self.client.create_network_interface(*[], **kwargs)
|
||||
ni_id1 = data['NetworkInterface']['NetworkInterfaceId']
|
||||
self.addResourceCleanUp(self.client.delete_network_interface,
|
||||
NetworkInterfaceId=ni_id1)
|
||||
self.get_network_interface_waiter().wait_available(ni_id1)
|
||||
|
||||
kwargs = {
|
||||
'SubnetId': self.subnet_id,
|
||||
}
|
||||
data = self.client.create_network_interface(*[], **kwargs)
|
||||
ni_id2 = data['NetworkInterface']['NetworkInterfaceId']
|
||||
self.addResourceCleanUp(self.client.delete_network_interface,
|
||||
NetworkInterfaceId=ni_id2)
|
||||
self.get_network_interface_waiter().wait_available(ni_id2)
|
||||
|
||||
# NOTE(andrey-mp): A network interface may not specify a network
|
||||
# interface ID and delete on termination as true
|
||||
kwargs = {
|
||||
'ImageId': CONF.aws.image_id,
|
||||
'InstanceType': CONF.aws.instance_type,
|
||||
'MinCount': 1,
|
||||
'MaxCount': 1,
|
||||
'NetworkInterfaces': [{'NetworkInterfaceId': ni_id1,
|
||||
'DeviceIndex': 0,
|
||||
'DeleteOnTermination': True}]
|
||||
}
|
||||
self.assertRaises('InvalidParameterCombination',
|
||||
self.client.run_instances, rollback_fn=_rollback,
|
||||
**kwargs)
|
||||
|
||||
if CONF.aws.run_incompatible_tests:
|
||||
# NOTE(andrey-mp): Each network interface requires a device index.
|
||||
kwargs = {
|
||||
'ImageId': CONF.aws.image_id,
|
||||
'InstanceType': CONF.aws.instance_type,
|
||||
'MinCount': 1,
|
||||
'MaxCount': 1,
|
||||
'NetworkInterfaces': [{'NetworkInterfaceId': ni_id1},
|
||||
{'NetworkInterfaceId': ni_id2}]
|
||||
}
|
||||
self.assertRaises('InvalidParameterValue',
|
||||
self.client.run_instances, rollback_fn=_rollback,
|
||||
**kwargs)
|
|
@ -1,223 +0,0 @@
|
|||
# Copyright 2014 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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 time
|
||||
|
||||
from oslo_log import log
|
||||
from tempest.lib import decorators
|
||||
import testtools
|
||||
|
||||
from ec2api_tempest_plugin import base
|
||||
from ec2api_tempest_plugin import config
|
||||
|
||||
CONF = config.CONF
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
|
||||
class InternetGatewayTest(base.EC2TestCase):
|
||||
|
||||
VPC_CIDR = '10.4.0.0/20'
|
||||
VPC_CIDR_ALT = '10.5.0.0/20'
|
||||
vpc_id = None
|
||||
vpc_id_alt = None
|
||||
|
||||
@classmethod
|
||||
@base.safe_setup
|
||||
def setUpClass(cls):
|
||||
super(InternetGatewayTest, cls).setUpClass()
|
||||
if not base.TesterStateHolder().get_vpc_enabled():
|
||||
raise cls.skipException('VPC is disabled')
|
||||
|
||||
data = cls.client.create_vpc(CidrBlock=cls.VPC_CIDR)
|
||||
cls.vpc_id = data['Vpc']['VpcId']
|
||||
cls.get_vpc_waiter().wait_available(cls.vpc_id)
|
||||
cls.addResourceCleanUpStatic(cls.client.delete_vpc, VpcId=cls.vpc_id)
|
||||
|
||||
data = cls.client.create_vpc(CidrBlock=cls.VPC_CIDR_ALT)
|
||||
cls.vpc_id_alt = data['Vpc']['VpcId']
|
||||
cls.get_vpc_waiter().wait_available(cls.vpc_id_alt)
|
||||
cls.addResourceCleanUpStatic(cls.client.delete_vpc,
|
||||
VpcId=cls.vpc_id_alt)
|
||||
|
||||
@decorators.idempotent_id('f2d40306-4b18-4e17-90a5-371db0ddc7cb')
|
||||
def test_create_attach_internet_gateway(self):
|
||||
data = self.client.create_internet_gateway()
|
||||
gw_id = data['InternetGateway']['InternetGatewayId']
|
||||
res_clean = self.addResourceCleanUp(
|
||||
self.client.delete_internet_gateway, InternetGatewayId=gw_id)
|
||||
self.assertEmpty(data['InternetGateway'].get('Attachments', []))
|
||||
|
||||
data = self.client.attach_internet_gateway(VpcId=self.vpc_id,
|
||||
InternetGatewayId=gw_id)
|
||||
|
||||
data = self.client.detach_internet_gateway(VpcId=self.vpc_id,
|
||||
InternetGatewayId=gw_id)
|
||||
|
||||
data = self.client.delete_internet_gateway(InternetGatewayId=gw_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
|
||||
self.assertRaises('InvalidInternetGatewayID.NotFound',
|
||||
self.client.describe_internet_gateways,
|
||||
InternetGatewayIds=[gw_id])
|
||||
|
||||
@decorators.idempotent_id('f092b63d-9460-4d8f-ba8a-bcd380666033')
|
||||
def test_delete_attached_internet_gateway(self):
|
||||
data = self.client.create_internet_gateway()
|
||||
gw_id = data['InternetGateway']['InternetGatewayId']
|
||||
res_clean = self.addResourceCleanUp(
|
||||
self.client.delete_internet_gateway, InternetGatewayId=gw_id)
|
||||
self.assertEmpty(data['InternetGateway'].get('Attachments', []))
|
||||
|
||||
data = self.client.attach_internet_gateway(VpcId=self.vpc_id,
|
||||
InternetGatewayId=gw_id)
|
||||
|
||||
self.assertRaises('DependencyViolation',
|
||||
self.client.delete_internet_gateway,
|
||||
InternetGatewayId=gw_id)
|
||||
|
||||
data = self.client.detach_internet_gateway(VpcId=self.vpc_id,
|
||||
InternetGatewayId=gw_id)
|
||||
|
||||
data = self.client.delete_internet_gateway(InternetGatewayId=gw_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
|
||||
@decorators.idempotent_id('89700013-5753-4608-8245-4fc99fbb67ea')
|
||||
@testtools.skipUnless(CONF.aws.run_incompatible_tests,
|
||||
"Another error code returned - InvalidParameterValue")
|
||||
def test_attach_detach_invalid_internet_gateway(self):
|
||||
gw_id = "gw-1"
|
||||
self.assertRaises('InvalidInternetGatewayID.NotFound',
|
||||
self.client.attach_internet_gateway,
|
||||
VpcId=self.vpc_id, InternetGatewayId=gw_id)
|
||||
|
||||
self.assertRaises('InvalidInternetGatewayID.NotFound',
|
||||
self.client.detach_internet_gateway,
|
||||
VpcId=self.vpc_id, InternetGatewayId=gw_id)
|
||||
|
||||
@decorators.idempotent_id('e3e4d8c4-8f62-43e8-a24d-bfd292b4144c')
|
||||
def test_double_attach_internet_gateway(self):
|
||||
data = self.client.create_internet_gateway()
|
||||
gw_id = data['InternetGateway']['InternetGatewayId']
|
||||
res_clean = self.addResourceCleanUp(
|
||||
self.client.delete_internet_gateway, InternetGatewayId=gw_id)
|
||||
self.assertEmpty(data['InternetGateway'].get('Attachments', []))
|
||||
|
||||
data = self.client.attach_internet_gateway(VpcId=self.vpc_id,
|
||||
InternetGatewayId=gw_id)
|
||||
|
||||
self.assertRaises('Resource.AlreadyAssociated',
|
||||
self.client.attach_internet_gateway,
|
||||
VpcId=self.vpc_id, InternetGatewayId=gw_id)
|
||||
|
||||
data = self.client.detach_internet_gateway(VpcId=self.vpc_id,
|
||||
InternetGatewayId=gw_id)
|
||||
|
||||
data = self.client.delete_internet_gateway(InternetGatewayId=gw_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
|
||||
@decorators.idempotent_id('d8f3a488-a4ba-4ed5-998c-3dc6f43d6d9e')
|
||||
def test_attach_one_internet_gateway_to_two_vpcs(self):
|
||||
data = self.client.create_internet_gateway()
|
||||
gw_id = data['InternetGateway']['InternetGatewayId']
|
||||
res_clean = self.addResourceCleanUp(
|
||||
self.client.delete_internet_gateway, InternetGatewayId=gw_id)
|
||||
self.assertEmpty(data['InternetGateway'].get('Attachments', []))
|
||||
|
||||
data = self.client.attach_internet_gateway(VpcId=self.vpc_id,
|
||||
InternetGatewayId=gw_id)
|
||||
|
||||
self.assertRaises('Resource.AlreadyAssociated',
|
||||
self.client.attach_internet_gateway,
|
||||
VpcId=self.vpc_id_alt, InternetGatewayId=gw_id)
|
||||
|
||||
data = self.client.detach_internet_gateway(VpcId=self.vpc_id,
|
||||
InternetGatewayId=gw_id)
|
||||
|
||||
data = self.client.delete_internet_gateway(InternetGatewayId=gw_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
|
||||
@decorators.idempotent_id('b86f338c-613e-4cd7-9742-07c86864b0da')
|
||||
def test_describe_internet_gateways_base(self):
|
||||
data = self.client.create_internet_gateway()
|
||||
gw_id = data['InternetGateway']['InternetGatewayId']
|
||||
res_clean = self.addResourceCleanUp(
|
||||
self.client.delete_internet_gateway, InternetGatewayId=gw_id)
|
||||
self.assertEmpty(data['InternetGateway'].get('Attachments', []))
|
||||
|
||||
data = self.client.attach_internet_gateway(VpcId=self.vpc_id,
|
||||
InternetGatewayId=gw_id)
|
||||
self.addResourceCleanUp(self.client.detach_internet_gateway,
|
||||
VpcId=self.vpc_id,
|
||||
InternetGatewayId=gw_id)
|
||||
|
||||
time.sleep(2)
|
||||
# NOTE(andrey-mp): by real id
|
||||
data = self.client.describe_internet_gateways(
|
||||
InternetGatewayIds=[gw_id])
|
||||
self.assertEqual(1, len(data['InternetGateways']))
|
||||
|
||||
# NOTE(andrey-mp): by fake id
|
||||
self.assertRaises('InvalidInternetGatewayID.NotFound',
|
||||
self.client.describe_internet_gateways,
|
||||
InternetGatewayIds=['igw-0'])
|
||||
|
||||
data = self.client.detach_internet_gateway(VpcId=self.vpc_id,
|
||||
InternetGatewayId=gw_id)
|
||||
|
||||
data = self.client.delete_internet_gateway(InternetGatewayId=gw_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
|
||||
@decorators.idempotent_id('3f141c56-9ee6-46bf-9c14-0d922ed8a482')
|
||||
def test_describe_internet_gateways_filters(self):
|
||||
# NOTE(andrey-mp): by filter real vpc-id before creation
|
||||
data = self.client.describe_internet_gateways(
|
||||
Filters=[{'Name': 'attachment.vpc-id', 'Values': [self.vpc_id]}])
|
||||
self.assertEqual(0, len(data['InternetGateways']))
|
||||
|
||||
data = self.client.create_internet_gateway()
|
||||
gw_id = data['InternetGateway']['InternetGatewayId']
|
||||
res_clean = self.addResourceCleanUp(
|
||||
self.client.delete_internet_gateway, InternetGatewayId=gw_id)
|
||||
self.assertEmpty(data['InternetGateway'].get('Attachments', []))
|
||||
|
||||
data = self.client.attach_internet_gateway(VpcId=self.vpc_id,
|
||||
InternetGatewayId=gw_id)
|
||||
self.addResourceCleanUp(self.client.detach_internet_gateway,
|
||||
VpcId=self.vpc_id,
|
||||
InternetGatewayId=gw_id)
|
||||
|
||||
time.sleep(2)
|
||||
# NOTE(andrey-mp): by filter real vpc-id
|
||||
data = self.client.describe_internet_gateways(
|
||||
Filters=[{'Name': 'attachment.vpc-id', 'Values': [self.vpc_id]}])
|
||||
self.assertEqual(1, len(data['InternetGateways']))
|
||||
self.assertEqual(gw_id,
|
||||
data['InternetGateways'][0]['InternetGatewayId'])
|
||||
|
||||
# NOTE(andrey-mp): by filter fake vpc-id
|
||||
data = self.client.describe_internet_gateways(
|
||||
Filters=[{'Name': 'attachment.vpc-id', 'Values': ['vpc-0']}])
|
||||
self.assertEqual(0, len(data['InternetGateways']))
|
||||
|
||||
# NOTE(andrey-mp): by fake filter
|
||||
self.assertRaises('InvalidParameterValue',
|
||||
self.client.describe_internet_gateways,
|
||||
Filters=[{'Name': 'fake', 'Values': ['fake']}])
|
||||
|
||||
data = self.client.detach_internet_gateway(VpcId=self.vpc_id,
|
||||
InternetGatewayId=gw_id)
|
||||
|
||||
data = self.client.delete_internet_gateway(InternetGatewayId=gw_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
|
@ -1,149 +0,0 @@
|
|||
# Copyright 2014 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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.
|
||||
|
||||
from tempest.lib import decorators
|
||||
import testtools
|
||||
|
||||
from ec2api_tempest_plugin import base
|
||||
from ec2api_tempest_plugin import config
|
||||
|
||||
CONF = config.CONF
|
||||
|
||||
|
||||
class KeyPairTest(base.EC2TestCase):
|
||||
|
||||
@decorators.idempotent_id('15cfd866-d6bb-473a-9b8a-6420900a5ca3')
|
||||
def test_create_delete_key_pair(self):
|
||||
keyName = 'Test key'
|
||||
data = self.client.create_key_pair(KeyName=keyName)
|
||||
res_clean = self.addResourceCleanUp(self.client.delete_key_pair,
|
||||
KeyName=keyName)
|
||||
|
||||
self.assertEqual(keyName, data['KeyName'])
|
||||
self.assertIsNotNone(data.get('KeyFingerprint'))
|
||||
self.assertGreater(len(data['KeyFingerprint']), 0)
|
||||
self.assertGreater(len(data.get('KeyMaterial')), 0)
|
||||
|
||||
data = self.client.delete_key_pair(KeyName=keyName)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
|
||||
@decorators.idempotent_id('05478a51-1505-42a8-8c7d-4fd7e32c467e')
|
||||
def test_create_duplicate_key_pair(self):
|
||||
keyName = 'Test key'
|
||||
self.client.create_key_pair(KeyName=keyName)
|
||||
res_clean = self.addResourceCleanUp(self.client.delete_key_pair,
|
||||
KeyName=keyName)
|
||||
|
||||
self.assertRaises('InvalidKeyPair.Duplicate',
|
||||
self.client.create_key_pair,
|
||||
KeyName=keyName)
|
||||
|
||||
self.client.delete_key_pair(KeyName=keyName)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
|
||||
@decorators.idempotent_id('43d87b6e-6667-4d19-8c0b-e73901105bb7')
|
||||
def test_describe_key_pairs(self):
|
||||
keyName = 'Test key'
|
||||
data = self.client.create_key_pair(KeyName=keyName)
|
||||
res_clean = self.addResourceCleanUp(self.client.delete_key_pair,
|
||||
KeyName=keyName)
|
||||
self.assertIsNotNone(data.get('KeyFingerprint'))
|
||||
self.assertGreater(len(data['KeyFingerprint']), 0)
|
||||
fingerprint = data.get('KeyFingerprint')
|
||||
|
||||
data = self.client.describe_key_pairs(KeyNames=[keyName])
|
||||
self.assertEqual(1, len(data.get('KeyPairs')))
|
||||
data = data['KeyPairs'][0]
|
||||
self.assertEqual(keyName, data['KeyName'])
|
||||
self.assertIsNotNone(data.get('KeyFingerprint'))
|
||||
self.assertGreater(len(data['KeyFingerprint']), 0)
|
||||
self.assertIsNone(data.get('KeyMaterial'))
|
||||
|
||||
data = self.client.describe_key_pairs(
|
||||
Filters=[{'Name': 'key-name', 'Values': [keyName]}])
|
||||
self.assertEqual(1, len(data.get('KeyPairs')))
|
||||
self.assertEqual(keyName, data['KeyPairs'][0]['KeyName'])
|
||||
|
||||
data = self.client.describe_key_pairs(
|
||||
Filters=[{'Name': 'fingerprint', 'Values': [fingerprint]}])
|
||||
self.assertEqual(1, len(data.get('KeyPairs')))
|
||||
self.assertEqual(keyName, data['KeyPairs'][0]['KeyName'])
|
||||
|
||||
self.assertRaises('InvalidKeyPair.NotFound',
|
||||
self.client.describe_key_pairs,
|
||||
KeyNames=['fake key'])
|
||||
|
||||
data = self.client.delete_key_pair(KeyName=keyName)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
|
||||
self.assertRaises('InvalidKeyPair.NotFound',
|
||||
self.client.describe_key_pairs,
|
||||
KeyNames=[keyName])
|
||||
|
||||
# NOTE(andrey-mp): Amazon allows to delete absent key and returns 200
|
||||
self.client.delete_key_pair(KeyName=keyName)
|
||||
|
||||
@decorators.idempotent_id('0e51eec5-3f61-4d8a-89c9-8d098f381682')
|
||||
def test_import_empty_key_pair(self):
|
||||
keyName = 'Test key'
|
||||
publicKey = ''
|
||||
|
||||
def _rollback(fn_data):
|
||||
self.client.delete_key_pair(KeyName=keyName)
|
||||
|
||||
self.assertRaises('MissingParameter',
|
||||
self.client.import_key_pair,
|
||||
rollback_fn=_rollback,
|
||||
KeyName=keyName, PublicKeyMaterial=publicKey)
|
||||
|
||||
@decorators.idempotent_id('478c17e6-b7ca-4115-bee2-be279bdd0f65')
|
||||
@testtools.skipUnless(CONF.aws.run_incompatible_tests,
|
||||
"Different error code")
|
||||
def test_import_invalid_key_pair(self):
|
||||
keyName = 'Test key'
|
||||
publicKey = 'ssh-rsa JUNK test@ubuntu'
|
||||
|
||||
def _rollback():
|
||||
self.client.delete_key_pair(KeyName=keyName)
|
||||
|
||||
self.assertRaises('InvalidKey.Format',
|
||||
self.client.import_key_pair,
|
||||
rollback_fn=_rollback,
|
||||
KeyName=keyName, PublicKeyMaterial=publicKey)
|
||||
|
||||
@decorators.idempotent_id('eda525d6-144b-4840-b6ba-e18d93e3589f')
|
||||
def test_import_key_pair(self):
|
||||
keyName = 'Test key'
|
||||
publicKey = ("ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCs"
|
||||
"Ne3/1ILNCqFyfYWDeTKLD6jEXC2OQHLmietMWW+/vd"
|
||||
"aZq7KZEwO0jhglaFjU1mpqq4Gz5RX156sCTNM9vRbw"
|
||||
"KAxfsdF9laBYVsex3m3Wmui3uYrKyumsoJn2g9GNnG1P"
|
||||
"I1mrVjZ61i0GY3khna+wzlTpCCmy5HNlrmbj3XLqBUpip"
|
||||
"TOXmsnr4sChzC53KCd8LXuwc1i/CZPvF+3XipvAgFSE53pCt"
|
||||
"LOeB1kYMOBaiUPLQTWXR3JpckqFIQwhIH0zoHlJvZE8hh90"
|
||||
"XcPojYN56tI0OlrGqojbediJYD0rUsJu4weZpbn8vilb3JuDY+jws"
|
||||
"snSA8wzBx3A/8y9Pp1B test@ubuntu")
|
||||
data = self.client.import_key_pair(KeyName=keyName,
|
||||
PublicKeyMaterial=publicKey)
|
||||
res_clean = self.addResourceCleanUp(self.client.delete_key_pair,
|
||||
KeyName=keyName)
|
||||
|
||||
self.assertEqual(keyName, data['KeyName'])
|
||||
self.assertIsNotNone(data.get('KeyFingerprint'))
|
||||
self.assertGreater(len(data['KeyFingerprint']), 0)
|
||||
self.assertIsNone(data.get('KeyMaterial'))
|
||||
|
||||
self.client.delete_key_pair(KeyName=keyName)
|
||||
self.cancelResourceCleanUp(res_clean)
|
|
@ -1,582 +0,0 @@
|
|||
# Copyright 2014 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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 time
|
||||
|
||||
import botocore.exceptions
|
||||
from oslo_log import log
|
||||
from tempest.lib.common.utils import data_utils
|
||||
from tempest.lib import decorators
|
||||
import testtools
|
||||
|
||||
from ec2api_tempest_plugin import base
|
||||
from ec2api_tempest_plugin import config
|
||||
|
||||
CONF = config.CONF
|
||||
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
|
||||
class NetworkInterfaceTest(base.EC2TestCase):
|
||||
|
||||
VPC_CIDR = '10.7.0.0/20'
|
||||
vpc_id = None
|
||||
SUBNET_CIDR = '10.7.0.0/28'
|
||||
subnet_id = None
|
||||
|
||||
@classmethod
|
||||
@base.safe_setup
|
||||
def setUpClass(cls):
|
||||
super(NetworkInterfaceTest, cls).setUpClass()
|
||||
if not base.TesterStateHolder().get_vpc_enabled():
|
||||
raise cls.skipException('VPC is disabled')
|
||||
|
||||
data = cls.client.create_vpc(CidrBlock=cls.VPC_CIDR)
|
||||
cls.vpc_id = data['Vpc']['VpcId']
|
||||
cls.addResourceCleanUpStatic(cls.client.delete_vpc, VpcId=cls.vpc_id)
|
||||
cls.get_vpc_waiter().wait_available(cls.vpc_id)
|
||||
|
||||
aws_zone = CONF.aws.aws_zone
|
||||
data = cls.client.create_subnet(VpcId=cls.vpc_id,
|
||||
CidrBlock=cls.SUBNET_CIDR,
|
||||
AvailabilityZone=aws_zone)
|
||||
cls.subnet_id = data['Subnet']['SubnetId']
|
||||
cls.addResourceCleanUpStatic(cls.client.delete_subnet,
|
||||
SubnetId=cls.subnet_id)
|
||||
cls.get_subnet_waiter().wait_available(cls.subnet_id)
|
||||
|
||||
def _wait_assignment(self, ni_id, data):
|
||||
# NOTE(andrey-mp): Amazon don't do it quickly and there is no way
|
||||
# to wait this request
|
||||
time.sleep(5)
|
||||
|
||||
@decorators.idempotent_id('d03f49b1-a77e-439b-96e2-5e152b968863')
|
||||
def test_delete_subnet_with_network_interface(self):
|
||||
data = self.client.create_subnet(VpcId=self.vpc_id,
|
||||
CidrBlock='10.7.1.0/28')
|
||||
subnet_id = data['Subnet']['SubnetId']
|
||||
res_clean_subnet = self.addResourceCleanUp(self.client.delete_subnet,
|
||||
SubnetId=subnet_id)
|
||||
self.get_subnet_waiter().wait_available(subnet_id)
|
||||
|
||||
data = self.client.create_network_interface(SubnetId=subnet_id)
|
||||
ni_id = data['NetworkInterface']['NetworkInterfaceId']
|
||||
res_clean_ni = self.addResourceCleanUp(
|
||||
self.client.delete_network_interface, NetworkInterfaceId=ni_id)
|
||||
self.get_network_interface_waiter().wait_available(ni_id)
|
||||
time.sleep(2)
|
||||
|
||||
self.assertRaises('DependencyViolation',
|
||||
self.client.delete_subnet,
|
||||
SubnetId=subnet_id)
|
||||
|
||||
self.client.delete_network_interface(NetworkInterfaceId=ni_id)
|
||||
self.cancelResourceCleanUp(res_clean_ni)
|
||||
self.get_network_interface_waiter().wait_delete(ni_id)
|
||||
|
||||
self.client.delete_subnet(SubnetId=subnet_id)
|
||||
self.cancelResourceCleanUp(res_clean_subnet)
|
||||
self.get_subnet_waiter().wait_delete(subnet_id)
|
||||
|
||||
@decorators.idempotent_id('e19e450d-5c24-47b1-9814-4a65a78e5a31')
|
||||
def test_create_network_interface(self):
|
||||
desc = data_utils.rand_name('ni')
|
||||
data = self.client.create_network_interface(SubnetId=self.subnet_id,
|
||||
Description=desc)
|
||||
ni_id = data['NetworkInterface']['NetworkInterfaceId']
|
||||
res_clean = self.addResourceCleanUp(
|
||||
self.client.delete_network_interface, NetworkInterfaceId=ni_id)
|
||||
ni = data['NetworkInterface']
|
||||
self.assertEqual(self.vpc_id, ni['VpcId'])
|
||||
self.assertEqual(self.subnet_id, ni['SubnetId'])
|
||||
self.assertEqual(desc, ni['Description'])
|
||||
|
||||
self.assertNotEmpty(ni.get('Groups'))
|
||||
self.assertEqual('default', ni['Groups'][0]['GroupName'])
|
||||
|
||||
address = ni.get('PrivateIpAddress')
|
||||
self.assertIsNotNone(address)
|
||||
addresses = ni.get('PrivateIpAddresses')
|
||||
self.assertIsNotNone(addresses)
|
||||
self.assertEqual(1, len(addresses))
|
||||
self.assertTrue(addresses[0]['Primary'])
|
||||
self.assertEqual(address, addresses[0]['PrivateIpAddress'])
|
||||
|
||||
self.assertIsNotNone(ni.get('MacAddress'))
|
||||
self.assertIsNotNone(ni.get('OwnerId'))
|
||||
self.assertIsNotNone(ni.get('RequesterManaged'))
|
||||
self.assertIsNotNone(ni.get('SourceDestCheck'))
|
||||
|
||||
self.get_network_interface_waiter().wait_available(ni_id)
|
||||
|
||||
self.client.delete_network_interface(NetworkInterfaceId=ni_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
self.get_network_interface_waiter().wait_delete(ni_id)
|
||||
|
||||
self.assertRaises('InvalidNetworkInterfaceID.NotFound',
|
||||
self.client.describe_network_interfaces,
|
||||
NetworkInterfaceIds=[ni_id])
|
||||
|
||||
# TODO(andrey-mp): add creation with addresses
|
||||
|
||||
@decorators.idempotent_id('61e16648-7736-4647-b618-27d3f4f0c9c6')
|
||||
def test_create_max_network_interface(self):
|
||||
# NOTE(andrey-mp): wait some time while all ports will be deleted
|
||||
# for this subnet(that are deleting after previous test)
|
||||
time.sleep(5)
|
||||
|
||||
data = self.client.describe_subnets(SubnetIds=[self.subnet_id])
|
||||
count_before = data['Subnets'][0]['AvailableIpAddressCount']
|
||||
addresses = []
|
||||
while True:
|
||||
try:
|
||||
data = self.client.create_network_interface(
|
||||
SubnetId=self.subnet_id)
|
||||
except botocore.exceptions.ClientError as e:
|
||||
error_code = e.response['Error']['Code']
|
||||
self.assertEqual('InsufficientFreeAddressesInSubnet',
|
||||
error_code)
|
||||
break
|
||||
ni_id = data['NetworkInterface']['NetworkInterfaceId']
|
||||
res_clean = self.addResourceCleanUp(
|
||||
self.client.delete_network_interface,
|
||||
NetworkInterfaceId=ni_id)
|
||||
addresses.append((ni_id, res_clean))
|
||||
|
||||
data = self.client.describe_subnets(SubnetIds=[self.subnet_id])
|
||||
count_after = data['Subnets'][0]['AvailableIpAddressCount']
|
||||
# NOTE(andrey-mp): This is strange but Amazon can't create last NI
|
||||
# and Openstack can
|
||||
self.assertIn(count_after, [0, 1])
|
||||
self.assertEqual(len(addresses), count_before - count_after)
|
||||
|
||||
for addr in addresses:
|
||||
self.client.delete_network_interface(NetworkInterfaceId=addr[0])
|
||||
self.cancelResourceCleanUp(addr[1])
|
||||
self.get_network_interface_waiter().wait_delete(addr[0])
|
||||
|
||||
@decorators.idempotent_id('8c174e5f-e377-4bf2-9315-b868a8199c17')
|
||||
def test_unassign_primary_addresses(self):
|
||||
data = self.client.create_network_interface(SubnetId=self.subnet_id)
|
||||
ni_id = data['NetworkInterface']['NetworkInterfaceId']
|
||||
res_clean = self.addResourceCleanUp(
|
||||
self.client.delete_network_interface, NetworkInterfaceId=ni_id)
|
||||
primary_address = data['NetworkInterface'].get('PrivateIpAddress')
|
||||
self.get_network_interface_waiter().wait_available(ni_id)
|
||||
|
||||
self.assertRaises('InvalidParameterValue',
|
||||
self.client.unassign_private_ip_addresses,
|
||||
NetworkInterfaceId=ni_id,
|
||||
PrivateIpAddresses=[primary_address])
|
||||
|
||||
self.client.delete_network_interface(NetworkInterfaceId=ni_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
self.get_network_interface_waiter().wait_delete(ni_id)
|
||||
|
||||
@decorators.idempotent_id('de0d0375-d99a-476c-939a-0e15c4e431a8')
|
||||
def test_assign_unassign_private_addresses_by_count(self):
|
||||
data = self.client.describe_subnets(SubnetIds=[self.subnet_id])
|
||||
count = data['Subnets'][0]['AvailableIpAddressCount']
|
||||
data = self.client.create_network_interface(SubnetId=self.subnet_id)
|
||||
ni_id = data['NetworkInterface']['NetworkInterfaceId']
|
||||
res_clean = self.addResourceCleanUp(
|
||||
self.client.delete_network_interface, NetworkInterfaceId=ni_id)
|
||||
self.get_network_interface_waiter().wait_available(ni_id)
|
||||
|
||||
data = self.client.assign_private_ip_addresses(
|
||||
NetworkInterfaceId=ni_id,
|
||||
SecondaryPrivateIpAddressCount=2)
|
||||
self._wait_assignment(ni_id, data)
|
||||
|
||||
data = self.client.describe_subnets(SubnetIds=[self.subnet_id])
|
||||
count_after = data['Subnets'][0]['AvailableIpAddressCount']
|
||||
self.assertEqual(count - 3, count_after)
|
||||
|
||||
data = self.client.describe_network_interfaces(
|
||||
NetworkInterfaceIds=[ni_id])
|
||||
|
||||
addresses = []
|
||||
for addr in data['NetworkInterfaces'][0]['PrivateIpAddresses']:
|
||||
if not addr['Primary']:
|
||||
addresses.append(addr['PrivateIpAddress'])
|
||||
self.assertEqual(2, len(addresses))
|
||||
|
||||
data = self.client.unassign_private_ip_addresses(
|
||||
NetworkInterfaceId=ni_id,
|
||||
PrivateIpAddresses=addresses)
|
||||
self._wait_assignment(ni_id, data)
|
||||
|
||||
data = self.client.describe_subnets(SubnetIds=[self.subnet_id])
|
||||
count_after = data['Subnets'][0]['AvailableIpAddressCount']
|
||||
self.assertEqual(count - 1, count_after)
|
||||
|
||||
self.client.delete_network_interface(NetworkInterfaceId=ni_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
self.get_network_interface_waiter().wait_delete(ni_id)
|
||||
|
||||
@decorators.idempotent_id('5d7bda42-d23e-4cbf-9e66-8ca052ac28ff')
|
||||
def test_assign_unassign_private_addresses_by_addresses(self):
|
||||
data = self.client.describe_subnets(SubnetIds=[self.subnet_id])
|
||||
count = data['Subnets'][0]['AvailableIpAddressCount']
|
||||
data = self.client.create_network_interface(SubnetId=self.subnet_id)
|
||||
ni_id = data['NetworkInterface']['NetworkInterfaceId']
|
||||
res_clean = self.addResourceCleanUp(
|
||||
self.client.delete_network_interface, NetworkInterfaceId=ni_id)
|
||||
self.get_network_interface_waiter().wait_available(ni_id)
|
||||
|
||||
ni = self.client.describe_network_interfaces(
|
||||
NetworkInterfaceIds=[ni_id])['NetworkInterfaces']
|
||||
ni_addr = ni[0]['PrivateIpAddresses'][0]['PrivateIpAddress']
|
||||
|
||||
# add two more addresses to interface.
|
||||
# check that they does not equal to current.
|
||||
addresses = []
|
||||
for i in range(10, 13):
|
||||
addr = '10.7.0.%d' % i
|
||||
if addr != ni_addr:
|
||||
addresses.append(addr)
|
||||
if len(addresses) >= 2:
|
||||
break
|
||||
data = self.client.assign_private_ip_addresses(
|
||||
NetworkInterfaceId=ni_id,
|
||||
PrivateIpAddresses=addresses)
|
||||
self._wait_assignment(ni_id, data)
|
||||
|
||||
data = self.client.describe_subnets(SubnetIds=[self.subnet_id])
|
||||
count_after = data['Subnets'][0]['AvailableIpAddressCount']
|
||||
# NOTE(Alex): Amazon misses 1 IP address by some reason.
|
||||
self.assertIn(count_after, [count - 3, count - 4])
|
||||
|
||||
data = self.client.describe_network_interfaces(
|
||||
NetworkInterfaceIds=[ni_id])
|
||||
|
||||
assigned_addresses = []
|
||||
for addr in data['NetworkInterfaces'][0]['PrivateIpAddresses']:
|
||||
if not addr['Primary']:
|
||||
self.assertIn(addr['PrivateIpAddress'], addresses)
|
||||
assigned_addresses.append(addr['PrivateIpAddress'])
|
||||
self.assertEqual(2, len(assigned_addresses))
|
||||
|
||||
data = self.client.unassign_private_ip_addresses(
|
||||
NetworkInterfaceId=ni_id,
|
||||
PrivateIpAddresses=addresses)
|
||||
self._wait_assignment(ni_id, data)
|
||||
|
||||
data = self.client.describe_subnets(SubnetIds=[self.subnet_id])
|
||||
count_after = data['Subnets'][0]['AvailableIpAddressCount']
|
||||
self.assertIn(count_after, [count - 1, count - 2])
|
||||
|
||||
self.client.delete_network_interface(NetworkInterfaceId=ni_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
self.get_network_interface_waiter().wait_delete(ni_id)
|
||||
|
||||
@decorators.idempotent_id('0c514bb4-5800-4db0-9032-0aa3ab998612')
|
||||
@testtools.skipUnless(CONF.aws.image_id, "image id is not defined")
|
||||
def test_attach_network_interface(self):
|
||||
data = self.client.create_network_interface(SubnetId=self.subnet_id)
|
||||
ni_id = data['NetworkInterface']['NetworkInterfaceId']
|
||||
self.addResourceCleanUp(self.client.delete_network_interface,
|
||||
NetworkInterfaceId=ni_id)
|
||||
ni = data['NetworkInterface']
|
||||
address = ni.get('PrivateIpAddress')
|
||||
self.assertIsNotNone(address)
|
||||
self.get_network_interface_waiter().wait_available(ni_id)
|
||||
|
||||
instance_id = self.run_instance(SubnetId=self.subnet_id)
|
||||
|
||||
# NOTE(andrey-mp): Amazon can't attach to device index = 0
|
||||
kwargs = {
|
||||
'DeviceIndex': 0,
|
||||
'InstanceId': instance_id,
|
||||
'NetworkInterfaceId': ni_id
|
||||
}
|
||||
self.assertRaises('InvalidParameterValue',
|
||||
self.client.attach_network_interface,
|
||||
**kwargs)
|
||||
|
||||
kwargs = {
|
||||
'DeviceIndex': 2,
|
||||
'InstanceId': instance_id,
|
||||
'NetworkInterfaceId': ni_id
|
||||
}
|
||||
data = self.client.attach_network_interface(*[], **kwargs)
|
||||
attachment_id = data['AttachmentId']
|
||||
|
||||
instance = self.get_instance(instance_id)
|
||||
nis = instance.get('NetworkInterfaces', [])
|
||||
self.assertEqual(2, len(nis))
|
||||
ids = [nis[0]['Attachment']['AttachmentId'],
|
||||
nis[1]['Attachment']['AttachmentId']]
|
||||
self.assertIn(attachment_id, ids)
|
||||
|
||||
self.assertRaises('InvalidParameterValue',
|
||||
self.client.delete_network_interface,
|
||||
NetworkInterfaceId=ni_id)
|
||||
|
||||
self.client.detach_network_interface(AttachmentId=attachment_id)
|
||||
|
||||
self.client.terminate_instances(InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_delete(instance_id)
|
||||
|
||||
@decorators.idempotent_id('381c9995-bc83-4e7e-b716-25a451660ace')
|
||||
@testtools.skipUnless(CONF.aws.image_id, "image id is not defined")
|
||||
def test_network_interfaces_are_not_deleted_on_termination(self):
|
||||
instance_id = self.run_instance(SubnetId=self.subnet_id)
|
||||
|
||||
instance = self.get_instance(instance_id)
|
||||
nis = instance.get('NetworkInterfaces', [])
|
||||
self.assertEqual(1, len(nis))
|
||||
self.assertTrue(nis[0]['Attachment']['DeleteOnTermination'])
|
||||
ni_id = nis[0]['NetworkInterfaceId']
|
||||
attachment_id = nis[0]['Attachment']['AttachmentId']
|
||||
|
||||
kwargs = {
|
||||
'NetworkInterfaceId': ni_id,
|
||||
'Attachment': {
|
||||
'AttachmentId': attachment_id,
|
||||
'DeleteOnTermination': False,
|
||||
}
|
||||
}
|
||||
self.client.modify_network_interface_attribute(*[], **kwargs)
|
||||
clean_ni = self.addResourceCleanUp(
|
||||
self.client.delete_network_interface, NetworkInterfaceId=ni_id)
|
||||
|
||||
data = self.client.create_network_interface(SubnetId=self.subnet_id)
|
||||
ni_id2 = data['NetworkInterface']['NetworkInterfaceId']
|
||||
clean_ni2 = self.addResourceCleanUp(
|
||||
self.client.delete_network_interface, NetworkInterfaceId=ni_id2)
|
||||
self.get_network_interface_waiter().wait_available(ni_id2)
|
||||
kwargs = {
|
||||
'DeviceIndex': 2,
|
||||
'InstanceId': instance_id,
|
||||
'NetworkInterfaceId': ni_id2
|
||||
}
|
||||
data = self.client.attach_network_interface(*[], **kwargs)
|
||||
attachment_id = data['AttachmentId']
|
||||
|
||||
instance = self.get_instance(instance_id)
|
||||
nis = instance.get('NetworkInterfaces', [])
|
||||
self.assertEqual(2, len(nis))
|
||||
ni = nis[0]
|
||||
if ni['Attachment']['AttachmentId'] != attachment_id:
|
||||
ni = nis[1]
|
||||
self.assertEqual(attachment_id, ni['Attachment']['AttachmentId'])
|
||||
self.assertFalse(ni['Attachment']['DeleteOnTermination'])
|
||||
|
||||
self.client.terminate_instances(InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_delete(instance_id)
|
||||
|
||||
self.get_network_interface_waiter().wait_available(ni_id)
|
||||
self.get_network_interface_waiter().wait_available(ni_id2)
|
||||
|
||||
self.client.delete_network_interface(NetworkInterfaceId=ni_id)
|
||||
self.cancelResourceCleanUp(clean_ni)
|
||||
self.get_network_interface_waiter().wait_delete(ni_id)
|
||||
|
||||
self.client.delete_network_interface(NetworkInterfaceId=ni_id2)
|
||||
self.cancelResourceCleanUp(clean_ni2)
|
||||
self.get_network_interface_waiter().wait_delete(ni_id2)
|
||||
|
||||
@decorators.idempotent_id('de910bc7-008a-40c2-b4b2-4587a489fc1c')
|
||||
@testtools.skipUnless(CONF.aws.image_id, "image id is not defined")
|
||||
def test_network_interfaces_are_deleted_on_termination(self):
|
||||
instance_id = self.run_instance(SubnetId=self.subnet_id)
|
||||
|
||||
instance = self.get_instance(instance_id)
|
||||
nis = instance.get('NetworkInterfaces', [])
|
||||
self.assertEqual(1, len(nis))
|
||||
self.assertTrue(nis[0]['Attachment']['DeleteOnTermination'])
|
||||
ni_id = nis[0]['NetworkInterfaceId']
|
||||
|
||||
data = self.client.create_network_interface(SubnetId=self.subnet_id)
|
||||
ni_id2 = data['NetworkInterface']['NetworkInterfaceId']
|
||||
self.addResourceCleanUp(self.client.delete_network_interface,
|
||||
NetworkInterfaceId=ni_id2)
|
||||
self.get_network_interface_waiter().wait_available(ni_id2)
|
||||
kwargs = {
|
||||
'DeviceIndex': 2,
|
||||
'InstanceId': instance_id,
|
||||
'NetworkInterfaceId': ni_id2
|
||||
}
|
||||
data = self.client.attach_network_interface(*[], **kwargs)
|
||||
attachment_id = data['AttachmentId']
|
||||
|
||||
kwargs = {
|
||||
'NetworkInterfaceId': ni_id2,
|
||||
'Attachment': {
|
||||
'AttachmentId': attachment_id,
|
||||
'DeleteOnTermination': True,
|
||||
}
|
||||
}
|
||||
self.client.modify_network_interface_attribute(*[], **kwargs)
|
||||
|
||||
self.client.terminate_instances(InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_delete(instance_id)
|
||||
|
||||
self.get_network_interface_waiter().wait_delete(ni_id)
|
||||
self.get_network_interface_waiter().wait_delete(ni_id2)
|
||||
|
||||
@decorators.idempotent_id('028eb864-59e9-4ed6-a062-9d5de9eba652')
|
||||
def test_network_interface_attribute_description(self):
|
||||
desc = data_utils.rand_name('ni')
|
||||
data = self.client.create_network_interface(
|
||||
SubnetId=self.subnet_id, Description=desc)
|
||||
ni_id = data['NetworkInterface']['NetworkInterfaceId']
|
||||
res_clean = self.addResourceCleanUp(
|
||||
self.client.delete_network_interface, NetworkInterfaceId=ni_id)
|
||||
self.get_network_interface_waiter().wait_available(ni_id)
|
||||
|
||||
data = self.client.describe_network_interface_attribute(
|
||||
NetworkInterfaceId=ni_id, Attribute='description')
|
||||
self.assertEqual(desc, data['Description']['Value'])
|
||||
|
||||
new_desc = data_utils.rand_name('new-ni')
|
||||
self.client.modify_network_interface_attribute(
|
||||
NetworkInterfaceId=ni_id, Description={'Value': new_desc})
|
||||
|
||||
data = self.client.describe_network_interface_attribute(
|
||||
NetworkInterfaceId=ni_id, Attribute='description')
|
||||
self.assertEqual(new_desc, data['Description']['Value'])
|
||||
|
||||
self.client.delete_network_interface(NetworkInterfaceId=ni_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
self.get_network_interface_waiter().wait_delete(ni_id)
|
||||
|
||||
@decorators.idempotent_id('9428b5e6-42f2-495f-a535-df53d1fcf4af')
|
||||
def test_network_interface_attribute_source_dest_check(self):
|
||||
data = self.client.create_network_interface(SubnetId=self.subnet_id)
|
||||
ni_id = data['NetworkInterface']['NetworkInterfaceId']
|
||||
res_clean = self.addResourceCleanUp(
|
||||
self.client.delete_network_interface, NetworkInterfaceId=ni_id)
|
||||
self.get_network_interface_waiter().wait_available(ni_id)
|
||||
|
||||
self.client.modify_network_interface_attribute(
|
||||
NetworkInterfaceId=ni_id, SourceDestCheck={'Value': False})
|
||||
|
||||
data = self.client.describe_network_interface_attribute(
|
||||
NetworkInterfaceId=ni_id, Attribute='sourceDestCheck')
|
||||
self.assertFalse(data['SourceDestCheck']['Value'])
|
||||
|
||||
# NOTE(andrey-mp): ResetNetworkInterfaceAttribute had inadequate json
|
||||
# scheme in botocore and doesn't work against Amazon.
|
||||
|
||||
self.client.modify_network_interface_attribute(
|
||||
NetworkInterfaceId=ni_id, SourceDestCheck={'Value': True})
|
||||
|
||||
data = self.client.describe_network_interface_attribute(
|
||||
NetworkInterfaceId=ni_id, Attribute='sourceDestCheck')
|
||||
self.assertEqual(True, data['SourceDestCheck']['Value'])
|
||||
|
||||
self.client.delete_network_interface(NetworkInterfaceId=ni_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
self.get_network_interface_waiter().wait_delete(ni_id)
|
||||
|
||||
@decorators.idempotent_id('19d25f59-5b32-4314-b4da-7c8f679b7a96')
|
||||
@testtools.skipUnless(CONF.aws.image_id, "image id is not defined")
|
||||
def test_network_interface_attribute_attachment(self):
|
||||
instance_id = self.run_instance(SubnetId=self.subnet_id)
|
||||
|
||||
instance = self.get_instance(instance_id)
|
||||
nis = instance.get('NetworkInterfaces', [])
|
||||
self.assertEqual(1, len(nis))
|
||||
self.assertTrue(nis[0]['Attachment']['DeleteOnTermination'])
|
||||
ni_id = nis[0]['NetworkInterfaceId']
|
||||
|
||||
data = self.client.describe_network_interface_attribute(
|
||||
NetworkInterfaceId=ni_id, Attribute='attachment')
|
||||
self.assertIn('Attachment', data)
|
||||
self.assertTrue(data['Attachment'].get('AttachmentId'))
|
||||
self.assertTrue(data['Attachment'].get('DeleteOnTermination'))
|
||||
self.assertEqual(0, data['Attachment'].get('DeviceIndex'))
|
||||
self.assertEqual(instance_id, data['Attachment'].get('InstanceId'))
|
||||
self.assertEqual('attached', data['Attachment'].get('Status'))
|
||||
|
||||
self.client.terminate_instances(InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_delete(instance_id)
|
||||
|
||||
@decorators.idempotent_id('74967cd0-155f-4cfe-994e-2c6803dad04c')
|
||||
def test_network_interface_attribute_empty_attachment(self):
|
||||
data = self.client.create_network_interface(SubnetId=self.subnet_id)
|
||||
ni_id = data['NetworkInterface']['NetworkInterfaceId']
|
||||
res_clean = self.addResourceCleanUp(
|
||||
self.client.delete_network_interface, NetworkInterfaceId=ni_id)
|
||||
self.get_network_interface_waiter().wait_available(ni_id)
|
||||
|
||||
data = self.client.describe_network_interface_attribute(
|
||||
NetworkInterfaceId=ni_id, Attribute='attachment')
|
||||
self.assertNotIn('Attachment', data)
|
||||
|
||||
self.client.delete_network_interface(NetworkInterfaceId=ni_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
self.get_network_interface_waiter().wait_delete(ni_id)
|
||||
|
||||
@decorators.idempotent_id('a55f1169-d302-4166-b74e-e84a0d79129c')
|
||||
def test_network_interface_attribute_group_set(self):
|
||||
data = self.client.create_network_interface(SubnetId=self.subnet_id)
|
||||
ni_id = data['NetworkInterface']['NetworkInterfaceId']
|
||||
res_clean = self.addResourceCleanUp(
|
||||
self.client.delete_network_interface, NetworkInterfaceId=ni_id)
|
||||
self.get_network_interface_waiter().wait_available(ni_id)
|
||||
|
||||
data = self.client.describe_network_interface_attribute(
|
||||
NetworkInterfaceId=ni_id, Attribute='groupSet')
|
||||
self.assertIn('Groups', data)
|
||||
self.assertEqual(1, len(data['Groups']))
|
||||
self.assertEqual('default', data['Groups'][0]['GroupName'])
|
||||
|
||||
self.client.delete_network_interface(NetworkInterfaceId=ni_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
self.get_network_interface_waiter().wait_delete(ni_id)
|
||||
|
||||
@decorators.idempotent_id('7832976f-27cb-405e-ab05-466b102d86f8')
|
||||
def test_instance_attributes_negative(self):
|
||||
data = self.client.create_network_interface(SubnetId=self.subnet_id)
|
||||
ni_id = data['NetworkInterface']['NetworkInterfaceId']
|
||||
res_clean = self.addResourceCleanUp(
|
||||
self.client.delete_network_interface, NetworkInterfaceId=ni_id)
|
||||
self.get_network_interface_waiter().wait_available(ni_id)
|
||||
|
||||
self.assertRaises('InvalidParameterCombination',
|
||||
self.client.describe_network_interface_attribute,
|
||||
NetworkInterfaceId=ni_id)
|
||||
self.assertRaises('InvalidParameterValue',
|
||||
self.client.describe_network_interface_attribute,
|
||||
NetworkInterfaceId=ni_id, Attribute='fake')
|
||||
self.assertRaises('InvalidNetworkInterfaceID.NotFound',
|
||||
self.client.describe_network_interface_attribute,
|
||||
NetworkInterfaceId='eni-0', Attribute='description')
|
||||
|
||||
self.assertRaises('InvalidParameterCombination',
|
||||
self.client.modify_network_interface_attribute,
|
||||
NetworkInterfaceId=ni_id)
|
||||
self.assertRaises('MissingParameter',
|
||||
self.client.modify_network_interface_attribute,
|
||||
NetworkInterfaceId=ni_id,
|
||||
Attachment={'AttachmentId': 'fake'})
|
||||
self.assertRaises('InvalidAttachmentID.NotFound',
|
||||
self.client.modify_network_interface_attribute,
|
||||
NetworkInterfaceId=ni_id,
|
||||
Attachment={'AttachmentId': 'eni-attach-0',
|
||||
'DeleteOnTermination': True})
|
||||
self.assertRaises('InvalidGroup.NotFound',
|
||||
self.client.modify_network_interface_attribute,
|
||||
NetworkInterfaceId=ni_id, Groups=['sg-0'])
|
||||
self.assertRaises('InvalidParameterCombination',
|
||||
self.client.modify_network_interface_attribute,
|
||||
NetworkInterfaceId=ni_id, Description={})
|
||||
|
||||
self.client.delete_network_interface(NetworkInterfaceId=ni_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
self.get_network_interface_waiter().wait_delete(ni_id)
|
|
@ -1,47 +0,0 @@
|
|||
# Copyright 2014 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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.
|
||||
|
||||
from tempest.lib import decorators
|
||||
|
||||
from ec2api_tempest_plugin import base
|
||||
from ec2api_tempest_plugin import config
|
||||
|
||||
CONF = config.CONF
|
||||
|
||||
|
||||
class RegionTest(base.EC2TestCase):
|
||||
|
||||
@decorators.idempotent_id('f303e87e-4e5f-4110-a5da-5f690acb44ba')
|
||||
def test_describe_regions(self):
|
||||
data = self.client.describe_regions()
|
||||
self.assertNotEmpty(data['Regions'])
|
||||
|
||||
region = CONF.aws.aws_region
|
||||
if not region:
|
||||
return
|
||||
|
||||
regions = [r['RegionName'] for r in data['Regions']]
|
||||
self.assertIn(region, regions)
|
||||
|
||||
@decorators.idempotent_id('be38f383-4637-4581-bb62-b47c1463f0a1')
|
||||
def test_describe_zones(self):
|
||||
data = self.client.describe_availability_zones()
|
||||
self.assertNotEmpty(data['AvailabilityZones'])
|
||||
|
||||
region = CONF.aws.aws_region
|
||||
if not region:
|
||||
return
|
||||
|
||||
# TODO(andrey-mp): add checking of other fields of returned data
|
|
@ -1,338 +0,0 @@
|
|||
# Copyright 2014 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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.
|
||||
|
||||
from oslo_log import log
|
||||
from tempest.lib import decorators
|
||||
|
||||
from ec2api_tempest_plugin import base
|
||||
from ec2api_tempest_plugin import config
|
||||
|
||||
CONF = config.CONF
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
|
||||
class RouteTest(base.EC2TestCase):
|
||||
|
||||
VPC_CIDR = '10.14.0.0/20'
|
||||
SUBNET_CIDR = '10.14.0.0/24'
|
||||
vpc_id = None
|
||||
|
||||
@classmethod
|
||||
@base.safe_setup
|
||||
def setUpClass(cls):
|
||||
super(RouteTest, cls).setUpClass()
|
||||
if not base.TesterStateHolder().get_vpc_enabled():
|
||||
raise cls.skipException('VPC is disabled')
|
||||
|
||||
data = cls.client.create_vpc(CidrBlock=cls.VPC_CIDR)
|
||||
cls.vpc_id = data['Vpc']['VpcId']
|
||||
cls.addResourceCleanUpStatic(cls.client.delete_vpc, VpcId=cls.vpc_id)
|
||||
cls.get_vpc_waiter().wait_available(cls.vpc_id)
|
||||
|
||||
@decorators.idempotent_id('69c04d14-5603-4a98-9331-739821b98b10')
|
||||
def test_create_delete_route_table(self):
|
||||
data = self.client.create_route_table(VpcId=self.vpc_id)
|
||||
rt_id = data['RouteTable']['RouteTableId']
|
||||
res_clean = self.addResourceCleanUp(self.client.delete_route_table,
|
||||
RouteTableId=rt_id)
|
||||
rt = data['RouteTable']
|
||||
self.assertEqual(self.vpc_id, rt['VpcId'])
|
||||
self.assertEqual(1, len(rt['Routes']))
|
||||
route = rt['Routes'][0]
|
||||
self.assertEqual(self.VPC_CIDR, route['DestinationCidrBlock'])
|
||||
self.assertEqual('active', route['State'])
|
||||
|
||||
data = self.client.delete_route_table(RouteTableId=rt_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
|
||||
self.assertRaises('InvalidRouteTableID.NotFound',
|
||||
self.client.describe_route_tables,
|
||||
RouteTableIds=[rt_id])
|
||||
|
||||
self.assertRaises('InvalidRouteTableID.NotFound',
|
||||
self.client.delete_route_table,
|
||||
RouteTableId=rt_id)
|
||||
|
||||
@decorators.idempotent_id('d8051b30-eb70-4c4b-988b-56078a125af3')
|
||||
def test_describe_route_tables_base(self):
|
||||
data = self.client.create_route_table(VpcId=self.vpc_id)
|
||||
rt_id = data['RouteTable']['RouteTableId']
|
||||
res_clean = self.addResourceCleanUp(self.client.delete_route_table,
|
||||
RouteTableId=rt_id)
|
||||
|
||||
# NOTE(andrey-mp): by real id
|
||||
data = self.client.describe_route_tables(RouteTableIds=[rt_id])
|
||||
self.assertEqual(1, len(data['RouteTables']))
|
||||
|
||||
# NOTE(andrey-mp): by fake id
|
||||
self.assertRaises('InvalidRouteTableID.NotFound',
|
||||
self.client.describe_route_tables,
|
||||
RouteTableIds=['rtb-0'])
|
||||
|
||||
data = self.client.delete_route_table(RouteTableId=rt_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
|
||||
@decorators.idempotent_id('77a53f3e-437a-45ed-b3b5-e6b7ab2c9407')
|
||||
def test_describe_route_tables_filters(self):
|
||||
data = self.client.create_route_table(VpcId=self.vpc_id)
|
||||
rt_id = data['RouteTable']['RouteTableId']
|
||||
self.addResourceCleanUp(self.client.delete_route_table,
|
||||
RouteTableId=rt_id)
|
||||
|
||||
data = self.client.create_subnet(VpcId=self.vpc_id,
|
||||
CidrBlock=self.SUBNET_CIDR)
|
||||
subnet_id = data['Subnet']['SubnetId']
|
||||
self.addResourceCleanUp(self.client.delete_subnet,
|
||||
SubnetId=subnet_id)
|
||||
self.get_subnet_waiter().wait_available(subnet_id)
|
||||
|
||||
data = self.client.associate_route_table(RouteTableId=rt_id,
|
||||
SubnetId=subnet_id)
|
||||
assoc_id = data['AssociationId']
|
||||
self.addResourceCleanUp(self.client.disassociate_route_table,
|
||||
AssociationId=assoc_id)
|
||||
|
||||
# NOTE(andrey-mp): by association_id
|
||||
data = self.client.describe_route_tables(
|
||||
Filters=[{'Name': 'association.route-table-association-id',
|
||||
'Values': [assoc_id]}])
|
||||
self.assertEqual(1, len(data['RouteTables']))
|
||||
|
||||
# NOTE(andrey-mp): by route table id
|
||||
data = self.client.describe_route_tables(
|
||||
Filters=[{'Name': 'association.route-table-id',
|
||||
'Values': [rt_id]}])
|
||||
self.assertEqual(1, len(data['RouteTables']))
|
||||
|
||||
# NOTE(andrey-mp): by subnet id
|
||||
data = self.client.describe_route_tables(
|
||||
Filters=[{'Name': 'association.subnet-id',
|
||||
'Values': [subnet_id]}])
|
||||
self.assertEqual(1, len(data['RouteTables']))
|
||||
|
||||
# NOTE(andrey-mp): by filter real vpc
|
||||
data = self.client.describe_route_tables(
|
||||
Filters=[{'Name': 'vpc-id', 'Values': [self.vpc_id]}])
|
||||
self.assertLess(0, len(data['RouteTables']))
|
||||
|
||||
# NOTE(andrey-mp): by filter fake vpc
|
||||
data = self.client.describe_route_tables(
|
||||
Filters=[{'Name': 'vpc-id', 'Values': ['vpc-0']}])
|
||||
self.assertEqual(0, len(data['RouteTables']))
|
||||
|
||||
# NOTE(andrey-mp): by fake filter
|
||||
self.assertRaises('InvalidParameterValue',
|
||||
self.client.describe_route_tables,
|
||||
Filters=[{'Name': 'fake', 'Values': ['fake']}])
|
||||
|
||||
@decorators.idempotent_id('55361f57-331a-43b8-8729-efee2d1c0dc9')
|
||||
def test_associate_disassociate_route_table(self):
|
||||
data = self.client.create_route_table(VpcId=self.vpc_id)
|
||||
rt_id = data['RouteTable']['RouteTableId']
|
||||
res_clean_rt = self.addResourceCleanUp(self.client.delete_route_table,
|
||||
RouteTableId=rt_id)
|
||||
|
||||
data = self.client.create_subnet(VpcId=self.vpc_id,
|
||||
CidrBlock=self.SUBNET_CIDR)
|
||||
subnet_id = data['Subnet']['SubnetId']
|
||||
res_clean_subnet = self.addResourceCleanUp(self.client.delete_subnet,
|
||||
SubnetId=subnet_id)
|
||||
self.get_subnet_waiter().wait_available(subnet_id)
|
||||
|
||||
data = self.client.associate_route_table(RouteTableId=rt_id,
|
||||
SubnetId=subnet_id)
|
||||
assoc_id = data['AssociationId']
|
||||
res_clean = self.addResourceCleanUp(
|
||||
self.client.disassociate_route_table, AssociationId=assoc_id)
|
||||
|
||||
data = self.client.disassociate_route_table(AssociationId=assoc_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
|
||||
data = self.client.delete_subnet(SubnetId=subnet_id)
|
||||
self.cancelResourceCleanUp(res_clean_subnet)
|
||||
self.get_subnet_waiter().wait_delete(subnet_id)
|
||||
|
||||
data = self.client.delete_route_table(RouteTableId=rt_id)
|
||||
self.cancelResourceCleanUp(res_clean_rt)
|
||||
|
||||
@decorators.idempotent_id('b1a07211-6e9a-41db-8017-47e7c4b9c043')
|
||||
def test_replace_route_table(self):
|
||||
data = self.client.create_subnet(VpcId=self.vpc_id,
|
||||
CidrBlock=self.SUBNET_CIDR)
|
||||
subnet_id = data['Subnet']['SubnetId']
|
||||
res_clean_subnet = self.addResourceCleanUp(self.client.delete_subnet,
|
||||
SubnetId=subnet_id)
|
||||
self.get_subnet_waiter().wait_available(subnet_id)
|
||||
|
||||
# NOTE(andrey-mp): by vpc id
|
||||
data = self.client.describe_route_tables(
|
||||
Filters=[{'Name': 'vpc-id', 'Values': [self.vpc_id]}])
|
||||
self.assertEqual(1, len(data['RouteTables']))
|
||||
self.assertEqual(1, len(data['RouteTables'][0]['Associations']))
|
||||
default_rt_id = data['RouteTables'][0]['RouteTableId']
|
||||
main_assoc = data['RouteTables'][0]['Associations'][0]
|
||||
self.assertTrue(main_assoc['Main'])
|
||||
main_assoc_id = main_assoc['RouteTableAssociationId']
|
||||
|
||||
data = self.client.create_route_table(VpcId=self.vpc_id)
|
||||
rt_id = data['RouteTable']['RouteTableId']
|
||||
res_clean_rt = self.addResourceCleanUp(self.client.delete_route_table,
|
||||
RouteTableId=rt_id)
|
||||
|
||||
data = self.client.replace_route_table_association(
|
||||
RouteTableId=rt_id, AssociationId=main_assoc_id)
|
||||
assoc_id = data['NewAssociationId']
|
||||
res_clean = self.addResourceCleanUp(
|
||||
self.client.replace_route_table_association,
|
||||
RouteTableId=default_rt_id,
|
||||
AssociationId=assoc_id)
|
||||
|
||||
# NOTE(andrey-mp): by vpc id
|
||||
data = self.client.describe_route_tables(
|
||||
Filters=[{'Name': 'vpc-id', 'Values': [self.vpc_id]}])
|
||||
self.assertEqual(2, len(data['RouteTables']))
|
||||
for rt in data['RouteTables']:
|
||||
if rt['RouteTableId'] == rt_id:
|
||||
self.assertEqual(1, len(rt['Associations']))
|
||||
self.assertTrue(rt['Associations'][0]['Main'])
|
||||
else:
|
||||
self.assertEmpty(rt.get('Associations', []))
|
||||
|
||||
self.assertRaises('DependencyViolation',
|
||||
self.client.delete_route_table,
|
||||
RouteTableId=rt_id)
|
||||
|
||||
self.assertRaises('InvalidParameterValue',
|
||||
self.client.disassociate_route_table,
|
||||
AssociationId=assoc_id)
|
||||
|
||||
data = self.client.replace_route_table_association(
|
||||
RouteTableId=default_rt_id,
|
||||
AssociationId=assoc_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
|
||||
data = self.client.delete_route_table(RouteTableId=rt_id)
|
||||
self.cancelResourceCleanUp(res_clean_rt)
|
||||
|
||||
data = self.client.delete_subnet(SubnetId=subnet_id)
|
||||
self.cancelResourceCleanUp(res_clean_subnet)
|
||||
self.get_subnet_waiter().wait_delete(subnet_id)
|
||||
|
||||
@decorators.idempotent_id('c112ecdb-dce3-4497-b11b-5349a2d89336')
|
||||
def test_create_delete_route(self):
|
||||
data = self.client.create_subnet(VpcId=self.vpc_id,
|
||||
CidrBlock=self.SUBNET_CIDR)
|
||||
subnet_id = data['Subnet']['SubnetId']
|
||||
res_clean_subnet = self.addResourceCleanUp(self.client.delete_subnet,
|
||||
SubnetId=subnet_id)
|
||||
self.get_subnet_waiter().wait_available(subnet_id)
|
||||
|
||||
kwargs = {
|
||||
'SubnetId': subnet_id,
|
||||
}
|
||||
data = self.client.create_network_interface(*[], **kwargs)
|
||||
ni_id = data['NetworkInterface']['NetworkInterfaceId']
|
||||
res_clean_ni = self.addResourceCleanUp(
|
||||
self.client.delete_network_interface,
|
||||
NetworkInterfaceId=ni_id)
|
||||
|
||||
data = self.client.create_route_table(VpcId=self.vpc_id)
|
||||
rt_id = data['RouteTable']['RouteTableId']
|
||||
res_clean_rt = self.addResourceCleanUp(self.client.delete_route_table,
|
||||
RouteTableId=rt_id)
|
||||
|
||||
kwargs = {
|
||||
'DestinationCidrBlock': self.VPC_CIDR,
|
||||
'RouteTableId': rt_id,
|
||||
'NetworkInterfaceId': ni_id
|
||||
}
|
||||
self.assertRaises('InvalidParameterValue',
|
||||
self.client.create_route,
|
||||
**kwargs)
|
||||
|
||||
# can create wider route
|
||||
kwargs = {
|
||||
'DestinationCidrBlock': '10.14.0.0/19',
|
||||
'RouteTableId': rt_id,
|
||||
'NetworkInterfaceId': ni_id
|
||||
}
|
||||
data = self.client.create_route(*[], **kwargs)
|
||||
# can create to another vpc
|
||||
kwargs = {
|
||||
'DestinationCidrBlock': '10.15.0.0/20',
|
||||
'RouteTableId': rt_id,
|
||||
'NetworkInterfaceId': ni_id
|
||||
}
|
||||
data = self.client.create_route(*[], **kwargs)
|
||||
|
||||
data = self.client.describe_route_tables(RouteTableIds=[rt_id])
|
||||
self.assertEqual(1, len(data['RouteTables']))
|
||||
self.assertEqual(3, len(data['RouteTables'][0]['Routes']))
|
||||
|
||||
kwargs = {
|
||||
'DestinationCidrBlock': '10.15.0.0/24',
|
||||
'RouteTableId': rt_id,
|
||||
}
|
||||
self.assertRaises('InvalidRoute.NotFound',
|
||||
self.client.delete_route,
|
||||
**kwargs)
|
||||
|
||||
kwargs = {
|
||||
'DestinationCidrBlock': self.VPC_CIDR,
|
||||
'RouteTableId': rt_id,
|
||||
}
|
||||
self.assertRaises('InvalidParameterValue',
|
||||
self.client.delete_route,
|
||||
**kwargs)
|
||||
|
||||
kwargs = {
|
||||
'DestinationCidrBlock': self.SUBNET_CIDR,
|
||||
'RouteTableId': rt_id,
|
||||
}
|
||||
self.assertRaises('InvalidRoute.NotFound',
|
||||
self.client.delete_route,
|
||||
**kwargs)
|
||||
|
||||
kwargs = {
|
||||
'DestinationCidrBlock': '10.16.0.0/24',
|
||||
'RouteTableId': rt_id,
|
||||
}
|
||||
self.assertRaises('InvalidRoute.NotFound',
|
||||
self.client.delete_route,
|
||||
**kwargs)
|
||||
|
||||
kwargs = {
|
||||
'DestinationCidrBlock': '10.15.0.0/20',
|
||||
'RouteTableId': rt_id,
|
||||
}
|
||||
data = self.client.delete_route(*[], **kwargs)
|
||||
|
||||
kwargs = {
|
||||
'DestinationCidrBlock': '10.14.0.0/19',
|
||||
'RouteTableId': rt_id,
|
||||
}
|
||||
data = self.client.delete_route(*[], **kwargs)
|
||||
|
||||
data = self.client.delete_route_table(RouteTableId=rt_id)
|
||||
self.cancelResourceCleanUp(res_clean_rt)
|
||||
|
||||
data = self.client.delete_network_interface(
|
||||
NetworkInterfaceId=ni_id)
|
||||
self.cancelResourceCleanUp(res_clean_ni)
|
||||
self.get_network_interface_waiter().wait_delete(ni_id)
|
||||
|
||||
data = self.client.delete_subnet(SubnetId=subnet_id)
|
||||
self.cancelResourceCleanUp(res_clean_subnet)
|
||||
self.get_subnet_waiter().wait_delete(subnet_id)
|
|
@ -1,326 +0,0 @@
|
|||
# Copyright 2014 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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 time
|
||||
|
||||
from oslo_log import log
|
||||
from tempest.lib.common.utils import data_utils
|
||||
from tempest.lib import decorators
|
||||
import testtools
|
||||
|
||||
from ec2api_tempest_plugin import base
|
||||
from ec2api_tempest_plugin import config
|
||||
|
||||
CONF = config.CONF
|
||||
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
|
||||
class SecurityGroupBaseTest(base.EC2TestCase):
|
||||
|
||||
def _test_rules(self, add_func, del_func, field, vpc_id=None):
|
||||
kwargs = dict()
|
||||
if vpc_id:
|
||||
kwargs['Filters'] = [{'Name': 'vpc-id', 'Values': [vpc_id]}]
|
||||
data = self.client.describe_security_groups(*[], **kwargs)
|
||||
security_groups = data['SecurityGroups']
|
||||
if not vpc_id:
|
||||
# TODO(andrey-mp): remove it when fitering by None will be
|
||||
security_groups = [sg for sg in security_groups
|
||||
if sg.get('VpcId') is None]
|
||||
default_group = security_groups[0]
|
||||
|
||||
name = data_utils.rand_name('sgName')
|
||||
desc = data_utils.rand_name('sgDesc')
|
||||
kwargs = {'GroupName': name, 'Description': desc}
|
||||
if vpc_id:
|
||||
kwargs['VpcId'] = vpc_id
|
||||
data = self.client.create_security_group(*[], **kwargs)
|
||||
group_id = data['GroupId']
|
||||
res_clean = self.addResourceCleanUp(self.client.delete_security_group,
|
||||
GroupId=group_id)
|
||||
time.sleep(2)
|
||||
data = self.client.describe_security_groups(GroupIds=[group_id])
|
||||
count = len(data['SecurityGroups'][0][field])
|
||||
|
||||
kwargs = {
|
||||
'GroupId': group_id,
|
||||
'IpPermissions': [{
|
||||
'IpProtocol': 'icmp',
|
||||
'FromPort': -1,
|
||||
'ToPort': -1,
|
||||
'IpRanges': [{
|
||||
'CidrIp': '10.0.0.0/8'
|
||||
}],
|
||||
}, {
|
||||
'UserIdGroupPairs': [{'GroupId': default_group['GroupId']}],
|
||||
'ToPort': 65535,
|
||||
'IpProtocol': 'tcp',
|
||||
'FromPort': 1
|
||||
}]
|
||||
}
|
||||
add_func(*[], **kwargs)
|
||||
|
||||
data = self.client.describe_security_groups(GroupIds=[group_id])
|
||||
self.assertEqual(1, len(data['SecurityGroups']))
|
||||
self.assertEqual(count + 2, len(data['SecurityGroups'][0][field]))
|
||||
found = 0
|
||||
for perm in data['SecurityGroups'][0][field]:
|
||||
cidrs = [v['CidrIp'] for v in perm.get('IpRanges', [])]
|
||||
if (perm.get('FromPort') == -1 and
|
||||
perm.get('ToPort') == -1 and
|
||||
perm.get('IpProtocol') == 'icmp' and
|
||||
len(perm.get('IpRanges')) == 1 and
|
||||
'10.0.0.0/8' in cidrs):
|
||||
found = found + 1
|
||||
elif (perm.get('FromPort') == 1 and
|
||||
perm.get('ToPort') == 65535 and
|
||||
perm.get('IpProtocol') == 'tcp' and
|
||||
len(perm.get('UserIdGroupPairs')) == 1 and
|
||||
perm.get('UserIdGroupPairs')[0]['GroupId']
|
||||
== default_group['GroupId']):
|
||||
found = found + 1
|
||||
self.assertEqual(2, found)
|
||||
|
||||
del_func(*[], **kwargs)
|
||||
|
||||
data = self.client.describe_security_groups(GroupIds=[group_id])
|
||||
self.assertEqual(1, len(data['SecurityGroups']))
|
||||
self.assertEqual(count, len(data['SecurityGroups'][0][field]))
|
||||
|
||||
if vpc_id:
|
||||
self.assertRaises('InvalidPermission.NotFound', del_func, **kwargs)
|
||||
else:
|
||||
del_func(*[], **kwargs)
|
||||
|
||||
self.client.delete_security_group(GroupId=group_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
|
||||
|
||||
class SecurityGroupInVPCTest(SecurityGroupBaseTest):
|
||||
|
||||
VPC_CIDR = '10.10.0.0/20'
|
||||
vpc_id = None
|
||||
|
||||
@classmethod
|
||||
@base.safe_setup
|
||||
def setUpClass(cls):
|
||||
super(SecurityGroupInVPCTest, cls).setUpClass()
|
||||
if not base.TesterStateHolder().get_vpc_enabled():
|
||||
raise cls.skipException('VPC is disabled')
|
||||
|
||||
data = cls.client.create_vpc(CidrBlock=cls.VPC_CIDR)
|
||||
cls.vpc_id = data['Vpc']['VpcId']
|
||||
cls.addResourceCleanUpStatic(cls.client.delete_vpc, VpcId=cls.vpc_id)
|
||||
cls.get_vpc_waiter().wait_available(cls.vpc_id)
|
||||
|
||||
@decorators.idempotent_id('f8354908-1b3a-4e7b-89e3-6956850bbbfb')
|
||||
def test_create_delete_security_group(self):
|
||||
name = data_utils.rand_name('sgName')
|
||||
desc = data_utils.rand_name('sgDesc')
|
||||
data = self.client.create_security_group(VpcId=self.vpc_id,
|
||||
GroupName=name,
|
||||
Description=desc)
|
||||
group_id = data['GroupId']
|
||||
res_clean = self.addResourceCleanUp(self.client.delete_security_group,
|
||||
GroupId=group_id)
|
||||
time.sleep(2)
|
||||
|
||||
self.client.delete_security_group(GroupId=group_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
|
||||
self.assertRaises('InvalidGroup.NotFound',
|
||||
self.client.describe_security_groups,
|
||||
GroupIds=[group_id])
|
||||
|
||||
self.assertRaises('InvalidGroup.NotFound',
|
||||
self.client.delete_security_group,
|
||||
GroupId=group_id)
|
||||
|
||||
@decorators.idempotent_id('fe209503-c348-4456-94b4-a77e68fabcbb')
|
||||
def test_create_duplicate_security_group(self):
|
||||
name = data_utils.rand_name('sgName')
|
||||
desc = data_utils.rand_name('sgDesc')
|
||||
data = self.client.create_security_group(VpcId=self.vpc_id,
|
||||
GroupName=name,
|
||||
Description=desc)
|
||||
group_id = data['GroupId']
|
||||
res_clean = self.addResourceCleanUp(self.client.delete_security_group,
|
||||
GroupId=group_id)
|
||||
time.sleep(2)
|
||||
|
||||
self.assertRaises('InvalidGroup.Duplicate',
|
||||
self.client.create_security_group,
|
||||
VpcId=self.vpc_id, GroupName=name, Description=desc)
|
||||
|
||||
data = self.client.delete_security_group(GroupId=group_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
|
||||
@decorators.idempotent_id('ffe5084a-2d05-42d1-ae8d-edcb0af27909')
|
||||
def test_create_duplicate_security_group_in_another_vpc(self):
|
||||
name = data_utils.rand_name('sgName')
|
||||
desc = data_utils.rand_name('sgDesc')
|
||||
data = self.client.create_security_group(VpcId=self.vpc_id,
|
||||
GroupName=name,
|
||||
Description=desc)
|
||||
group_id = data['GroupId']
|
||||
res_clean = self.addResourceCleanUp(self.client.delete_security_group,
|
||||
GroupId=group_id)
|
||||
time.sleep(2)
|
||||
|
||||
data = self.client.create_vpc(CidrBlock=self.VPC_CIDR)
|
||||
vpc_id = data['Vpc']['VpcId']
|
||||
dv_clean = self.addResourceCleanUp(self.client.delete_vpc,
|
||||
VpcId=vpc_id)
|
||||
|
||||
data = self.client.create_security_group(VpcId=vpc_id,
|
||||
GroupName=name,
|
||||
Description=desc)
|
||||
time.sleep(2)
|
||||
self.client.delete_security_group(GroupId=data['GroupId'])
|
||||
|
||||
self.client.delete_vpc(VpcId=vpc_id)
|
||||
self.cancelResourceCleanUp(dv_clean)
|
||||
self.get_vpc_waiter().wait_delete(vpc_id)
|
||||
|
||||
data = self.client.delete_security_group(GroupId=group_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
|
||||
@decorators.idempotent_id('524993f7-a8d3-4ffc-bbf1-6a3014377181')
|
||||
@testtools.skipUnless(CONF.aws.run_incompatible_tests,
|
||||
"MismatchError: 'InvalidParameterValue' != 'ValidationError'")
|
||||
def test_create_invalid_name_desc(self):
|
||||
valid = data_utils.rand_name('sgName')
|
||||
invalid = 'name%"'
|
||||
self.assertRaises('InvalidParameterValue',
|
||||
self.client.create_security_group,
|
||||
VpcId=self.vpc_id, GroupName=invalid,
|
||||
Description=valid)
|
||||
|
||||
self.assertRaises('InvalidParameterValue',
|
||||
self.client.create_security_group,
|
||||
VpcId=self.vpc_id, GroupName=valid,
|
||||
Description=invalid)
|
||||
|
||||
self.assertRaises('InvalidParameterValue',
|
||||
self.client.create_security_group,
|
||||
VpcId=self.vpc_id, GroupName='default',
|
||||
Description='default')
|
||||
|
||||
self.assertRaises('MissingParameter',
|
||||
self.client.create_security_group,
|
||||
VpcId=self.vpc_id, GroupName=valid, Description='')
|
||||
|
||||
self.assertRaises('MissingParameter',
|
||||
self.client.create_security_group,
|
||||
VpcId=self.vpc_id, GroupName='', Description=valid)
|
||||
|
||||
@decorators.idempotent_id('3460cefd-c759-4738-ba75-b275939aad1d')
|
||||
@testtools.skip("flaky test")
|
||||
def test_ingress_rules(self):
|
||||
self._test_rules(self.client.authorize_security_group_ingress,
|
||||
self.client.revoke_security_group_ingress,
|
||||
'IpPermissions', self.vpc_id)
|
||||
|
||||
@decorators.idempotent_id('74a5de83-69b4-4cc5-9431-e4c1f691f0c1')
|
||||
@testtools.skip("flaky test")
|
||||
def test_egress_rules(self):
|
||||
self._test_rules(self.client.authorize_security_group_egress,
|
||||
self.client.revoke_security_group_egress,
|
||||
'IpPermissionsEgress', self.vpc_id)
|
||||
|
||||
|
||||
class SecurityGroupEC2ClassicTest(SecurityGroupBaseTest):
|
||||
|
||||
@classmethod
|
||||
@base.safe_setup
|
||||
def setUpClass(cls):
|
||||
super(SecurityGroupEC2ClassicTest, cls).setUpClass()
|
||||
if not base.TesterStateHolder().get_ec2_enabled():
|
||||
raise cls.skipException('EC2-classic is disabled')
|
||||
|
||||
@decorators.idempotent_id('eb097f7c-4b10-4365-aa34-c17e5769f4a7')
|
||||
def test_create_delete_security_group(self):
|
||||
name = data_utils.rand_name('sgName')
|
||||
desc = data_utils.rand_name('sgDesc')
|
||||
data = self.client.create_security_group(GroupName=name,
|
||||
Description=desc)
|
||||
group_id = data['GroupId']
|
||||
res_clean = self.addResourceCleanUp(self.client.delete_security_group,
|
||||
GroupId=group_id)
|
||||
time.sleep(2)
|
||||
|
||||
data = self.client.describe_security_groups(GroupNames=[name])
|
||||
self.assertEqual(1, len(data['SecurityGroups']))
|
||||
self.assertEqual(group_id, data['SecurityGroups'][0]['GroupId'])
|
||||
|
||||
data = self.client.describe_security_groups(GroupIds=[group_id])
|
||||
self.assertEqual(1, len(data['SecurityGroups']))
|
||||
self.assertEqual(name, data['SecurityGroups'][0]['GroupName'])
|
||||
|
||||
self.client.delete_security_group(GroupName=name)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
|
||||
@decorators.idempotent_id('b97b8b4a-811e-4584-8e79-086499459aca')
|
||||
def test_create_duplicate_security_group(self):
|
||||
name = data_utils.rand_name('sgName')
|
||||
desc = data_utils.rand_name('sgDesc')
|
||||
data = self.client.create_security_group(GroupName=name,
|
||||
Description=desc)
|
||||
group_id = data['GroupId']
|
||||
res_clean = self.addResourceCleanUp(self.client.delete_security_group,
|
||||
GroupId=group_id)
|
||||
time.sleep(2)
|
||||
|
||||
self.assertRaises('InvalidGroup.Duplicate',
|
||||
self.client.create_security_group,
|
||||
GroupName=name, Description=desc)
|
||||
|
||||
self.client.delete_security_group(GroupId=group_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
|
||||
@decorators.idempotent_id('b80c578d-0c0d-4c7e-b0ee-a7ed23b6b209')
|
||||
@testtools.skipUnless(CONF.aws.run_incompatible_tests,
|
||||
"MismatchError: 'MissingParameter' != 'ValidationError'")
|
||||
def test_create_invalid_name_desc(self):
|
||||
valid = data_utils.rand_name('sgName')
|
||||
|
||||
self.assertRaises('MissingParameter',
|
||||
self.client.create_security_group,
|
||||
GroupName=valid, Description='')
|
||||
|
||||
self.assertRaises('MissingParameter',
|
||||
self.client.create_security_group,
|
||||
GroupName='', Description=valid)
|
||||
|
||||
self.assertRaises('InvalidGroup.Reserved',
|
||||
self.client.create_security_group,
|
||||
GroupName='default', Description='default')
|
||||
|
||||
@decorators.idempotent_id('eba8a7c4-3781-4562-b137-dbe8037395a3')
|
||||
def test_ingress_rules(self):
|
||||
self._test_rules(self.client.authorize_security_group_ingress,
|
||||
self.client.revoke_security_group_ingress,
|
||||
'IpPermissions')
|
||||
|
||||
@decorators.idempotent_id('435d5e53-060f-455a-9317-60177246e04d')
|
||||
def test_egress_rules(self):
|
||||
def _test():
|
||||
self._test_rules(
|
||||
self.client.authorize_security_group_egress,
|
||||
self.client.revoke_security_group_egress,
|
||||
'IpPermissionsEgress')
|
||||
|
||||
self.assertRaises('InvalidParameterValue', _test)
|
|
@ -1,267 +0,0 @@
|
|||
# Copyright 2014 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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.
|
||||
|
||||
from tempest.lib import decorators
|
||||
import testtools
|
||||
|
||||
from ec2api_tempest_plugin import base
|
||||
from ec2api_tempest_plugin import config
|
||||
|
||||
CONF = config.CONF
|
||||
|
||||
|
||||
class SnapshotTest(base.EC2TestCase):
|
||||
|
||||
@decorators.idempotent_id('3eb8868b-5c6b-4619-8c99-9429ca86a526')
|
||||
def test_create_delete_snapshot(self):
|
||||
kwargs = {
|
||||
'Size': 1,
|
||||
'AvailabilityZone': CONF.aws.aws_zone
|
||||
}
|
||||
data = self.client.create_volume(*[], **kwargs)
|
||||
volume_id = data['VolumeId']
|
||||
clean_vol = self.addResourceCleanUp(self.client.delete_volume,
|
||||
VolumeId=volume_id)
|
||||
self.get_volume_waiter().wait_available(volume_id)
|
||||
|
||||
desc = 'test snapshot'
|
||||
kwargs = {
|
||||
'VolumeId': volume_id,
|
||||
'Description': desc
|
||||
}
|
||||
data = self.client.create_snapshot(*[], **kwargs)
|
||||
snapshot_id = data['SnapshotId']
|
||||
res_clean = self.addResourceCleanUp(self.client.delete_snapshot,
|
||||
SnapshotId=snapshot_id)
|
||||
self.get_snapshot_waiter().wait_available(snapshot_id,
|
||||
final_set=('completed'))
|
||||
|
||||
self.assertEqual(desc, data['Description'])
|
||||
self.assertEqual(volume_id, data['VolumeId'])
|
||||
self.assertEqual(1, data['VolumeSize'])
|
||||
self.assertNotEmpty(data.get('State', ''))
|
||||
if 'Encrypted' in data:
|
||||
self.assertFalse(data['Encrypted'])
|
||||
self.assertIsNotNone(data['StartTime'])
|
||||
|
||||
data = self.client.delete_snapshot(SnapshotId=snapshot_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
self.get_snapshot_waiter().wait_delete(snapshot_id)
|
||||
|
||||
data = self.client.delete_volume(VolumeId=volume_id)
|
||||
self.cancelResourceCleanUp(clean_vol)
|
||||
self.get_volume_waiter().wait_delete(volume_id)
|
||||
|
||||
@decorators.idempotent_id('dfe0f2e6-c103-4e26-93e5-63010bf6b0af')
|
||||
def test_describe_snapshots(self):
|
||||
kwargs = {
|
||||
'Size': 1,
|
||||
'AvailabilityZone': CONF.aws.aws_zone
|
||||
}
|
||||
data = self.client.create_volume(*[], **kwargs)
|
||||
volume_id = data['VolumeId']
|
||||
clean_vol = self.addResourceCleanUp(self.client.delete_volume,
|
||||
VolumeId=volume_id)
|
||||
self.get_volume_waiter().wait_available(volume_id)
|
||||
|
||||
desc = 'test snapshot'
|
||||
kwargs = {
|
||||
'VolumeId': volume_id,
|
||||
'Description': desc
|
||||
}
|
||||
data = self.client.create_snapshot(*[], **kwargs)
|
||||
snapshot_id = data['SnapshotId']
|
||||
ownerId = data['OwnerId']
|
||||
res_clean = self.addResourceCleanUp(self.client.delete_snapshot,
|
||||
SnapshotId=snapshot_id)
|
||||
self.get_snapshot_waiter().wait_available(snapshot_id,
|
||||
final_set=('completed'))
|
||||
|
||||
self.assertEqual(desc, data['Description'])
|
||||
self.assertEqual(volume_id, data['VolumeId'])
|
||||
self.assertEqual(1, data['VolumeSize'])
|
||||
self.assertNotEmpty(data.get('State', ''))
|
||||
if 'Encrypted' in data:
|
||||
self.assertFalse(data['Encrypted'])
|
||||
self.assertIsNotNone(data['StartTime'])
|
||||
|
||||
data = self.client.describe_snapshots(SnapshotIds=[snapshot_id])
|
||||
self.assertEqual(1, len(data['Snapshots']))
|
||||
data = data['Snapshots'][0]
|
||||
self.assertEqual(snapshot_id, data['SnapshotId'])
|
||||
self.assertEqual(desc, data['Description'])
|
||||
self.assertEqual(volume_id, data['VolumeId'])
|
||||
self.assertEqual(1, data['VolumeSize'])
|
||||
self.assertNotEmpty(data.get('State', ''))
|
||||
if 'Encrypted' in data:
|
||||
self.assertFalse(data['Encrypted'])
|
||||
self.assertIsNotNone(data['StartTime'])
|
||||
|
||||
data = self.client.describe_snapshots(OwnerIds=[ownerId])
|
||||
data = [s for s in data['Snapshots'] if s['SnapshotId'] == snapshot_id]
|
||||
self.assertEqual(1, len(data))
|
||||
|
||||
data = self.client.delete_snapshot(SnapshotId=snapshot_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
self.get_snapshot_waiter().wait_delete(snapshot_id)
|
||||
|
||||
self.assertRaises('InvalidSnapshot.NotFound',
|
||||
self.client.describe_snapshots,
|
||||
SnapshotIds=[snapshot_id])
|
||||
|
||||
data = self.client.delete_volume(VolumeId=volume_id)
|
||||
self.cancelResourceCleanUp(clean_vol)
|
||||
self.get_volume_waiter().wait_delete(volume_id)
|
||||
|
||||
@decorators.idempotent_id('c4a99068-3c9e-4d8c-8d7a-e96548cfdaa7')
|
||||
def test_create_volume_from_snapshot(self):
|
||||
kwargs = {
|
||||
'Size': 1,
|
||||
'AvailabilityZone': CONF.aws.aws_zone
|
||||
}
|
||||
data = self.client.create_volume(*[], **kwargs)
|
||||
volume_id = data['VolumeId']
|
||||
clean_vol = self.addResourceCleanUp(self.client.delete_volume,
|
||||
VolumeId=volume_id)
|
||||
self.get_volume_waiter().wait_available(volume_id)
|
||||
vol1 = data
|
||||
|
||||
desc = 'test snapshot'
|
||||
kwargs = {
|
||||
'VolumeId': volume_id,
|
||||
'Description': desc
|
||||
}
|
||||
data = self.client.create_snapshot(*[], **kwargs)
|
||||
snapshot_id = data['SnapshotId']
|
||||
res_clean = self.addResourceCleanUp(self.client.delete_snapshot,
|
||||
SnapshotId=snapshot_id)
|
||||
self.get_snapshot_waiter().wait_available(snapshot_id,
|
||||
final_set=('completed'))
|
||||
|
||||
kwargs = {
|
||||
'SnapshotId': snapshot_id,
|
||||
'AvailabilityZone': CONF.aws.aws_zone
|
||||
}
|
||||
data = self.client.create_volume(*[], **kwargs)
|
||||
volume_id2 = data['VolumeId']
|
||||
clean_vol2 = self.addResourceCleanUp(self.client.delete_volume,
|
||||
VolumeId=volume_id2)
|
||||
self.get_volume_waiter().wait_available(volume_id2)
|
||||
|
||||
self.assertNotEqual(volume_id, volume_id2)
|
||||
self.assertEqual(vol1['Size'], data['Size'])
|
||||
self.assertEqual(snapshot_id, data['SnapshotId'])
|
||||
|
||||
data = self.client.describe_volumes(
|
||||
Filters=[{'Name': 'snapshot-id', 'Values': [snapshot_id]}])
|
||||
self.assertEqual(1, len(data['Volumes']))
|
||||
self.assertEqual(volume_id2, data['Volumes'][0]['VolumeId'])
|
||||
|
||||
data = self.client.delete_snapshot(SnapshotId=snapshot_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
self.get_snapshot_waiter().wait_delete(snapshot_id)
|
||||
|
||||
data = self.client.delete_volume(VolumeId=volume_id)
|
||||
self.cancelResourceCleanUp(clean_vol)
|
||||
self.get_volume_waiter().wait_delete(volume_id)
|
||||
|
||||
data = self.client.delete_volume(VolumeId=volume_id2)
|
||||
self.cancelResourceCleanUp(clean_vol2)
|
||||
self.get_volume_waiter().wait_delete(volume_id2)
|
||||
|
||||
@decorators.idempotent_id('c6f0be0a-67ca-4f33-b821-83e9158cee66')
|
||||
def test_create_increased_volume_from_snapshot(self):
|
||||
kwargs = {
|
||||
'Size': 1,
|
||||
'AvailabilityZone': CONF.aws.aws_zone
|
||||
}
|
||||
data = self.client.create_volume(*[], **kwargs)
|
||||
volume_id = data['VolumeId']
|
||||
clean_vol = self.addResourceCleanUp(self.client.delete_volume,
|
||||
VolumeId=volume_id)
|
||||
self.get_volume_waiter().wait_available(volume_id)
|
||||
|
||||
desc = 'test snapshot'
|
||||
kwargs = {
|
||||
'VolumeId': volume_id,
|
||||
'Description': desc
|
||||
}
|
||||
data = self.client.create_snapshot(*[], **kwargs)
|
||||
snapshot_id = data['SnapshotId']
|
||||
res_clean = self.addResourceCleanUp(self.client.delete_snapshot,
|
||||
SnapshotId=snapshot_id)
|
||||
self.get_snapshot_waiter().wait_available(snapshot_id,
|
||||
final_set=('completed'))
|
||||
|
||||
kwargs = {
|
||||
'Size': 2,
|
||||
'SnapshotId': snapshot_id,
|
||||
'AvailabilityZone': CONF.aws.aws_zone
|
||||
}
|
||||
data = self.client.create_volume(*[], **kwargs)
|
||||
volume_id2 = data['VolumeId']
|
||||
clean_vol2 = self.addResourceCleanUp(self.client.delete_volume,
|
||||
VolumeId=volume_id2)
|
||||
self.get_volume_waiter().wait_available(volume_id2)
|
||||
|
||||
self.assertNotEqual(volume_id, volume_id2)
|
||||
self.assertEqual(2, data['Size'])
|
||||
self.assertEqual(snapshot_id, data['SnapshotId'])
|
||||
|
||||
data = self.client.delete_snapshot(SnapshotId=snapshot_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
self.get_snapshot_waiter().wait_delete(snapshot_id)
|
||||
|
||||
data = self.client.delete_volume(VolumeId=volume_id)
|
||||
self.cancelResourceCleanUp(clean_vol)
|
||||
self.get_volume_waiter().wait_delete(volume_id)
|
||||
|
||||
data = self.client.delete_volume(VolumeId=volume_id2)
|
||||
self.cancelResourceCleanUp(clean_vol2)
|
||||
self.get_volume_waiter().wait_delete(volume_id2)
|
||||
|
||||
@decorators.idempotent_id('8f885da3-97e3-419e-b382-036ca7b25877')
|
||||
@testtools.skipUnless(CONF.aws.run_incompatible_tests,
|
||||
"Openstack can't delete volume with snapshots")
|
||||
def test_delete_volume_with_snapshots(self):
|
||||
kwargs = {
|
||||
'Size': 1,
|
||||
'AvailabilityZone': CONF.aws.aws_zone
|
||||
}
|
||||
data = self.client.create_volume(*[], **kwargs)
|
||||
volume_id = data['VolumeId']
|
||||
clean_vol = self.addResourceCleanUp(self.client.delete_volume,
|
||||
VolumeId=volume_id)
|
||||
self.get_volume_waiter().wait_available(volume_id)
|
||||
|
||||
desc = 'test snapshot'
|
||||
kwargs = {
|
||||
'VolumeId': volume_id,
|
||||
'Description': desc
|
||||
}
|
||||
data = self.client.create_snapshot(*[], **kwargs)
|
||||
snapshot_id = data['SnapshotId']
|
||||
res_clean = self.addResourceCleanUp(self.client.delete_snapshot,
|
||||
SnapshotId=snapshot_id)
|
||||
self.get_snapshot_waiter().wait_available(snapshot_id,
|
||||
final_set=('completed'))
|
||||
|
||||
data = self.client.delete_volume(VolumeId=volume_id)
|
||||
self.cancelResourceCleanUp(clean_vol)
|
||||
self.get_volume_waiter().wait_delete(volume_id)
|
||||
|
||||
data = self.client.delete_snapshot(SnapshotId=snapshot_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
self.get_snapshot_waiter().wait_delete(snapshot_id)
|
|
@ -1,191 +0,0 @@
|
|||
# Copyright 2014 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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.
|
||||
|
||||
from oslo_log import log
|
||||
from tempest.lib import decorators
|
||||
import testtools
|
||||
|
||||
from ec2api_tempest_plugin import base
|
||||
from ec2api_tempest_plugin import config
|
||||
|
||||
CONF = config.CONF
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
|
||||
class SubnetTest(base.EC2TestCase):
|
||||
|
||||
BASE_CIDR = '10.2.0.0'
|
||||
VPC_CIDR = BASE_CIDR + '/20'
|
||||
vpc_id = None
|
||||
|
||||
@classmethod
|
||||
@base.safe_setup
|
||||
def setUpClass(cls):
|
||||
super(SubnetTest, cls).setUpClass()
|
||||
if not base.TesterStateHolder().get_vpc_enabled():
|
||||
raise cls.skipException('VPC is disabled')
|
||||
|
||||
data = cls.client.create_vpc(CidrBlock=cls.VPC_CIDR)
|
||||
cls.vpc_id = data['Vpc']['VpcId']
|
||||
cls.addResourceCleanUpStatic(cls.client.delete_vpc, VpcId=cls.vpc_id)
|
||||
cls.get_vpc_waiter().wait_available(cls.vpc_id)
|
||||
|
||||
@decorators.idempotent_id('506993c3-aff6-48ea-8916-da8a4f199a66')
|
||||
def test_create_delete_subnet(self):
|
||||
cidr = self.BASE_CIDR + '/24'
|
||||
data = self.client.create_subnet(VpcId=self.vpc_id,
|
||||
CidrBlock=cidr)
|
||||
subnet_id = data['Subnet']['SubnetId']
|
||||
res_clean = self.addResourceCleanUp(self.client.delete_subnet,
|
||||
SubnetId=subnet_id)
|
||||
self.assertEqual(cidr, data['Subnet']['CidrBlock'])
|
||||
self.assertIsNotNone(data['Subnet'].get('AvailableIpAddressCount'))
|
||||
|
||||
self.get_subnet_waiter().wait_available(subnet_id)
|
||||
|
||||
data = self.client.delete_subnet(SubnetId=subnet_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
self.get_subnet_waiter().wait_delete(subnet_id)
|
||||
|
||||
self.assertRaises('InvalidSubnetID.NotFound',
|
||||
self.client.describe_subnets,
|
||||
SubnetIds=[subnet_id])
|
||||
|
||||
self.assertRaises('InvalidSubnetID.NotFound',
|
||||
self.client.delete_subnet,
|
||||
SubnetId=subnet_id)
|
||||
|
||||
@decorators.idempotent_id('4d27f078-46d2-4e2c-87c4-b5ba4589c2aa')
|
||||
def test_dependency_subnet_to_vpc(self):
|
||||
data = self.client.create_vpc(CidrBlock=self.VPC_CIDR)
|
||||
vpc_id = data['Vpc']['VpcId']
|
||||
vpc_clean = self.addResourceCleanUp(self.client.delete_vpc,
|
||||
VpcId=vpc_id)
|
||||
self.get_vpc_waiter().wait_available(vpc_id)
|
||||
|
||||
cidr = self.BASE_CIDR + '/24'
|
||||
data = self.client.create_subnet(VpcId=vpc_id, CidrBlock=cidr)
|
||||
subnet_id = data['Subnet']['SubnetId']
|
||||
res_clean = self.addResourceCleanUp(self.client.delete_subnet,
|
||||
SubnetId=subnet_id)
|
||||
self.get_subnet_waiter().wait_available(subnet_id)
|
||||
|
||||
self.assertRaises('DependencyViolation',
|
||||
self.client.delete_vpc,
|
||||
VpcId=vpc_id)
|
||||
|
||||
data = self.client.delete_subnet(SubnetId=subnet_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
self.get_subnet_waiter().wait_delete(subnet_id)
|
||||
|
||||
self.client.delete_vpc(VpcId=vpc_id)
|
||||
self.cancelResourceCleanUp(vpc_clean)
|
||||
|
||||
@decorators.idempotent_id('85ee17ca-5e2c-4d54-84ca-efcca8f94ff9')
|
||||
@testtools.skipUnless(
|
||||
CONF.aws.run_incompatible_tests,
|
||||
"bug with overlapped subnets")
|
||||
def test_create_overlapped_subnet(self):
|
||||
cidr = self.BASE_CIDR + '/24'
|
||||
data = self.client.create_subnet(VpcId=self.vpc_id, CidrBlock=cidr)
|
||||
subnet_id = data['Subnet']['SubnetId']
|
||||
res_clean = self.addResourceCleanUp(self.client.delete_subnet,
|
||||
SubnetId=subnet_id)
|
||||
self.get_subnet_waiter().wait_available(subnet_id)
|
||||
|
||||
cidr = '10.2.0.128/26'
|
||||
|
||||
def _rollback(fn_data):
|
||||
self.client.delete_subnet(SubnetId=data['Subnet']['SubnetId'])
|
||||
self.assertRaises('InvalidSubnet.Conflict',
|
||||
self.client.create_subnet, rollback_fn=_rollback,
|
||||
VpcId=self.vpc_id, CidrBlock=cidr)
|
||||
|
||||
data = self.client.delete_subnet(SubnetId=subnet_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
self.get_subnet_waiter().wait_delete(subnet_id)
|
||||
|
||||
@decorators.idempotent_id('20ea7ea4-67e6-42ed-9b91-e7b4b8d82605')
|
||||
def test_create_subnet_invalid_cidr(self):
|
||||
def _rollback(fn_data):
|
||||
self.client.delete_subnet(SubnetId=fn_data['Subnet']['SubnetId'])
|
||||
|
||||
# NOTE(andrey-mp): another cidr than VPC has
|
||||
cidr = '10.1.0.0/24'
|
||||
self.assertRaises('InvalidSubnet.Range',
|
||||
self.client.create_subnet, rollback_fn=_rollback,
|
||||
VpcId=self.vpc_id, CidrBlock=cidr)
|
||||
|
||||
# NOTE(andrey-mp): bigger cidr than VPC has
|
||||
cidr = self.BASE_CIDR + '/19'
|
||||
self.assertRaises('InvalidSubnet.Range',
|
||||
self.client.create_subnet, rollback_fn=_rollback,
|
||||
VpcId=self.vpc_id, CidrBlock=cidr)
|
||||
|
||||
# NOTE(andrey-mp): too small cidr
|
||||
cidr = self.BASE_CIDR + '/29'
|
||||
self.assertRaises('InvalidSubnet.Range',
|
||||
self.client.create_subnet, rollback_fn=_rollback,
|
||||
VpcId=self.vpc_id, CidrBlock=cidr)
|
||||
|
||||
@decorators.idempotent_id('8f0f2637-118f-4307-8585-7470808b3a86')
|
||||
def test_describe_subnets_base(self):
|
||||
cidr = self.BASE_CIDR + '/24'
|
||||
data = self.client.create_subnet(VpcId=self.vpc_id, CidrBlock=cidr)
|
||||
subnet_id = data['Subnet']['SubnetId']
|
||||
res_clean = self.addResourceCleanUp(self.client.delete_subnet,
|
||||
SubnetId=subnet_id)
|
||||
self.get_subnet_waiter().wait_available(subnet_id)
|
||||
|
||||
# NOTE(andrey-mp): by real id
|
||||
data = self.client.describe_subnets(SubnetIds=[subnet_id])
|
||||
self.assertEqual(1, len(data['Subnets']))
|
||||
|
||||
# NOTE(andrey-mp): by fake id
|
||||
self.assertRaises('InvalidSubnetID.NotFound',
|
||||
self.client.describe_subnets,
|
||||
SubnetIds=['subnet-0'])
|
||||
|
||||
data = self.client.delete_subnet(SubnetId=subnet_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
self.get_subnet_waiter().wait_delete(subnet_id)
|
||||
|
||||
@decorators.idempotent_id('182d151c-2dca-46bd-b137-1dece7276e1f')
|
||||
def test_describe_subnets_filters(self):
|
||||
cidr = self.BASE_CIDR + '/24'
|
||||
data = self.client.create_subnet(VpcId=self.vpc_id, CidrBlock=cidr)
|
||||
subnet_id = data['Subnet']['SubnetId']
|
||||
res_clean = self.addResourceCleanUp(self.client.delete_subnet,
|
||||
SubnetId=subnet_id)
|
||||
self.get_subnet_waiter().wait_available(subnet_id)
|
||||
|
||||
# NOTE(andrey-mp): by filter real cidr
|
||||
data = self.client.describe_subnets(
|
||||
Filters=[{'Name': 'cidr', 'Values': [cidr]}])
|
||||
self.assertEqual(1, len(data['Subnets']))
|
||||
|
||||
# NOTE(andrey-mp): by filter fake cidr
|
||||
data = self.client.describe_subnets(
|
||||
Filters=[{'Name': 'cidr', 'Values': ['123.0.0.0/16']}])
|
||||
self.assertEqual(0, len(data['Subnets']))
|
||||
|
||||
# NOTE(andrey-mp): by fake filter
|
||||
self.assertRaises('InvalidParameterValue',
|
||||
self.client.describe_subnets,
|
||||
Filters=[{'Name': 'fake', 'Values': ['fake']}])
|
||||
|
||||
data = self.client.delete_subnet(SubnetId=subnet_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
self.get_subnet_waiter().wait_delete(subnet_id)
|
|
@ -1,511 +0,0 @@
|
|||
# Copyright 2015 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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 time
|
||||
|
||||
from tempest.lib.common.utils import data_utils
|
||||
from tempest.lib import decorators
|
||||
import testtools
|
||||
|
||||
from ec2api_tempest_plugin import base
|
||||
from ec2api_tempest_plugin import config
|
||||
|
||||
CONF = config.CONF
|
||||
|
||||
|
||||
class TagTest(base.EC2TestCase):
|
||||
|
||||
@classmethod
|
||||
@base.safe_setup
|
||||
def setUpClass(cls):
|
||||
super(TagTest, cls).setUpClass()
|
||||
|
||||
cls.zone = CONF.aws.aws_zone
|
||||
data = cls.client.create_volume(
|
||||
Size=1, AvailabilityZone=cls.zone)
|
||||
cls.volume_id = data['VolumeId']
|
||||
cls.addResourceCleanUpStatic(cls.client.delete_volume,
|
||||
VolumeId=cls.volume_id)
|
||||
cls.get_volume_waiter().wait_available(cls.volume_id)
|
||||
|
||||
@decorators.idempotent_id('249f59cf-2fcd-47ac-a233-682f17fc3129')
|
||||
def test_create_get_delete_tag(self):
|
||||
tag_key = data_utils.rand_name('tag-key')
|
||||
self.client.create_tags(Resources=[self.volume_id],
|
||||
Tags=[{'Key': tag_key, 'Value': 'fake_value'}])
|
||||
self.addResourceCleanUp(self.client.delete_tags,
|
||||
Resources=[self.volume_id],
|
||||
Tags=[{'Key': tag_key}])
|
||||
|
||||
data = self.client.describe_tags(
|
||||
Filters=[{'Name': 'resource-id', 'Values': [self.volume_id]}])
|
||||
self.assertEqual(1, len(data['Tags']))
|
||||
|
||||
self.client.delete_tags(Resources=[self.volume_id],
|
||||
Tags=[{'Key': tag_key}])
|
||||
|
||||
data = self.client.describe_tags(
|
||||
Filters=[{'Name': 'resource-id', 'Values': [self.volume_id]}])
|
||||
self.assertEqual(0, len(data['Tags']))
|
||||
|
||||
@decorators.idempotent_id('41dec90b-a878-4367-ba95-83757281e343')
|
||||
def test_describe_tags(self):
|
||||
tag_key = data_utils.rand_name('tag-key')
|
||||
self.client.create_tags(Resources=[self.volume_id],
|
||||
Tags=[{'Key': tag_key, 'Value': 'fake_value'}])
|
||||
self.addResourceCleanUp(self.client.delete_tags,
|
||||
Resources=[self.volume_id],
|
||||
Tags=[{'Key': tag_key}])
|
||||
|
||||
data = self.client.describe_tags(
|
||||
Filters=[{'Name': 'resource-id', 'Values': [self.volume_id]}])
|
||||
self.assertEqual(1, len(data['Tags']))
|
||||
tag = data['Tags'][0]
|
||||
self.assertEqual('volume', tag.get('ResourceType'))
|
||||
self.assertEqual(self.volume_id, tag.get('ResourceId'))
|
||||
self.assertEqual(tag_key, tag.get('Key'))
|
||||
self.assertEqual('fake_value', tag.get('Value'))
|
||||
|
||||
data = self.client.describe_tags(
|
||||
Filters=[{'Name': 'resource-id', 'Values': [self.volume_id]},
|
||||
{'Name': 'key', 'Values': [tag_key]}])
|
||||
self.assertEqual(1, len(data['Tags']))
|
||||
|
||||
data = self.client.describe_tags(
|
||||
Filters=[{'Name': 'key', 'Values': [tag_key]}])
|
||||
self.assertIn(tag_key, [k.get('Key') for k in data['Tags']])
|
||||
|
||||
data = self.client.describe_tags(
|
||||
Filters=[{'Name': 'value', 'Values': ['fake_value']}])
|
||||
self.assertIn('fake_value', [k.get('Value') for k in data['Tags']])
|
||||
|
||||
data = self.client.describe_tags(
|
||||
Filters=[{'Name': 'key', 'Values': ['fake_value']}])
|
||||
items = [k.get('Key') for k in data['Tags']]
|
||||
self.assertNotIn(tag_key, items)
|
||||
self.assertNotIn('fake_value', items)
|
||||
|
||||
data = self.client.describe_tags(
|
||||
Filters=[{'Name': 'resource-type', 'Values': ['volume']}])
|
||||
self.assertIn(tag_key, [k.get('Key') for k in data['Tags']])
|
||||
|
||||
self.client.delete_tags(Resources=[self.volume_id],
|
||||
Tags=[{'Key': tag_key}])
|
||||
|
||||
data = self.client.describe_tags(
|
||||
Filters=[{'Name': 'resource-id', 'Values': [self.volume_id]}])
|
||||
self.assertEqual(0, len(data['Tags']))
|
||||
|
||||
def _test_tag_resource(self, resource_id, res_type, describe_func):
|
||||
data = self.client.describe_tags(
|
||||
Filters=[{'Name': 'resource-id', 'Values': [resource_id]}])
|
||||
origin_count = len(data['Tags'])
|
||||
|
||||
tag_key = data_utils.rand_name('tag-key')
|
||||
data = self.client.create_tags(Resources=[resource_id],
|
||||
Tags=[{'Key': tag_key, 'Value': 'fake_value'}])
|
||||
self.addResourceCleanUp(self.client.delete_tags,
|
||||
Resources=[resource_id],
|
||||
Tags=[{'Key': tag_key}])
|
||||
|
||||
data = self.client.describe_tags(
|
||||
Filters=[{'Name': 'resource-id', 'Values': [resource_id]}])
|
||||
self.assertEqual(origin_count + 1, len(data['Tags']))
|
||||
|
||||
data = self.client.describe_tags(
|
||||
Filters=[{'Name': 'resource-type', 'Values': [res_type]}])
|
||||
self.assertIn(tag_key, [k.get('Key') for k in data['Tags']])
|
||||
|
||||
describe_func(Filters=[{'Name': 'tag-key', 'Values': [tag_key]}])
|
||||
|
||||
self.client.delete_tags(Resources=[resource_id],
|
||||
Tags=[{'Key': tag_key}])
|
||||
|
||||
data = self.client.describe_tags(
|
||||
Filters=[{'Name': 'resource-id', 'Values': [resource_id]}])
|
||||
self.assertEqual(origin_count, len(data['Tags']))
|
||||
|
||||
def _test_tag_resource_negative(self, resource_id):
|
||||
data = self.client.describe_tags(
|
||||
Filters=[{'Name': 'resource-id', 'Values': [resource_id]}])
|
||||
self.assertEmpty(data['Tags'])
|
||||
|
||||
def _rollback(fn_data):
|
||||
self.client.delete_tags(Resources=[resource_id],
|
||||
Tags=[{'Key': tag_key}])
|
||||
|
||||
tag_key = data_utils.rand_name('tag-key')
|
||||
self.assertRaises('InvalidID',
|
||||
self.client.create_tags, rollback_fn=_rollback,
|
||||
Resources=[resource_id],
|
||||
Tags=[{'Key': tag_key, 'Value': 'fake_value'}])
|
||||
|
||||
@decorators.idempotent_id('36478dc6-cf3f-4a4b-b275-282ba147822b')
|
||||
def test_tag_image(self):
|
||||
image_id = CONF.aws.ebs_image_id
|
||||
if not image_id:
|
||||
image_id = CONF.aws.image_id
|
||||
if not image_id:
|
||||
raise self.skipException('aws or ebs image_id does not provided')
|
||||
|
||||
def describe_func(*args, **kwargs):
|
||||
data = self.client.describe_images(*args, **kwargs)
|
||||
self.assertEqual(1, len(data['Images']))
|
||||
self.assertEqual(image_id, data['Images'][0]['ImageId'])
|
||||
|
||||
self._test_tag_resource(image_id, 'image', describe_func)
|
||||
|
||||
data = self.client.describe_images(ImageIds=[image_id])
|
||||
image = data['Images'][0]
|
||||
if 'KernelId' in image:
|
||||
image_id = image['KernelId']
|
||||
self._test_tag_resource(image_id, 'image', describe_func)
|
||||
if 'RamdiskId' in image:
|
||||
image_id = image['RamdiskId']
|
||||
self._test_tag_resource(image_id, 'image', describe_func)
|
||||
|
||||
@base.skip_without_vpc()
|
||||
@decorators.idempotent_id('adc459f3-858d-4ce8-a097-549ab9350b18')
|
||||
def test_tag_dhcp_options(self):
|
||||
kwargs = {
|
||||
'DhcpConfigurations': [
|
||||
{'Key': 'domain-name',
|
||||
'Values': ['my.com']},
|
||||
],
|
||||
}
|
||||
data = self.client.create_dhcp_options(*[], **kwargs)
|
||||
options = data['DhcpOptions']
|
||||
res_id = options['DhcpOptionsId']
|
||||
res_clean = self.addResourceCleanUp(self.client.delete_dhcp_options,
|
||||
DhcpOptionsId=res_id)
|
||||
|
||||
def describe_func(*args, **kwargs):
|
||||
data = self.client.describe_dhcp_options(*args, **kwargs)
|
||||
self.assertEqual(1, len(data['DhcpOptions']))
|
||||
self.assertEqual(res_id, data['DhcpOptions'][0]['DhcpOptionsId'])
|
||||
|
||||
self._test_tag_resource(res_id, 'dhcp-options', describe_func)
|
||||
|
||||
self.client.delete_dhcp_options(DhcpOptionsId=res_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
|
||||
@decorators.idempotent_id('afa064b2-8caf-442d-b001-b6cb8120e57e')
|
||||
def test_tag_volume(self):
|
||||
def describe_func(*args, **kwargs):
|
||||
data = self.client.describe_volumes(*args, **kwargs)
|
||||
self.assertEqual(1, len(data['Volumes']))
|
||||
self.assertEqual(self.volume_id, data['Volumes'][0]['VolumeId'])
|
||||
|
||||
self._test_tag_resource(self.volume_id, 'volume', describe_func)
|
||||
|
||||
@base.skip_without_vpc()
|
||||
@decorators.idempotent_id('96e581c6-8f38-41f9-9126-e35215c83d3e')
|
||||
def test_tag_address(self):
|
||||
kwargs = {
|
||||
'Domain': 'vpc',
|
||||
}
|
||||
data = self.client.allocate_address(*[], **kwargs)
|
||||
res_id = data['AllocationId']
|
||||
res_clean = self.addResourceCleanUp(self.client.release_address,
|
||||
AllocationId=res_id)
|
||||
self.assertEqual('vpc', data['Domain'])
|
||||
|
||||
self._test_tag_resource_negative(res_id)
|
||||
|
||||
self.client.release_address(AllocationId=res_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
|
||||
@decorators.idempotent_id('f9a6dd26-b26f-4482-aad3-0b4f0e7cc3dd')
|
||||
@testtools.skipUnless(CONF.aws.image_id, "image id is not defined")
|
||||
def test_tag_instance(self):
|
||||
instance_id = self.run_instance()
|
||||
|
||||
def describe_func(*args, **kwargs):
|
||||
data = self.client.describe_instances(*args, **kwargs)
|
||||
self.assertEqual(1, len(data['Reservations']))
|
||||
self.assertEqual(1, len(data['Reservations'][0]['Instances']))
|
||||
self.assertEqual(instance_id,
|
||||
data['Reservations'][0]['Instances'][0]['InstanceId'])
|
||||
|
||||
self._test_tag_resource(instance_id, 'instance', describe_func)
|
||||
|
||||
self.client.terminate_instances(InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_delete(instance_id)
|
||||
|
||||
@base.skip_without_vpc()
|
||||
@decorators.idempotent_id('a223af28-b355-4404-a465-7fc9e9d71ad7')
|
||||
def test_tag_internet_gateway(self):
|
||||
data = self.client.create_internet_gateway()
|
||||
gw_id = data['InternetGateway']['InternetGatewayId']
|
||||
res_clean = self.addResourceCleanUp(
|
||||
self.client.delete_internet_gateway, InternetGatewayId=gw_id)
|
||||
|
||||
def describe_func(*args, **kwargs):
|
||||
data = self.client.describe_internet_gateways(*args, **kwargs)
|
||||
self.assertEqual(1, len(data['InternetGateways']))
|
||||
self.assertEqual(gw_id,
|
||||
data['InternetGateways'][0]['InternetGatewayId'])
|
||||
|
||||
self._test_tag_resource(gw_id, 'internet-gateway', describe_func)
|
||||
|
||||
self.client.delete_internet_gateway(InternetGatewayId=gw_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
|
||||
@base.skip_without_vpc()
|
||||
@decorators.idempotent_id('4691eefb-c118-4595-a386-8a2abd5c0d77')
|
||||
def test_tag_network_interface(self):
|
||||
cidr = '10.1.0.0/16'
|
||||
data = self.client.create_vpc(CidrBlock=cidr)
|
||||
vpc_id = data['Vpc']['VpcId']
|
||||
dv_clean = self.addResourceCleanUp(
|
||||
self.client.delete_vpc, VpcId=vpc_id)
|
||||
|
||||
cidr = '10.1.0.0/24'
|
||||
data = self.client.create_subnet(VpcId=vpc_id,
|
||||
CidrBlock=cidr)
|
||||
subnet_id = data['Subnet']['SubnetId']
|
||||
subnet_clean = self.addResourceCleanUp(self.client.delete_subnet,
|
||||
SubnetId=subnet_id)
|
||||
|
||||
data = self.client.create_network_interface(SubnetId=subnet_id,
|
||||
Description=data_utils.rand_name('ni'))
|
||||
ni_id = data['NetworkInterface']['NetworkInterfaceId']
|
||||
res_clean = self.addResourceCleanUp(
|
||||
self.client.delete_network_interface, NetworkInterfaceId=ni_id)
|
||||
self.get_network_interface_waiter().wait_available(ni_id)
|
||||
|
||||
def describe_func(*args, **kwargs):
|
||||
data = self.client.describe_network_interfaces(*args, **kwargs)
|
||||
self.assertEqual(1, len(data['NetworkInterfaces']))
|
||||
self.assertEqual(ni_id,
|
||||
data['NetworkInterfaces'][0]['NetworkInterfaceId'])
|
||||
|
||||
self._test_tag_resource(ni_id, 'network-interface', describe_func)
|
||||
|
||||
self.client.delete_network_interface(NetworkInterfaceId=ni_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
self.get_network_interface_waiter().wait_delete(ni_id)
|
||||
|
||||
self.client.delete_subnet(SubnetId=subnet_id)
|
||||
self.cancelResourceCleanUp(subnet_clean)
|
||||
self.get_subnet_waiter().wait_delete(subnet_id)
|
||||
|
||||
self.client.delete_vpc(VpcId=vpc_id)
|
||||
self.cancelResourceCleanUp(dv_clean)
|
||||
self.get_vpc_waiter().wait_delete(vpc_id)
|
||||
|
||||
@base.skip_without_vpc()
|
||||
@decorators.idempotent_id('384083a0-d492-4620-8093-166cd339ffaa')
|
||||
def test_tag_route_table(self):
|
||||
cidr = '10.1.0.0/16'
|
||||
data = self.client.create_vpc(CidrBlock=cidr)
|
||||
vpc_id = data['Vpc']['VpcId']
|
||||
dv_clean = self.addResourceCleanUp(
|
||||
self.client.delete_vpc, VpcId=vpc_id)
|
||||
|
||||
data = self.client.create_route_table(VpcId=vpc_id)
|
||||
rt_id = data['RouteTable']['RouteTableId']
|
||||
res_clean = self.addResourceCleanUp(self.client.delete_route_table,
|
||||
RouteTableId=rt_id)
|
||||
|
||||
def describe_func(*args, **kwargs):
|
||||
data = self.client.describe_route_tables(*args, **kwargs)
|
||||
self.assertEqual(1, len(data['RouteTables']))
|
||||
self.assertEqual(rt_id, data['RouteTables'][0]['RouteTableId'])
|
||||
|
||||
self._test_tag_resource(rt_id, 'route-table', describe_func)
|
||||
|
||||
self.client.delete_route_table(RouteTableId=rt_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
|
||||
self.client.delete_vpc(VpcId=vpc_id)
|
||||
self.cancelResourceCleanUp(dv_clean)
|
||||
self.get_vpc_waiter().wait_delete(vpc_id)
|
||||
|
||||
@base.skip_without_vpc()
|
||||
@decorators.idempotent_id('03b8cd38-3017-4a8f-b2e0-1c4ac5e7333d')
|
||||
def test_tag_security_group(self):
|
||||
cidr = '10.1.0.0/16'
|
||||
data = self.client.create_vpc(CidrBlock=cidr)
|
||||
vpc_id = data['Vpc']['VpcId']
|
||||
dv_clean = self.addResourceCleanUp(
|
||||
self.client.delete_vpc, VpcId=vpc_id)
|
||||
|
||||
name = data_utils.rand_name('sgName')
|
||||
desc = data_utils.rand_name('sgDesc')
|
||||
data = self.client.create_security_group(VpcId=vpc_id,
|
||||
GroupName=name,
|
||||
Description=desc)
|
||||
group_id = data['GroupId']
|
||||
res_clean = self.addResourceCleanUp(self.client.delete_security_group,
|
||||
GroupId=group_id)
|
||||
time.sleep(2)
|
||||
|
||||
def describe_func(*args, **kwargs):
|
||||
data = self.client.describe_security_groups(*args, **kwargs)
|
||||
self.assertEqual(1, len(data['SecurityGroups']))
|
||||
self.assertEqual(group_id,
|
||||
data['SecurityGroups'][0]['GroupId'])
|
||||
|
||||
self._test_tag_resource(group_id, 'security-group', describe_func)
|
||||
|
||||
self.client.delete_security_group(GroupId=group_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
|
||||
self.client.delete_vpc(VpcId=vpc_id)
|
||||
self.cancelResourceCleanUp(dv_clean)
|
||||
self.get_vpc_waiter().wait_delete(vpc_id)
|
||||
|
||||
@decorators.idempotent_id('bed98f9c-f987-4192-afd8-4bdf35ac916e')
|
||||
def test_tag_snapshot(self):
|
||||
data = self.client.create_snapshot(VolumeId=self.volume_id)
|
||||
snapshot_id = data['SnapshotId']
|
||||
res_clean = self.addResourceCleanUp(self.client.delete_snapshot,
|
||||
SnapshotId=snapshot_id)
|
||||
self.get_snapshot_waiter().wait_available(snapshot_id,
|
||||
final_set=('completed'))
|
||||
|
||||
def describe_func(*args, **kwargs):
|
||||
data = self.client.describe_snapshots(*args, **kwargs)
|
||||
self.assertEqual(1, len(data['Snapshots']))
|
||||
self.assertEqual(snapshot_id, data['Snapshots'][0]['SnapshotId'])
|
||||
|
||||
self._test_tag_resource(snapshot_id, 'snapshot', describe_func)
|
||||
|
||||
self.client.delete_snapshot(SnapshotId=snapshot_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
self.get_snapshot_waiter().wait_delete(snapshot_id)
|
||||
|
||||
@base.skip_without_vpc()
|
||||
@decorators.idempotent_id('3a6f64fc-d2d4-496d-bf30-3ee0efe04e42')
|
||||
def test_tag_subnet(self):
|
||||
cidr = '10.1.0.0/16'
|
||||
data = self.client.create_vpc(CidrBlock=cidr)
|
||||
vpc_id = data['Vpc']['VpcId']
|
||||
dv_clean = self.addResourceCleanUp(
|
||||
self.client.delete_vpc, VpcId=vpc_id)
|
||||
|
||||
cidr = '10.1.0.0/24'
|
||||
data = self.client.create_subnet(VpcId=vpc_id,
|
||||
CidrBlock=cidr)
|
||||
subnet_id = data['Subnet']['SubnetId']
|
||||
res_clean = self.addResourceCleanUp(self.client.delete_subnet,
|
||||
SubnetId=subnet_id)
|
||||
|
||||
def describe_func(*args, **kwargs):
|
||||
data = self.client.describe_subnets(*args, **kwargs)
|
||||
self.assertEqual(1, len(data['Subnets']))
|
||||
self.assertEqual(subnet_id, data['Subnets'][0]['SubnetId'])
|
||||
|
||||
self._test_tag_resource(subnet_id, 'subnet', describe_func)
|
||||
|
||||
self.client.delete_subnet(SubnetId=subnet_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
self.get_subnet_waiter().wait_delete(subnet_id)
|
||||
|
||||
self.client.delete_vpc(VpcId=vpc_id)
|
||||
self.cancelResourceCleanUp(dv_clean)
|
||||
self.get_vpc_waiter().wait_delete(vpc_id)
|
||||
|
||||
@base.skip_without_vpc()
|
||||
@decorators.idempotent_id('0667c68b-9d3c-4599-9335-0cee68ba5d80')
|
||||
def test_tag_vpc(self):
|
||||
cidr = '10.1.0.0/16'
|
||||
data = self.client.create_vpc(CidrBlock=cidr)
|
||||
vpc_id = data['Vpc']['VpcId']
|
||||
dv_clean = self.addResourceCleanUp(
|
||||
self.client.delete_vpc, VpcId=vpc_id)
|
||||
|
||||
def describe_func(*args, **kwargs):
|
||||
data = self.client.describe_vpcs(*args, **kwargs)
|
||||
self.assertEqual(1, len(data['Vpcs']))
|
||||
self.assertEqual(vpc_id, data['Vpcs'][0]['VpcId'])
|
||||
|
||||
self._test_tag_resource(vpc_id, 'vpc', describe_func)
|
||||
|
||||
self.client.delete_vpc(VpcId=vpc_id)
|
||||
self.cancelResourceCleanUp(dv_clean)
|
||||
self.get_vpc_waiter().wait_delete(vpc_id)
|
||||
|
||||
@base.skip_without_vpc()
|
||||
@decorators.idempotent_id('07b2f20d-6b26-4c3d-9d32-93f98f187d78')
|
||||
def test_tag_customer_gateway(self):
|
||||
data = self.client.create_customer_gateway(
|
||||
Type='ipsec.1', IpAddress='198.51.100.77', BgpAsn=65000)
|
||||
cgw_id = data['CustomerGateway']['CustomerGatewayId']
|
||||
self.addResourceCleanUp(self.client.delete_customer_gateway,
|
||||
CustomerGatewayId=cgw_id)
|
||||
|
||||
def describe_func(*args, **kwargs):
|
||||
data = self.client.describe_customer_gateways(*args, **kwargs)
|
||||
self.assertEqual(1, len(data['CustomerGateways']))
|
||||
self.assertEqual(cgw_id,
|
||||
data['CustomerGateways'][0]['CustomerGatewayId'])
|
||||
|
||||
self._test_tag_resource(cgw_id, 'customer-gateway', describe_func)
|
||||
|
||||
@testtools.skip("Some unknown bug. Will fix this later")
|
||||
@base.skip_without_vpc()
|
||||
@base.skip_without_vpnaas_enabled()
|
||||
@decorators.idempotent_id('a0437171-81a1-4871-9b71-c7629b25c337')
|
||||
def test_tag_vpn_gateway(self):
|
||||
data = self.client.create_vpn_gateway(Type='ipsec.1')
|
||||
vgw_id = data['VpnGateway']['VpnGatewayId']
|
||||
self.addResourceCleanUp(self.client.delete_vpn_gateway,
|
||||
VpnGatewayId=vgw_id)
|
||||
|
||||
def describe_func(*args, **kwargs):
|
||||
data = self.client.describe_vpn_gateways(*args, **kwargs)
|
||||
self.assertEqual(1, len(data['VpnGateways']))
|
||||
self.assertEqual(vgw_id,
|
||||
data['VpnGateways'][0]['VpnGatewayId'])
|
||||
|
||||
self._test_tag_resource(vgw_id, 'vpn-gateway', describe_func)
|
||||
|
||||
@testtools.skip("Some unknown bug. Will fix this later")
|
||||
@base.skip_without_vpc()
|
||||
@base.skip_without_vpnaas_enabled()
|
||||
@decorators.idempotent_id('ecd343b4-f448-4990-880d-02a68febc9cf')
|
||||
def test_tag_vpn_connection(self):
|
||||
data = self.client.create_customer_gateway(
|
||||
Type='ipsec.1', PublicIp='198.51.100.77', BgpAsn=65000)
|
||||
cgw_id = data['CustomerGateway']['CustomerGatewayId']
|
||||
self.addResourceCleanUp(self.client.delete_customer_gateway,
|
||||
CustomerGatewayId=cgw_id)
|
||||
|
||||
data = self.client.create_vpn_gateway(Type='ipsec.1')
|
||||
vgw_id = data['VpnGateway']['VpnGatewayId']
|
||||
self.addResourceCleanUp(self.client.delete_vpn_gateway,
|
||||
VpnGatewayId=vgw_id)
|
||||
|
||||
data = self.client.create_vpn_connection(
|
||||
CustomerGatewayId=cgw_id, VpnGatewayId=vgw_id,
|
||||
Options={'StaticRoutesOnly': True}, Type='ipsec.1')
|
||||
vpn_id = data['VpnConnection']['VpnConnectionId']
|
||||
vpn_clean = self.addResourceCleanUp(self.client.delete_vpn_connection,
|
||||
VpnConnectionId=vpn_id)
|
||||
|
||||
def describe_func(*args, **kwargs):
|
||||
data = self.client.describe_vpn_connections(*args, **kwargs)
|
||||
self.assertEqual(1, len(data['VpnConnections']))
|
||||
self.assertEqual(vpn_id,
|
||||
data['VpnConnections'][0]['VpnConnectionId'])
|
||||
|
||||
self._test_tag_resource(vpn_id, 'vpn-connection', describe_func)
|
||||
|
||||
self.client.delete_vpn_connection(VpnConnectionId=vpn_id)
|
||||
vpn_waiter = self.get_vpn_connection_waiter()
|
||||
self.cancelResourceCleanUp(vpn_clean)
|
||||
vpn_waiter.wait_delete(vpn_id)
|
|
@ -1,420 +0,0 @@
|
|||
# Copyright 2014 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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.
|
||||
|
||||
from tempest.lib import decorators
|
||||
import testtools
|
||||
|
||||
from ec2api_tempest_plugin import base
|
||||
from ec2api_tempest_plugin import config
|
||||
|
||||
CONF = config.CONF
|
||||
|
||||
|
||||
class VolumeTest(base.EC2TestCase):
|
||||
|
||||
@decorators.idempotent_id('51fd4d06-7b00-427a-9d69-6ecd076c219a')
|
||||
def test_create_delete_volume(self):
|
||||
kwargs = {
|
||||
'Size': 1,
|
||||
'AvailabilityZone': CONF.aws.aws_zone
|
||||
}
|
||||
data = self.client.create_volume(*[], **kwargs)
|
||||
volume_id = data['VolumeId']
|
||||
res_clean = self.addResourceCleanUp(self.client.delete_volume,
|
||||
VolumeId=volume_id)
|
||||
|
||||
self.get_volume_waiter().wait_available(volume_id)
|
||||
|
||||
if CONF.aws.run_incompatible_tests:
|
||||
self.assertEqual('standard', data['VolumeType'])
|
||||
self.assertEqual(1, data['Size'])
|
||||
if 'Encrypted' in data:
|
||||
self.assertFalse(data['Encrypted'])
|
||||
self.assertIsNotNone(data['CreateTime'])
|
||||
self.assertEqual(CONF.aws.aws_zone, data['AvailabilityZone'])
|
||||
|
||||
self.client.delete_volume(VolumeId=volume_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
self.get_volume_waiter().wait_delete(volume_id)
|
||||
|
||||
self.assertRaises('InvalidVolume.NotFound',
|
||||
self.client.describe_volumes,
|
||||
VolumeIds=[volume_id])
|
||||
|
||||
self.assertRaises('InvalidVolume.NotFound',
|
||||
self.client.delete_volume,
|
||||
VolumeId=volume_id)
|
||||
|
||||
@decorators.idempotent_id('a7f1c4f8-2153-4d09-b5d5-bf087ea2f6ed')
|
||||
@testtools.skipUnless(CONF.aws.run_incompatible_tests,
|
||||
"Encryption is not implemented")
|
||||
def test_create_encrypted_volume(self):
|
||||
kwargs = {
|
||||
'Size': 1,
|
||||
'AvailabilityZone': CONF.aws.aws_zone,
|
||||
'Encrypted': True,
|
||||
}
|
||||
data = self.client.create_volume(*[], **kwargs)
|
||||
volume_id = data['VolumeId']
|
||||
res_clean = self.addResourceCleanUp(self.client.delete_volume,
|
||||
VolumeId=volume_id)
|
||||
|
||||
self.get_volume_waiter().wait_available(volume_id)
|
||||
|
||||
self.assertTrue(data['Encrypted'])
|
||||
|
||||
self.client.delete_volume(VolumeId=volume_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
self.get_volume_waiter().wait_delete(volume_id)
|
||||
|
||||
@decorators.idempotent_id('16c97f73-c4f2-4e91-9506-4f6da4a33f8a')
|
||||
def test_describe_volumes(self):
|
||||
kwargs = {
|
||||
'Size': 1,
|
||||
'AvailabilityZone': CONF.aws.aws_zone
|
||||
}
|
||||
data = self.client.create_volume(*[], **kwargs)
|
||||
volume_id = data['VolumeId']
|
||||
res_clean = self.addResourceCleanUp(self.client.delete_volume,
|
||||
VolumeId=volume_id)
|
||||
self.get_volume_waiter().wait_available(volume_id)
|
||||
|
||||
data = self.client.create_volume(*[], **kwargs)
|
||||
volume_id_ext = data['VolumeId']
|
||||
res_clean_ext = self.addResourceCleanUp(self.client.delete_volume,
|
||||
VolumeId=volume_id_ext)
|
||||
self.get_volume_waiter().wait_available(volume_id_ext)
|
||||
|
||||
data = self.client.describe_volumes(VolumeIds=[volume_id])
|
||||
self.assertEqual(1, len(data['Volumes']))
|
||||
|
||||
volume = data['Volumes'][0]
|
||||
self.assertEqual(volume_id, volume['VolumeId'])
|
||||
if CONF.aws.run_incompatible_tests:
|
||||
self.assertEqual('standard', volume['VolumeType'])
|
||||
self.assertEqual(1, volume['Size'])
|
||||
if 'Encrypted' in volume:
|
||||
self.assertFalse(volume['Encrypted'])
|
||||
|
||||
self.client.delete_volume(VolumeId=volume_id_ext)
|
||||
self.cancelResourceCleanUp(res_clean_ext)
|
||||
self.get_volume_waiter().wait_delete(volume_id_ext)
|
||||
|
||||
self.client.delete_volume(VolumeId=volume_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
self.get_volume_waiter().wait_delete(volume_id)
|
||||
|
||||
@decorators.idempotent_id('30697dd5-12e7-4dd3-8cf8-5bdb296f26d8')
|
||||
@testtools.skipUnless(CONF.aws.run_incompatible_tests,
|
||||
"Volume statuses are not implemented")
|
||||
def test_describe_volume_status(self):
|
||||
kwargs = {
|
||||
'Size': 1,
|
||||
'AvailabilityZone': CONF.aws.aws_zone
|
||||
}
|
||||
data = self.client.create_volume(*[], **kwargs)
|
||||
volume_id = data['VolumeId']
|
||||
res_clean = self.addResourceCleanUp(self.client.delete_volume,
|
||||
VolumeId=volume_id)
|
||||
|
||||
self.get_volume_waiter().wait_available(volume_id)
|
||||
|
||||
data = self.client.describe_volume_status(VolumeIds=[volume_id])
|
||||
self.assertEqual(1, len(data['VolumeStatuses']))
|
||||
|
||||
volume_status = data['VolumeStatuses'][0]
|
||||
self.assertIn('Actions', volume_status)
|
||||
self.assertIn('Events', volume_status)
|
||||
self.assertIn('VolumeStatus', volume_status)
|
||||
|
||||
self.client.delete_volume(VolumeId=volume_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
self.get_volume_waiter().wait_delete(volume_id)
|
||||
|
||||
@decorators.idempotent_id('b0116edc-250c-4083-b1ad-66c0eb984415')
|
||||
@testtools.skipUnless(CONF.aws.ebs_image_id, "ebs image id is not defined")
|
||||
def test_attach_detach_volume(self):
|
||||
clean_dict = {}
|
||||
instance_id = self.run_instance(ImageId=CONF.aws.ebs_image_id,
|
||||
clean_dict=clean_dict)
|
||||
clean_i = clean_dict['instance']
|
||||
|
||||
kwargs = {
|
||||
'Size': 1,
|
||||
'AvailabilityZone': CONF.aws.aws_zone
|
||||
}
|
||||
data = self.client.create_volume(*[], **kwargs)
|
||||
volume_id = data['VolumeId']
|
||||
clean_v = self.addResourceCleanUp(self.client.delete_volume,
|
||||
VolumeId=volume_id)
|
||||
self.get_volume_waiter().wait_available(volume_id)
|
||||
|
||||
kwargs = {
|
||||
'Device': '/dev/sdh',
|
||||
'InstanceId': instance_id,
|
||||
'VolumeId': volume_id,
|
||||
}
|
||||
self.client.attach_volume(*[], **kwargs)
|
||||
clean_vi = self.addResourceCleanUp(self.client.detach_volume,
|
||||
VolumeId=volume_id)
|
||||
self.get_volume_attachment_waiter().wait_available(
|
||||
volume_id, final_set=('attached'))
|
||||
|
||||
# reorder cleanups to avoid error on volume delete
|
||||
self.cancelResourceCleanUp(clean_i)
|
||||
clean_i = self.addResourceCleanUp(self.client.terminate_instances,
|
||||
InstanceIds=[instance_id])
|
||||
|
||||
data = self.client.describe_volumes(VolumeIds=[volume_id])
|
||||
self.assertEqual(1, len(data['Volumes']))
|
||||
volume = data['Volumes'][0]
|
||||
self.assertEqual('in-use', volume['State'])
|
||||
self.assertEqual(1, len(volume['Attachments']))
|
||||
attachment = volume['Attachments'][0]
|
||||
self.assertFalse(attachment['DeleteOnTermination'])
|
||||
self.assertIsNotNone(attachment['Device'])
|
||||
self.assertEqual(instance_id, attachment['InstanceId'])
|
||||
self.assertEqual(volume_id, attachment['VolumeId'])
|
||||
|
||||
data = self.client.describe_instances(InstanceIds=[instance_id])
|
||||
self.assertEqual(1, len(data.get('Reservations', [])))
|
||||
self.assertEqual(1, len(data['Reservations'][0].get('Instances', [])))
|
||||
bdms = data['Reservations'][0]['Instances'][0]['BlockDeviceMappings']
|
||||
self.assertNotEmpty(bdms)
|
||||
self.assertIn('DeviceName', bdms[0])
|
||||
self.assertIn('Ebs', bdms[0])
|
||||
|
||||
# stop instance to prevent 'busy' state of detached volume
|
||||
data = self.client.stop_instances(InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_available(instance_id,
|
||||
final_set=('stopped'))
|
||||
|
||||
self.client.detach_volume(VolumeId=volume_id)
|
||||
self.get_volume_attachment_waiter().wait_delete(volume_id)
|
||||
self.cancelResourceCleanUp(clean_vi)
|
||||
|
||||
data = self.client.describe_volumes(VolumeIds=[volume_id])
|
||||
self.assertEqual(1, len(data['Volumes']))
|
||||
volume = data['Volumes'][0]
|
||||
self.assertEqual('available', volume['State'])
|
||||
self.assertEqual(0, len(volume['Attachments']))
|
||||
|
||||
self.client.delete_volume(VolumeId=volume_id)
|
||||
self.cancelResourceCleanUp(clean_v)
|
||||
self.get_volume_waiter().wait_delete(volume_id)
|
||||
|
||||
self.client.terminate_instances(InstanceIds=[instance_id])
|
||||
self.cancelResourceCleanUp(clean_i)
|
||||
self.get_instance_waiter().wait_delete(instance_id)
|
||||
|
||||
@decorators.idempotent_id('c4b470b7-0825-418f-bc76-533f84247878')
|
||||
@testtools.skipUnless(CONF.aws.ebs_image_id, "EBS image id is not defined")
|
||||
def test_attaching_stage(self):
|
||||
clean_dict = {}
|
||||
instance_id = self.run_instance(ImageId=CONF.aws.ebs_image_id,
|
||||
clean_dict=clean_dict)
|
||||
clean_i = clean_dict['instance']
|
||||
|
||||
data = self.client.create_volume(
|
||||
AvailabilityZone=CONF.aws.aws_zone, Size=1)
|
||||
volume_id = data['VolumeId']
|
||||
clean_v = self.addResourceCleanUp(self.client.delete_volume,
|
||||
VolumeId=volume_id)
|
||||
self.get_volume_waiter().wait_available(volume_id)
|
||||
|
||||
device_name = '/dev/xvdh'
|
||||
kwargs = {
|
||||
'Device': device_name,
|
||||
'InstanceId': instance_id,
|
||||
'VolumeId': volume_id,
|
||||
}
|
||||
data = self.client.attach_volume(*[], **kwargs)
|
||||
clean_vi = self.addResourceCleanUp(self.client.detach_volume,
|
||||
VolumeId=volume_id)
|
||||
self.assertEqual('attaching', data['State'])
|
||||
|
||||
if CONF.aws.run_incompatible_tests:
|
||||
bdt = self.get_instance_bdm(instance_id, device_name)
|
||||
self.assertIsNotNone(bdt)
|
||||
self.assertEqual('attaching', bdt['Ebs']['Status'])
|
||||
|
||||
self.get_volume_attachment_waiter().wait_available(
|
||||
volume_id, final_set=('attached'))
|
||||
|
||||
# reorder cleanups to avoid error on volume delete
|
||||
self.cancelResourceCleanUp(clean_i)
|
||||
clean_i = self.addResourceCleanUp(self.client.terminate_instances,
|
||||
InstanceIds=[instance_id])
|
||||
|
||||
# stop instance to prevent 'busy' state of detached volume
|
||||
data = self.client.stop_instances(InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_available(instance_id,
|
||||
final_set=('stopped'))
|
||||
|
||||
self.client.detach_volume(VolumeId=volume_id)
|
||||
self.get_volume_attachment_waiter().wait_delete(volume_id)
|
||||
self.cancelResourceCleanUp(clean_vi)
|
||||
|
||||
self.client.delete_volume(VolumeId=volume_id)
|
||||
self.cancelResourceCleanUp(clean_v)
|
||||
self.get_volume_waiter().wait_delete(volume_id)
|
||||
|
||||
self.client.terminate_instances(InstanceIds=[instance_id])
|
||||
self.cancelResourceCleanUp(clean_i)
|
||||
self.get_instance_waiter().wait_delete(instance_id)
|
||||
|
||||
@decorators.idempotent_id('949ced35-fb66-4e87-afd8-f64de3dd20e9')
|
||||
@testtools.skipUnless(CONF.aws.run_incompatible_tests,
|
||||
"Volume statuses are not implemented")
|
||||
@testtools.skipUnless(CONF.aws.ebs_image_id, "EBS image id is not defined")
|
||||
def test_delete_detach_attached_volume(self):
|
||||
instance_id = self.run_instance(ImageId=CONF.aws.ebs_image_id)
|
||||
|
||||
kwargs = {
|
||||
'Size': 1,
|
||||
'AvailabilityZone': CONF.aws.aws_zone
|
||||
}
|
||||
data = self.client.create_volume(*[], **kwargs)
|
||||
volume_id = data['VolumeId']
|
||||
clean_v = self.addResourceCleanUp(self.client.delete_volume,
|
||||
VolumeId=volume_id)
|
||||
self.get_volume_waiter().wait_available(volume_id)
|
||||
|
||||
kwargs = {
|
||||
'Device': '/dev/sdh',
|
||||
'InstanceId': instance_id,
|
||||
'VolumeId': volume_id,
|
||||
}
|
||||
self.client.attach_volume(*[], **kwargs)
|
||||
clean_vi = self.addResourceCleanUp(self.client.detach_volume,
|
||||
VolumeId=volume_id)
|
||||
self.get_volume_attachment_waiter().wait_available(
|
||||
volume_id, final_set=('attached'))
|
||||
|
||||
self.assertRaises('VolumeInUse',
|
||||
self.client.attach_volume,
|
||||
**kwargs)
|
||||
|
||||
kwargs['Device'] = '/dev/sdi'
|
||||
self.assertRaises('VolumeInUse',
|
||||
self.client.attach_volume,
|
||||
**kwargs)
|
||||
|
||||
self.assertRaises('VolumeInUse',
|
||||
self.client.delete_volume,
|
||||
VolumeId=volume_id)
|
||||
|
||||
# stop instance to prevent 'busy' state of detached volume
|
||||
data = self.client.stop_instances(InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_available(instance_id,
|
||||
final_set=('stopped'))
|
||||
|
||||
self.client.detach_volume(VolumeId=volume_id)
|
||||
self.cancelResourceCleanUp(clean_vi)
|
||||
self.get_volume_attachment_waiter().wait_delete(volume_id)
|
||||
|
||||
self.assertRaises('IncorrectState',
|
||||
self.client.detach_volume,
|
||||
VolumeId=volume_id)
|
||||
|
||||
self.client.delete_volume(VolumeId=volume_id)
|
||||
self.cancelResourceCleanUp(clean_v)
|
||||
self.get_volume_waiter().wait_delete(volume_id)
|
||||
|
||||
self.assertRaises('InvalidVolume.NotFound',
|
||||
self.client.detach_volume,
|
||||
VolumeId=volume_id)
|
||||
|
||||
self.client.terminate_instances(InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_delete(instance_id)
|
||||
|
||||
@decorators.idempotent_id('c37b01f7-5b27-4773-9278-9e0b8eaccb5f')
|
||||
@testtools.skipUnless(CONF.aws.image_id, "image id is not defined")
|
||||
def test_volume_auto_termination_swithed_off(self):
|
||||
instance_id = self.run_instance()
|
||||
|
||||
kwargs = {
|
||||
'Size': 1,
|
||||
'AvailabilityZone': CONF.aws.aws_zone
|
||||
}
|
||||
data = self.client.create_volume(*[], **kwargs)
|
||||
volume_id = data['VolumeId']
|
||||
clean_v = self.addResourceCleanUp(self.client.delete_volume,
|
||||
VolumeId=volume_id)
|
||||
self.get_volume_waiter().wait_available(volume_id)
|
||||
|
||||
kwargs = {
|
||||
'Device': '/dev/sdh',
|
||||
'InstanceId': instance_id,
|
||||
'VolumeId': volume_id,
|
||||
}
|
||||
self.client.attach_volume(*[], **kwargs)
|
||||
self.addResourceCleanUp(self.client.detach_volume, VolumeId=volume_id)
|
||||
self.get_volume_attachment_waiter().wait_available(
|
||||
volume_id, final_set=('attached'))
|
||||
|
||||
self.client.terminate_instances(InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_delete(instance_id)
|
||||
|
||||
data = self.client.describe_volumes(VolumeIds=[volume_id])
|
||||
self.assertEqual(1, len(data['Volumes']))
|
||||
volume = data['Volumes'][0]
|
||||
self.assertEqual('available', volume['State'])
|
||||
if 'Attachments' in volume:
|
||||
self.assertEqual(0, len(volume['Attachments']))
|
||||
|
||||
self.client.delete_volume(VolumeId=volume_id)
|
||||
self.cancelResourceCleanUp(clean_v)
|
||||
self.get_volume_waiter().wait_delete(volume_id)
|
||||
|
||||
@decorators.idempotent_id('c8649cab-e1f4-42f7-9578-8e72d06534ba')
|
||||
@testtools.skipUnless(CONF.aws.run_incompatible_tests,
|
||||
"modify_instance_attribute is not implemented")
|
||||
@testtools.skipUnless(CONF.aws.image_id, "image id is not defined")
|
||||
def test_volume_auto_termination_swithed_on(self):
|
||||
instance_id = self.run_instance()
|
||||
|
||||
kwargs = {
|
||||
'Size': 1,
|
||||
'AvailabilityZone': CONF.aws.aws_zone
|
||||
}
|
||||
data = self.client.create_volume(*[], **kwargs)
|
||||
volume_id = data['VolumeId']
|
||||
self.addResourceCleanUp(self.client.delete_volume, VolumeId=volume_id)
|
||||
self.get_volume_waiter().wait_available(volume_id)
|
||||
|
||||
kwargs = {
|
||||
'Device': '/dev/sdh',
|
||||
'InstanceId': instance_id,
|
||||
'VolumeId': volume_id,
|
||||
}
|
||||
self.client.attach_volume(*[], **kwargs)
|
||||
self.addResourceCleanUp(self.client.detach_volume, VolumeId=volume_id)
|
||||
self.get_volume_attachment_waiter().wait_available(
|
||||
volume_id, final_set=('attached'))
|
||||
|
||||
kwargs = {
|
||||
'InstanceId': instance_id,
|
||||
'BlockDeviceMappings': [{'DeviceName': '/dev/sdh',
|
||||
'Ebs': {'VolumeId': volume_id,
|
||||
'DeleteOnTermination': True}}],
|
||||
}
|
||||
self.client.modify_instance_attribute(*[], **kwargs)
|
||||
|
||||
self.client.terminate_instances(InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_delete(instance_id)
|
||||
|
||||
# volume should be deleted by the Cloud
|
||||
self.get_volume_waiter().wait_delete(volume_id)
|
|
@ -1,208 +0,0 @@
|
|||
# Copyright 2014 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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.
|
||||
|
||||
from tempest.lib import decorators
|
||||
import testtools
|
||||
|
||||
from ec2api_tempest_plugin import base
|
||||
from ec2api_tempest_plugin import config
|
||||
|
||||
CONF = config.CONF
|
||||
|
||||
|
||||
class VPCTest(base.EC2TestCase):
|
||||
|
||||
@classmethod
|
||||
@base.safe_setup
|
||||
def setUpClass(cls):
|
||||
super(VPCTest, cls).setUpClass()
|
||||
if not base.TesterStateHolder().get_vpc_enabled():
|
||||
raise cls.skipException('VPC is disabled')
|
||||
|
||||
@decorators.idempotent_id('446b19ba-2b70-4f52-9e32-82e04771cb70')
|
||||
def test_create_delete_vpc(self):
|
||||
cidr = '10.1.0.0/16'
|
||||
data = self.client.create_vpc(CidrBlock=cidr)
|
||||
vpc_id = data['Vpc']['VpcId']
|
||||
dv_clean = self.addResourceCleanUp(self.client.delete_vpc,
|
||||
VpcId=vpc_id)
|
||||
|
||||
self.assertEqual(cidr, data['Vpc']['CidrBlock'])
|
||||
if CONF.aws.run_incompatible_tests:
|
||||
# NOTE(andrey-mp): not ready
|
||||
self.assertEqual('default', data['Vpc']['InstanceTenancy'])
|
||||
self.assertIsNotNone(data['Vpc'].get('DhcpOptionsId'))
|
||||
|
||||
self.get_vpc_waiter().wait_available(vpc_id)
|
||||
|
||||
self.client.delete_vpc(VpcId=vpc_id)
|
||||
self.cancelResourceCleanUp(dv_clean)
|
||||
self.get_vpc_waiter().wait_delete(vpc_id)
|
||||
|
||||
self.assertRaises('InvalidVpcID.NotFound',
|
||||
self.client.describe_vpcs,
|
||||
VpcIds=[vpc_id])
|
||||
|
||||
self.assertRaises('InvalidVpcID.NotFound',
|
||||
self.client.delete_vpc,
|
||||
VpcId=vpc_id)
|
||||
|
||||
@decorators.idempotent_id('de300ce9-41a4-4b88-a991-99186e8c97b4')
|
||||
def test_create_more_than_one_vpc(self):
|
||||
cidr = '10.0.0.0/16'
|
||||
data = self.client.create_vpc(CidrBlock=cidr)
|
||||
vpc_id1 = data['Vpc']['VpcId']
|
||||
rc1 = self.addResourceCleanUp(self.client.delete_vpc, VpcId=vpc_id1)
|
||||
self.get_vpc_waiter().wait_available(vpc_id1)
|
||||
|
||||
cidr = '10.1.0.0/16'
|
||||
data = self.client.create_vpc(CidrBlock=cidr)
|
||||
vpc_id2 = data['Vpc']['VpcId']
|
||||
rc2 = self.addResourceCleanUp(self.client.delete_vpc, VpcId=vpc_id2)
|
||||
self.get_vpc_waiter().wait_available(vpc_id2)
|
||||
|
||||
self.client.delete_vpc(VpcId=vpc_id1)
|
||||
self.cancelResourceCleanUp(rc1)
|
||||
self.get_vpc_waiter().wait_delete(vpc_id1)
|
||||
|
||||
self.client.delete_vpc(VpcId=vpc_id2)
|
||||
self.cancelResourceCleanUp(rc2)
|
||||
self.get_vpc_waiter().wait_delete(vpc_id2)
|
||||
|
||||
@decorators.idempotent_id('011bd6e0-65c3-4716-a1f3-ba6cdb477b19')
|
||||
def test_describe_vpcs_base(self):
|
||||
cidr = '10.1.0.0/16'
|
||||
data = self.client.create_vpc(CidrBlock=cidr)
|
||||
vpc_id = data['Vpc']['VpcId']
|
||||
dv_clean = self.addResourceCleanUp(self.client.delete_vpc,
|
||||
VpcId=vpc_id)
|
||||
self.get_vpc_waiter().wait_available(vpc_id)
|
||||
|
||||
# NOTE(andrey-mp): by real id
|
||||
data = self.client.describe_vpcs(VpcIds=[vpc_id])
|
||||
self.assertEqual(1, len(data['Vpcs']))
|
||||
|
||||
# NOTE(andrey-mp): by fake id
|
||||
self.assertRaises('InvalidVpcID.NotFound',
|
||||
self.client.describe_vpcs,
|
||||
VpcIds=['vpc-0'])
|
||||
|
||||
self.client.delete_vpc(VpcId=vpc_id)
|
||||
self.cancelResourceCleanUp(dv_clean)
|
||||
self.get_vpc_waiter().wait_delete(vpc_id)
|
||||
|
||||
@decorators.idempotent_id('9c8735b9-f745-49a0-b68d-33f771bac660')
|
||||
def test_describe_vpcs_filters(self):
|
||||
cidr = '10.163.0.0/16'
|
||||
data = self.client.create_vpc(CidrBlock=cidr)
|
||||
vpc_id = data['Vpc']['VpcId']
|
||||
dv_clean = self.addResourceCleanUp(self.client.delete_vpc,
|
||||
VpcId=vpc_id)
|
||||
self.get_vpc_waiter().wait_available(vpc_id)
|
||||
|
||||
# NOTE(andrey-mp): by filter real cidr
|
||||
data = self.client.describe_vpcs(
|
||||
Filters=[{'Name': 'cidr', 'Values': [cidr]}])
|
||||
self.assertEqual(1, len(data['Vpcs']))
|
||||
|
||||
# NOTE(andrey-mp): by filter fake cidr
|
||||
data = self.client.describe_vpcs(
|
||||
Filters=[{'Name': 'cidr', 'Values': ['123.0.0.0/16']}])
|
||||
self.assertEqual(0, len(data['Vpcs']))
|
||||
|
||||
# NOTE(andrey-mp): by fake filter
|
||||
self.assertRaises('InvalidParameterValue',
|
||||
self.client.describe_vpcs,
|
||||
Filters=[{'Name': 'fake', 'Values': ['fake']}])
|
||||
|
||||
data = self.client.delete_vpc(VpcId=vpc_id)
|
||||
self.cancelResourceCleanUp(dv_clean)
|
||||
self.get_vpc_waiter().wait_delete(vpc_id)
|
||||
|
||||
@decorators.idempotent_id('3070ea61-992b-4711-a874-322c6c672204')
|
||||
@testtools.skipUnless(CONF.aws.run_incompatible_tests,
|
||||
"Invalid request on checking vpc atributes.")
|
||||
def test_vpc_attributes(self):
|
||||
cidr = '10.1.0.0/16'
|
||||
data = self.client.create_vpc(CidrBlock=cidr)
|
||||
vpc_id = data['Vpc']['VpcId']
|
||||
dv_clean = self.addResourceCleanUp(self.client.delete_vpc,
|
||||
VpcId=vpc_id)
|
||||
self.get_vpc_waiter().wait_available(vpc_id)
|
||||
|
||||
self._check_attribute(vpc_id, 'EnableDnsHostnames')
|
||||
self._check_attribute(vpc_id, 'EnableDnsSupport')
|
||||
|
||||
data = self.client.delete_vpc(VpcId=vpc_id)
|
||||
self.cancelResourceCleanUp(dv_clean)
|
||||
self.get_vpc_waiter().wait_delete(vpc_id)
|
||||
|
||||
def _check_attribute(self, vpc_id, attribute):
|
||||
req_attr = attribute[0].lower() + attribute[1:]
|
||||
data = self.client.describe_vpc_attribute(VpcId=vpc_id,
|
||||
Attribute=req_attr)
|
||||
attr = data[attribute].get('Value')
|
||||
self.assertIsNotNone(attr)
|
||||
|
||||
kwargs = {'VpcId': vpc_id, attribute: {'Value': not attr}}
|
||||
data = self.client.modify_vpc_attribute(*[], **kwargs)
|
||||
data = self.client.describe_vpc_attribute(VpcId=vpc_id,
|
||||
Attribute=req_attr)
|
||||
self.assertNotEqual(attr, data[attribute].get('Value'))
|
||||
|
||||
@decorators.idempotent_id('8c5f1e82-05da-40e0-8ee8-640db2d94dd6')
|
||||
def test_create_with_invalid_cidr(self):
|
||||
def _rollback(fn_data):
|
||||
self.client.delete_vpc(VpcId=fn_data['Vpc']['VpcId'])
|
||||
|
||||
# NOTE(andrey-mp): The largest uses a /16 netmask
|
||||
self.assertRaises('InvalidVpc.Range',
|
||||
self.client.create_vpc, rollback_fn=_rollback,
|
||||
CidrBlock='10.0.0.0/15')
|
||||
|
||||
# NOTE(andrey-mp): The smallest VPC you can create uses a /28 netmask
|
||||
self.assertRaises('InvalidVpc.Range',
|
||||
self.client.create_vpc, rollback_fn=_rollback,
|
||||
CidrBlock='10.0.0.0/29')
|
||||
|
||||
@decorators.idempotent_id('5abb2ff0-8ea2-4e02-b9a4-95a371982b82')
|
||||
def test_describe_non_existing_vpc_by_id(self):
|
||||
vpc_id = 'vpc-00000000'
|
||||
self.assertRaises('InvalidVpcID.NotFound',
|
||||
self.client.describe_vpcs,
|
||||
VpcIds=[vpc_id])
|
||||
|
||||
@decorators.idempotent_id('e99d81f1-902a-46b0-afc8-c64e6d548891')
|
||||
def test_describe_non_existing_vpc_by_cidr(self):
|
||||
data = self.client.describe_vpcs(
|
||||
Filters=[{'Name': 'cidr', 'Values': ['123.0.0.0/16']}])
|
||||
self.assertEqual(0, len(data['Vpcs']))
|
||||
|
||||
@decorators.idempotent_id('62263b68-6991-4bbe-b7b2-9997a84fd0a5')
|
||||
def test_describe_with_invalid_filter(self):
|
||||
cidr = '10.1.0.0/16'
|
||||
data = self.client.create_vpc(CidrBlock=cidr)
|
||||
vpc_id = data['Vpc']['VpcId']
|
||||
dv_clean = self.addResourceCleanUp(self.client.delete_vpc,
|
||||
VpcId=vpc_id)
|
||||
self.get_vpc_waiter().wait_available(vpc_id)
|
||||
|
||||
self.assertRaises('InvalidParameterValue',
|
||||
self.client.describe_vpcs,
|
||||
Filters=[{'Name': 'unknown', 'Values': ['unknown']}])
|
||||
|
||||
data = self.client.delete_vpc(VpcId=vpc_id)
|
||||
self.cancelResourceCleanUp(dv_clean)
|
||||
self.get_vpc_waiter().wait_delete(vpc_id)
|
|
@ -1,113 +0,0 @@
|
|||
# Copyright 2014 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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 botocore.exceptions
|
||||
from lxml import etree
|
||||
from tempest.lib import decorators
|
||||
|
||||
from ec2api_tempest_plugin import base
|
||||
from ec2api_tempest_plugin import config
|
||||
|
||||
CONF = config.CONF
|
||||
|
||||
|
||||
class VpnConnectionTest(base.EC2TestCase):
|
||||
|
||||
CUSTOMER_GATEWAY_IP = '198.51.100.77'
|
||||
CUSTOMER_VPN_CIDR = '172.16.25.0/24'
|
||||
cgw_id = None
|
||||
vgw_id = None
|
||||
|
||||
@classmethod
|
||||
@base.safe_setup
|
||||
def setUpClass(cls):
|
||||
super(VpnConnectionTest, cls).setUpClass()
|
||||
if not base.TesterStateHolder().get_vpc_enabled():
|
||||
raise cls.skipException('VPC is disabled')
|
||||
base.check_vpnaas_enabled()
|
||||
|
||||
data = cls.client.create_customer_gateway(
|
||||
Type='ipsec.1', PublicIp=cls.CUSTOMER_GATEWAY_IP, BgpAsn=65000)
|
||||
cls.cgw_id = data['CustomerGateway']['CustomerGatewayId']
|
||||
cls.addResourceCleanUpStatic(
|
||||
cls.client.delete_customer_gateway, CustomerGatewayId=cls.cgw_id)
|
||||
cls.get_customer_gateway_waiter().wait_available(cls.cgw_id)
|
||||
|
||||
data = cls.client.create_vpn_gateway(
|
||||
Type='ipsec.1', AvailabilityZone=CONF.aws.aws_zone)
|
||||
cls.vgw_id = data['VpnGateway']['VpnGatewayId']
|
||||
cls.addResourceCleanUpStatic(
|
||||
cls.client.delete_vpn_gateway, VpnGatewayId=cls.vgw_id)
|
||||
cls.get_vpn_gateway_waiter().wait_available(cls.vgw_id)
|
||||
|
||||
@decorators.idempotent_id('57426aab-cf2d-4114-a11d-2bd6642ac606')
|
||||
def test_create_delete_vpn_connection(self):
|
||||
data = self.client.create_vpn_connection(
|
||||
CustomerGatewayId=self.cgw_id, VpnGatewayId=self.vgw_id,
|
||||
Options={'StaticRoutesOnly': True}, Type='ipsec.1')
|
||||
vpn_id = data['VpnConnection']['VpnConnectionId']
|
||||
vpn_clean = self.addResourceCleanUp(
|
||||
self.client.delete_vpn_connection, VpnConnectionId=vpn_id)
|
||||
vpn_config = etree.fromstring(
|
||||
data['VpnConnection']['CustomerGatewayConfiguration'].encode())
|
||||
psks = vpn_config.xpath(
|
||||
'/vpn_connection/ipsec_tunnel/ike/pre_shared_key')
|
||||
self.assertNotEmpty(psks)
|
||||
self.assertTrue(psks[0].text)
|
||||
vpn_waiter = self.get_vpn_connection_waiter()
|
||||
vpn_waiter.wait_available(vpn_id)
|
||||
|
||||
self.client.delete_vpn_connection(VpnConnectionId=vpn_id)
|
||||
self.cancelResourceCleanUp(vpn_clean)
|
||||
vpn_waiter.wait_delete(vpn_id)
|
||||
|
||||
try:
|
||||
data = self.client.describe_vpn_connections(
|
||||
VpnConnectionIds=[vpn_id])
|
||||
self.assertEqual(1, len(data['VpnConnections']))
|
||||
self.assertEqual('deleted', data['VpnConnections'][0]['State'])
|
||||
except botocore.exceptions.ClientError as ex:
|
||||
self.assertEqual('InvalidVpnConnectionID.NotFound',
|
||||
ex.response['Error']['Code'])
|
||||
|
||||
@decorators.idempotent_id('6fa8c58d-876b-4d3f-85ba-e972a9d6db3b')
|
||||
def test_create_delete_vpn_connection_route(self):
|
||||
data = self.client.create_vpn_connection(
|
||||
CustomerGatewayId=self.cgw_id, VpnGatewayId=self.vgw_id,
|
||||
Options={'StaticRoutesOnly': True}, Type='ipsec.1')
|
||||
vpn_id = data['VpnConnection']['VpnConnectionId']
|
||||
self.addResourceCleanUp(
|
||||
self.client.delete_vpn_connection, VpnConnectionId=vpn_id)
|
||||
vpn_waiter = self.get_vpn_connection_waiter()
|
||||
vpn_waiter.wait_available(vpn_id)
|
||||
|
||||
data = self.client.create_vpn_connection_route(
|
||||
VpnConnectionId=vpn_id,
|
||||
DestinationCidrBlock=self.CUSTOMER_VPN_CIDR)
|
||||
|
||||
data = self.client.describe_vpn_connections(VpnConnectionIds=[vpn_id])
|
||||
self.assertEqual(1, len(data['VpnConnections'][0]['Routes']))
|
||||
self.assertEqual(
|
||||
self.CUSTOMER_VPN_CIDR,
|
||||
data['VpnConnections'][0]['Routes'][0]['DestinationCidrBlock'])
|
||||
route_waiter = self.get_vpn_connection_route_waiter(
|
||||
self.CUSTOMER_VPN_CIDR)
|
||||
route_waiter.wait_available(vpn_id)
|
||||
|
||||
data = self.client.delete_vpn_connection_route(
|
||||
VpnConnectionId=vpn_id,
|
||||
DestinationCidrBlock=self.CUSTOMER_VPN_CIDR)
|
||||
data = self.client.describe_vpn_connections(VpnConnectionIds=[vpn_id])
|
||||
route_waiter.wait_delete(vpn_id)
|
|
@ -1,93 +0,0 @@
|
|||
# Copyright 2014 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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 botocore.exceptions
|
||||
from tempest.lib import decorators
|
||||
|
||||
from ec2api_tempest_plugin import base
|
||||
from ec2api_tempest_plugin import config
|
||||
|
||||
CONF = config.CONF
|
||||
|
||||
|
||||
class VpnGatewayTest(base.EC2TestCase):
|
||||
|
||||
VPC_CIDR = '10.41.0.0/20'
|
||||
vpc_id = None
|
||||
|
||||
@classmethod
|
||||
@base.safe_setup
|
||||
def setUpClass(cls):
|
||||
super(VpnGatewayTest, cls).setUpClass()
|
||||
if not base.TesterStateHolder().get_vpc_enabled():
|
||||
raise cls.skipException('VPC is disabled')
|
||||
base.check_vpnaas_enabled()
|
||||
|
||||
data = cls.client.create_vpc(CidrBlock=cls.VPC_CIDR)
|
||||
cls.vpc_id = data['Vpc']['VpcId']
|
||||
cls.get_vpc_waiter().wait_available(cls.vpc_id)
|
||||
cls.addResourceCleanUpStatic(cls.client.delete_vpc, VpcId=cls.vpc_id)
|
||||
|
||||
@decorators.idempotent_id('d38c0185-782c-4da3-b02c-9cd7bf91b001')
|
||||
def test_create_delete_vpn_gateway(self):
|
||||
data = self.client.create_vpn_gateway(
|
||||
Type='ipsec.1', AvailabilityZone=CONF.aws.aws_zone)
|
||||
vgw_id = data['VpnGateway']['VpnGatewayId']
|
||||
vgw_clean = self.addResourceCleanUp(
|
||||
self.client.delete_vpn_gateway, VpnGatewayId=vgw_id)
|
||||
self.get_vpn_gateway_waiter().wait_available(vgw_id)
|
||||
|
||||
self.client.delete_vpn_gateway(VpnGatewayId=vgw_id)
|
||||
self.cancelResourceCleanUp(vgw_clean)
|
||||
self.get_vpn_gateway_waiter().wait_delete(vgw_id)
|
||||
|
||||
try:
|
||||
data = self.client.describe_vpn_gateways(
|
||||
VpnGatewayIds=[vgw_id])
|
||||
self.assertEqual(1, len(data['VpnGateways']))
|
||||
self.assertEqual('deleted', data['VpnGateways'][0]['State'])
|
||||
except botocore.exceptions.ClientError as ex:
|
||||
self.assertEqual('InvalidVpnGatewayID.NotFound',
|
||||
ex.response['Error']['Code'])
|
||||
|
||||
@decorators.idempotent_id('1d76b335-57ba-449a-9751-af75a8a7d11c')
|
||||
def test_attach_detach_vpn_gateway(self):
|
||||
data = self.client.create_vpn_gateway(
|
||||
Type='ipsec.1', AvailabilityZone=CONF.aws.aws_zone)
|
||||
vgw_id = data['VpnGateway']['VpnGatewayId']
|
||||
self.addResourceCleanUp(self.client.delete_vpn_gateway,
|
||||
VpnGatewayId=vgw_id)
|
||||
self.get_vpn_gateway_waiter().wait_available(vgw_id)
|
||||
|
||||
data = self.client.attach_vpn_gateway(VpnGatewayId=vgw_id,
|
||||
VpcId=self.vpc_id)
|
||||
attach_clean = self.addResourceCleanUp(
|
||||
self.client.detach_vpn_gateway,
|
||||
VpnGatewayId=vgw_id, VpcId=self.vpc_id)
|
||||
self.assertIn('VpcAttachment', data)
|
||||
self.assertEqual(self.vpc_id, data['VpcAttachment']['VpcId'])
|
||||
attach_waiter = self.get_vpn_gateway_attachment_waiter()
|
||||
attach_waiter.wait_available(vgw_id, 'attached')
|
||||
|
||||
data = self.client.detach_vpn_gateway(VpnGatewayId=vgw_id,
|
||||
VpcId=self.vpc_id)
|
||||
self.cancelResourceCleanUp(attach_clean)
|
||||
attach_waiter.wait_delete(vgw_id)
|
||||
|
||||
data = self.client.describe_vpn_gateways(VpnGatewayIds=[vgw_id])
|
||||
self.assertEqual(
|
||||
'detached',
|
||||
(data['VpnGateways'][0]['VpcAttachments'] or
|
||||
[{'State': 'detached'}])[0]['State'])
|
|
@ -1,881 +0,0 @@
|
|||
# Copyright 2014 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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 functools
|
||||
import logging
|
||||
import sys
|
||||
import time
|
||||
import traceback
|
||||
|
||||
import botocore.exceptions
|
||||
from oslo_log import log
|
||||
import six
|
||||
from tempest.lib import base
|
||||
from tempest.lib import exceptions
|
||||
import testtools
|
||||
|
||||
from ec2api_tempest_plugin import botocoreclient
|
||||
from ec2api_tempest_plugin import config as cfg
|
||||
|
||||
CONF = cfg.CONF
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
logging.getLogger('botocore').setLevel(logging.INFO)
|
||||
logging.getLogger(
|
||||
'botocore.vendored.requests.packages.urllib3.connectionpool'
|
||||
).setLevel(logging.WARNING)
|
||||
logging.getLogger('paramiko.transport').setLevel(logging.WARNING)
|
||||
|
||||
|
||||
class EC2Waiter(object):
|
||||
|
||||
def __init__(self, wait_func):
|
||||
self.wait_func = wait_func
|
||||
self.default_timeout = CONF.aws.build_timeout
|
||||
self.default_check_interval = CONF.aws.build_interval
|
||||
|
||||
def _state_wait(self, f, f_args=None, f_kwargs=None,
|
||||
final_set=set(), error_set=('error')):
|
||||
if not isinstance(final_set, set):
|
||||
final_set = set((final_set,))
|
||||
if not isinstance(error_set, set):
|
||||
error_set = set((error_set,))
|
||||
interval = self.default_check_interval
|
||||
start_time = time.time()
|
||||
args = f_args if f_args is not None else []
|
||||
kwargs = f_kwargs if f_kwargs is not None else {}
|
||||
try:
|
||||
old_status = status = f(*args, **kwargs)
|
||||
except exceptions.NotFound:
|
||||
old_status = status = "NotFound"
|
||||
while True:
|
||||
if status != old_status:
|
||||
LOG.info('State transition "%s" ==> "%s" %d second',
|
||||
old_status, status, time.time() - start_time)
|
||||
if status in final_set:
|
||||
return status
|
||||
if error_set is not None and status in error_set:
|
||||
raise testtools.TestCase.failureException(
|
||||
'State changes to error state! '
|
||||
'While waiting for %s at "%s"' %
|
||||
(final_set, status))
|
||||
dtime = time.time() - start_time
|
||||
if dtime > self.default_timeout:
|
||||
raise testtools.TestCase.failureException(
|
||||
'State change timeout exceeded! '
|
||||
'(%ds) While waiting for %s at "%s"' %
|
||||
(dtime, final_set, status))
|
||||
time.sleep(interval)
|
||||
interval += self.default_check_interval
|
||||
old_status = status
|
||||
try:
|
||||
status = f(*args, **kwargs)
|
||||
except exceptions.NotFound:
|
||||
status = "NotFound"
|
||||
|
||||
def _state_wait_gone(self, f, f_args=None, f_kwargs=None):
|
||||
interval = self.default_check_interval
|
||||
start_time = time.time()
|
||||
args = f_args if f_args is not None else []
|
||||
kwargs = f_kwargs if f_kwargs is not None else {}
|
||||
try:
|
||||
old_status = status = f(*args, **kwargs)
|
||||
while True:
|
||||
if status != old_status:
|
||||
LOG.info('State transition "%s" ==> "%s" %d second',
|
||||
old_status, status, time.time() - start_time)
|
||||
dtime = time.time() - start_time
|
||||
if dtime > self.default_timeout:
|
||||
raise testtools.TestCase.failureException(
|
||||
"State change timeout exceeded while waiting"
|
||||
" for deleting")
|
||||
time.sleep(interval)
|
||||
interval += self.default_check_interval
|
||||
old_status = status
|
||||
status = f(*args, **kwargs)
|
||||
except exceptions.NotFound:
|
||||
pass
|
||||
|
||||
def wait_available(self, obj_id, final_set=('available')):
|
||||
self._state_wait(self.wait_func, f_args=[obj_id],
|
||||
final_set=final_set)
|
||||
|
||||
def wait_delete(self, obj_id):
|
||||
self._state_wait_gone(self.wait_func, f_args=[obj_id])
|
||||
|
||||
def wait_no_exception(self, *args, **kwargs):
|
||||
interval = self.default_check_interval
|
||||
start_time = time.time()
|
||||
while True:
|
||||
try:
|
||||
self.wait_func(*args, **kwargs)
|
||||
return
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
dtime = time.time() - start_time
|
||||
if dtime > self.default_timeout:
|
||||
raise testtools.TestCase.failureException(
|
||||
"Timeout exceeded while waiting")
|
||||
time.sleep(interval)
|
||||
interval += self.default_check_interval
|
||||
|
||||
def wait_for_result(self, *args, **kwargs):
|
||||
interval = self.default_check_interval
|
||||
start_time = time.time()
|
||||
while True:
|
||||
result = self.wait_func(*args, **kwargs)
|
||||
if result:
|
||||
return result
|
||||
|
||||
dtime = time.time() - start_time
|
||||
if dtime > self.default_timeout:
|
||||
raise testtools.TestCase.failureException(
|
||||
"Timeout exceeded while waiting")
|
||||
time.sleep(interval)
|
||||
interval += self.default_check_interval
|
||||
|
||||
|
||||
def safe_setup(f):
|
||||
"""A decorator used to wrap the setUpClass for safe setup."""
|
||||
|
||||
def decorator(cls):
|
||||
try:
|
||||
f(cls)
|
||||
except Exception as se:
|
||||
exc_info = sys.exc_info()
|
||||
LOG.exception("setUpClass failed: %s" % se)
|
||||
try:
|
||||
cls.tearDownClass()
|
||||
except Exception as te:
|
||||
LOG.exception("tearDownClass failed: %s" % te)
|
||||
six.reraise(*exc_info)
|
||||
|
||||
return decorator
|
||||
|
||||
|
||||
def get_device_name_prefix(device_name):
|
||||
"""Return device name without device number.
|
||||
|
||||
/dev/sda1 -> /dev/sd
|
||||
/dev/vda -> /dev/vd
|
||||
"""
|
||||
dev_num_pos = 0
|
||||
while '0' <= device_name[dev_num_pos - 1] <= '9':
|
||||
dev_num_pos -= 1
|
||||
return device_name[:dev_num_pos - 1]
|
||||
|
||||
|
||||
class TesterStateHolder(object):
|
||||
|
||||
ec2_client = None
|
||||
_instance = None
|
||||
|
||||
def __new__(cls, *args, **kwargs):
|
||||
if not cls._instance:
|
||||
cls._instance = super(TesterStateHolder, cls).__new__(
|
||||
cls, *args, **kwargs)
|
||||
return cls._instance
|
||||
|
||||
_ec2_enabled = None
|
||||
_vpc_enabled = None
|
||||
|
||||
def get_ec2_enabled(self):
|
||||
if self._ec2_enabled is None:
|
||||
self._fill_attributes()
|
||||
return self._ec2_enabled
|
||||
|
||||
def get_vpc_enabled(self):
|
||||
if self._vpc_enabled is None:
|
||||
self._fill_attributes()
|
||||
return self._vpc_enabled
|
||||
|
||||
def _fill_attributes(self):
|
||||
self._ec2_enabled = False
|
||||
self._vpc_enabled = False
|
||||
data = self.ec2_client.describe_account_attributes()
|
||||
for item in data.get('AccountAttributes', []):
|
||||
if item['AttributeName'] == 'supported-platforms':
|
||||
for value in item['AttributeValues']:
|
||||
if value['AttributeValue'] == 'VPC':
|
||||
self._vpc_enabled = True
|
||||
if value['AttributeValue'] == 'EC2':
|
||||
self._ec2_enabled = True
|
||||
|
||||
|
||||
def skip_without_ec2(*args, **kwargs):
|
||||
"""A decorator useful to skip tests if EC2-classic is not supported."""
|
||||
def decorator(f):
|
||||
@functools.wraps(f)
|
||||
def wrapper(self, *func_args, **func_kwargs):
|
||||
if not TesterStateHolder().get_ec2_enabled():
|
||||
msg = "Skipped because EC2-classic is not enabled"
|
||||
raise testtools.TestCase.skipException(msg)
|
||||
return f(self, *func_args, **func_kwargs)
|
||||
return wrapper
|
||||
return decorator
|
||||
|
||||
|
||||
def skip_without_vpc(*args, **kwargs):
|
||||
"""A decorator useful to skip tests if VPC is not supported."""
|
||||
def decorator(f):
|
||||
@functools.wraps(f)
|
||||
def wrapper(self, *func_args, **func_kwargs):
|
||||
if not TesterStateHolder().get_vpc_enabled():
|
||||
msg = "Skipped because VPC is disabled"
|
||||
raise testtools.TestCase.skipException(msg)
|
||||
return f(self, *func_args, **func_kwargs)
|
||||
return wrapper
|
||||
return decorator
|
||||
|
||||
|
||||
def check_vpnaas_enabled():
|
||||
if not CONF.aws.vpnaas_enabled:
|
||||
msg = ("Skipped VPN test as vpnaas is not available")
|
||||
raise testtools.TestCase.skipException(msg)
|
||||
|
||||
|
||||
def skip_without_vpnaas_enabled(*args, **kwargs):
|
||||
"""A decorator useful to skip tests without specified network extension."""
|
||||
def decorator(f):
|
||||
@functools.wraps(f)
|
||||
def wrapper(self, *func_args, **func_kwargs):
|
||||
check_vpnaas_enabled()
|
||||
return f(self, *func_args, **func_kwargs)
|
||||
return wrapper
|
||||
return decorator
|
||||
|
||||
|
||||
class EC2TestCase(base.BaseTestCase):
|
||||
"""Recommended to use as base class for boto related test."""
|
||||
|
||||
# The trash contains cleanup functions and paramaters in tuples
|
||||
# (function, *args, **kwargs)
|
||||
_global_resource_trash_bin = {}
|
||||
_global_sequence = -1
|
||||
|
||||
@classmethod
|
||||
@safe_setup
|
||||
def setUpClass(cls):
|
||||
super(EC2TestCase, cls).setUpClass()
|
||||
if not CONF.service_available.ec2api:
|
||||
raise cls.skipException("ec2api is disabled")
|
||||
|
||||
cls.client = botocoreclient.get_ec2_client(
|
||||
CONF.aws.ec2_url, CONF.aws.aws_region,
|
||||
CONF.aws.aws_access, CONF.aws.aws_secret,
|
||||
CONF.aws.ca_bundle)
|
||||
cls.s3_client = botocoreclient.get_s3_client(
|
||||
CONF.aws.s3_url, CONF.aws.aws_region,
|
||||
CONF.aws.aws_access, CONF.aws.aws_secret,
|
||||
CONF.aws.ca_bundle)
|
||||
TesterStateHolder().ec2_client = cls.client
|
||||
|
||||
@classmethod
|
||||
def addResourceCleanUpStatic(cls, function, *args, **kwargs):
|
||||
"""Adds CleanUp callable, used by tearDownClass.
|
||||
|
||||
Recommended to a use (deep)copy on the mutable args.
|
||||
"""
|
||||
tb = traceback.extract_stack(limit=2)
|
||||
cls._global_sequence = cls._global_sequence + 1
|
||||
cls._global_resource_trash_bin[cls._global_sequence] = (function,
|
||||
args, kwargs,
|
||||
tb[0])
|
||||
return cls._global_sequence
|
||||
|
||||
def setUp(self):
|
||||
super(EC2TestCase, self).setUp()
|
||||
self._resource_trash_bin = {}
|
||||
self._sequence = -1
|
||||
|
||||
def tearDown(self):
|
||||
fail_count = self.cleanUp(self._resource_trash_bin)
|
||||
super(EC2TestCase, self).tearDown()
|
||||
if fail_count:
|
||||
raise exceptions.TempestException("%d cleanUp operation failed"
|
||||
% fail_count)
|
||||
|
||||
def addResourceCleanUp(self, function, *args, **kwargs):
|
||||
"""Adds CleanUp callable, used by tearDown.
|
||||
|
||||
Recommended to a use (deep)copy on the mutable args.
|
||||
"""
|
||||
tb = traceback.extract_stack(limit=2)[0]
|
||||
self._sequence = self._sequence + 1
|
||||
self._resource_trash_bin[self._sequence] = (function, args, kwargs, tb)
|
||||
|
||||
LOG.debug("For cleaning up: %s\n From: %s" %
|
||||
(self.friendly_function_call_str(function, *args, **kwargs),
|
||||
str((tb[0], tb[1], tb[2]))))
|
||||
|
||||
return self._sequence
|
||||
|
||||
def cancelResourceCleanUp(self, key):
|
||||
"""Cancel Clean up request."""
|
||||
del self._resource_trash_bin[key]
|
||||
|
||||
# NOTE(andrey-mp): if ERROR in responce_code then treat object as deleted
|
||||
_VALID_CLEANUP_ERRORS = [
|
||||
'NotFound',
|
||||
'Gateway.NotAttached'
|
||||
]
|
||||
|
||||
# NOTE(andrey-mp): function must return boolean - should we retry
|
||||
# deleting or not
|
||||
_HOOKED_CLEANUP_ERRORS = {
|
||||
('delete_vpc', 'DependencyViolation'): (
|
||||
'delete_vpc_failed',
|
||||
lambda kwargs: kwargs['VpcId'])
|
||||
}
|
||||
|
||||
_CLEANUP_WAITERS = {
|
||||
'delete_vpc': (
|
||||
'get_vpc_waiter',
|
||||
lambda kwargs: kwargs['VpcId']),
|
||||
'delete_subnet': (
|
||||
'get_subnet_waiter',
|
||||
lambda kwargs: kwargs['SubnetId']),
|
||||
'delete_network_interface': (
|
||||
'get_network_interface_waiter',
|
||||
lambda kwargs: kwargs['NetworkInterfaceId']),
|
||||
'terminate_instances': (
|
||||
'get_instance_waiter',
|
||||
lambda kwargs: kwargs['InstanceIds'][0]),
|
||||
'delete_volume': (
|
||||
'get_volume_waiter',
|
||||
lambda kwargs: kwargs['VolumeId']),
|
||||
'detach_volume': (
|
||||
'get_volume_attachment_waiter',
|
||||
lambda kwargs: kwargs['VolumeId']),
|
||||
'delete_snapshot': (
|
||||
'get_snapshot_waiter',
|
||||
lambda kwargs: kwargs['SnapshotId']),
|
||||
'deregister_image': (
|
||||
'get_image_waiter',
|
||||
lambda kwargs: kwargs['ImageId']),
|
||||
'detach_vpn_gateway': (
|
||||
'get_vpn_gateway_attachment_waiter',
|
||||
lambda kwargs: kwargs['VpnGatewayId']),
|
||||
'delete_vpn_connection': (
|
||||
'get_vpn_connection_waiter',
|
||||
lambda kwargs: kwargs['VpnConnectionId']),
|
||||
'delete_customer_gateway': (
|
||||
'get_customer_gateway_waiter',
|
||||
lambda kwargs: kwargs['CustomerGatewayId']),
|
||||
'delete_vpn_gateway': (
|
||||
'get_vpn_gateway_waiter',
|
||||
lambda kwargs: kwargs['VpnGatewayId']),
|
||||
'disassociate_address': (
|
||||
'get_address_assoc_waiter',
|
||||
lambda kwargs: kwargs),
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
fail_count = cls.cleanUp(cls._global_resource_trash_bin)
|
||||
super(EC2TestCase, cls).tearDownClass()
|
||||
if fail_count:
|
||||
raise exceptions.TempestException("%d cleanUp operation failed"
|
||||
% fail_count)
|
||||
|
||||
@classmethod
|
||||
def cleanUp(cls, trash_bin):
|
||||
"""Calls the callables added by addResourceCleanUp,
|
||||
|
||||
when you overwire this function dont't forget to call this too.
|
||||
"""
|
||||
fail_count = 0
|
||||
trash_keys = sorted(trash_bin, reverse=True)
|
||||
for key in trash_keys:
|
||||
(function, pos_args, kw_args, tb) = trash_bin[key]
|
||||
try:
|
||||
LOG.debug("Cleaning up: %s\n From: %s" %
|
||||
(cls.friendly_function_call_str(function, *pos_args,
|
||||
**kw_args),
|
||||
str((tb[0], tb[1], tb[2]))))
|
||||
res = cls.cleanUpItem(function, pos_args, kw_args)
|
||||
if not res:
|
||||
fail_count += 1
|
||||
LOG.error('Failure in cleanup for: %s' % str(kw_args))
|
||||
except BaseException:
|
||||
fail_count += 1
|
||||
LOG.exception('Failure in cleanup for: %s' % str(kw_args))
|
||||
finally:
|
||||
del trash_bin[key]
|
||||
return fail_count
|
||||
|
||||
@classmethod
|
||||
def cleanUpItem(cls, function, pos_args, kw_args):
|
||||
attempts_left = 10
|
||||
interval = 1
|
||||
deleted = False
|
||||
while not deleted and attempts_left > 0:
|
||||
try:
|
||||
function(*pos_args, **kw_args)
|
||||
deleted = True
|
||||
|
||||
key = function.__name__
|
||||
if key in cls._CLEANUP_WAITERS:
|
||||
(waiter, obj_id) = cls._CLEANUP_WAITERS[key]
|
||||
waiter = getattr(cls, waiter)
|
||||
obj_id = obj_id(kw_args)
|
||||
try:
|
||||
waiter().wait_delete(obj_id)
|
||||
except botocore.exceptions.ClientError:
|
||||
LOG.exception('Exception occurred in cleanup waiting')
|
||||
return False
|
||||
except botocore.exceptions.ClientError as e:
|
||||
error_code = e.response['Error']['Code']
|
||||
for err in cls._VALID_CLEANUP_ERRORS:
|
||||
if err in error_code:
|
||||
deleted = True
|
||||
break
|
||||
else:
|
||||
hook_res = False
|
||||
key = (function.__name__, error_code)
|
||||
if key in cls._HOOKED_CLEANUP_ERRORS:
|
||||
(hook, obj_id) = cls._HOOKED_CLEANUP_ERRORS[key]
|
||||
hook = getattr(cls, hook)
|
||||
obj_id = obj_id(kw_args)
|
||||
hook_res = hook(obj_id)
|
||||
if not hook_res:
|
||||
LOG.error('Cleanup failed: %s', e, exc_info=True)
|
||||
return False
|
||||
LOG.error('Retrying cleanup due to: %s', e)
|
||||
time.sleep(interval)
|
||||
attempts_left -= 1
|
||||
interval += 1
|
||||
|
||||
return deleted
|
||||
|
||||
@classmethod
|
||||
def friendly_function_name_simple(cls, call_able):
|
||||
name = ""
|
||||
if hasattr(call_able, "im_class"):
|
||||
name += call_able.im_class.__name__ + "."
|
||||
name += call_able.__name__
|
||||
return name
|
||||
|
||||
@classmethod
|
||||
def friendly_function_call_str(cls, call_able, *args, **kwargs):
|
||||
string = cls.friendly_function_name_simple(call_able)
|
||||
string += "(" + ", ".join(map(str, args))
|
||||
if len(kwargs):
|
||||
if len(args):
|
||||
string += ", "
|
||||
string += ", ".join("=".join(map(str, (key, value)))
|
||||
for (key, value) in kwargs.items())
|
||||
return string + ")"
|
||||
|
||||
@classmethod
|
||||
def _vpc_get_state(cls, vpc_id):
|
||||
try:
|
||||
data = cls.client.describe_vpcs(VpcIds=[vpc_id])
|
||||
if not data['Vpcs']:
|
||||
raise exceptions.NotFound()
|
||||
return data['Vpcs'][0]['State']
|
||||
except botocore.exceptions.ClientError:
|
||||
error_code = sys.exc_info()[1].response['Error']['Code']
|
||||
if error_code == 'InvalidVpcID.NotFound':
|
||||
raise exceptions.NotFound()
|
||||
raise
|
||||
|
||||
@classmethod
|
||||
def get_vpc_waiter(cls):
|
||||
return EC2Waiter(cls._vpc_get_state)
|
||||
|
||||
@classmethod
|
||||
def _subnet_get_state(cls, subnet_id):
|
||||
try:
|
||||
data = cls.client.describe_subnets(SubnetIds=[subnet_id])
|
||||
if not data['Subnets']:
|
||||
raise exceptions.NotFound()
|
||||
return data['Subnets'][0]['State']
|
||||
except botocore.exceptions.ClientError:
|
||||
error_code = sys.exc_info()[1].response['Error']['Code']
|
||||
if error_code == 'InvalidSubnetID.NotFound':
|
||||
raise exceptions.NotFound()
|
||||
raise
|
||||
|
||||
@classmethod
|
||||
def get_subnet_waiter(cls):
|
||||
return EC2Waiter(cls._subnet_get_state)
|
||||
|
||||
@classmethod
|
||||
def _address_assoc_get_state(cls, kwargs):
|
||||
try:
|
||||
ip = kwargs.get('PublicIp')
|
||||
alloc_id = kwargs.get('AllocationId')
|
||||
assoc_id = kwargs.get('AssociationId')
|
||||
if ip:
|
||||
data = cls.client.describe_addresses(PublicIps=[ip])
|
||||
elif alloc_id:
|
||||
data = cls.client.describe_addresses(AllocationIds=[alloc_id])
|
||||
elif assoc_id:
|
||||
data = cls.client.describe_addresses(
|
||||
Filters=[{'Name': 'association-id', 'Values': [assoc_id]}])
|
||||
|
||||
LOG.debug('Addresses: %s' % str(data.get('Addresses')))
|
||||
|
||||
if ('Addresses' in data and len(data['Addresses']) == 1 and
|
||||
data['Addresses'][0].get('InstanceId')):
|
||||
return 'available'
|
||||
raise exceptions.NotFound()
|
||||
except botocore.exceptions.ClientError:
|
||||
raise exceptions.NotFound()
|
||||
|
||||
@classmethod
|
||||
def get_address_assoc_waiter(cls):
|
||||
return EC2Waiter(cls._address_assoc_get_state)
|
||||
|
||||
@classmethod
|
||||
def _instance_get_state(cls, instance_id):
|
||||
try:
|
||||
data = cls.client.describe_instances(InstanceIds=[instance_id])
|
||||
if not data['Reservations']:
|
||||
raise exceptions.NotFound()
|
||||
if not data['Reservations'][0]['Instances']:
|
||||
raise exceptions.NotFound()
|
||||
state = data['Reservations'][0]['Instances'][0]['State']['Name']
|
||||
if state != 'terminated':
|
||||
return state
|
||||
raise exceptions.NotFound()
|
||||
except botocore.exceptions.ClientError:
|
||||
error_code = sys.exc_info()[1].response['Error']['Code']
|
||||
if error_code == 'InvalidInstanceID.NotFound':
|
||||
raise exceptions.NotFound()
|
||||
raise
|
||||
|
||||
@classmethod
|
||||
def get_instance_waiter(cls):
|
||||
return EC2Waiter(cls._instance_get_state)
|
||||
|
||||
@classmethod
|
||||
def _network_interface_get_state(cls, ni_id):
|
||||
try:
|
||||
data = cls.client.describe_network_interfaces(
|
||||
NetworkInterfaceIds=[ni_id])
|
||||
if not data['NetworkInterfaces']:
|
||||
raise exceptions.NotFound()
|
||||
return data['NetworkInterfaces'][0]['Status']
|
||||
except botocore.exceptions.ClientError:
|
||||
error_code = sys.exc_info()[1].response['Error']['Code']
|
||||
if error_code == 'InvalidNetworkInterfaceID.NotFound':
|
||||
raise exceptions.NotFound()
|
||||
raise
|
||||
|
||||
@classmethod
|
||||
def get_network_interface_waiter(cls):
|
||||
return EC2Waiter(cls._network_interface_get_state)
|
||||
|
||||
@classmethod
|
||||
def _volume_get_state(cls, volume_id):
|
||||
try:
|
||||
data = cls.client.describe_volumes(VolumeIds=[volume_id])
|
||||
if not data['Volumes']:
|
||||
raise exceptions.NotFound()
|
||||
return data['Volumes'][0]['State']
|
||||
except botocore.exceptions.ClientError:
|
||||
error_code = sys.exc_info()[1].response['Error']['Code']
|
||||
if error_code == 'InvalidVolume.NotFound':
|
||||
raise exceptions.NotFound()
|
||||
raise
|
||||
|
||||
@classmethod
|
||||
def get_volume_waiter(cls):
|
||||
return EC2Waiter(cls._volume_get_state)
|
||||
|
||||
@classmethod
|
||||
def _volume_attachment_get_state(cls, volume_id):
|
||||
try:
|
||||
data = cls.client.describe_volumes(VolumeIds=[volume_id])
|
||||
volume = data['Volumes'][0]
|
||||
if 'Attachments' in volume and len(volume['Attachments']) > 0:
|
||||
return volume['Attachments'][0]['State']
|
||||
raise exceptions.NotFound()
|
||||
except botocore.exceptions.ClientError:
|
||||
error_code = sys.exc_info()[1].response['Error']['Code']
|
||||
if error_code == 'InvalidVolume.NotFound':
|
||||
raise exceptions.NotFound()
|
||||
raise
|
||||
|
||||
@classmethod
|
||||
def get_volume_attachment_waiter(cls):
|
||||
return EC2Waiter(cls._volume_attachment_get_state)
|
||||
|
||||
@classmethod
|
||||
def _snapshot_get_state(cls, snapshot_id):
|
||||
try:
|
||||
data = cls.client.describe_snapshots(SnapshotIds=[snapshot_id])
|
||||
if not data['Snapshots']:
|
||||
raise exceptions.NotFound()
|
||||
return data['Snapshots'][0]['State']
|
||||
except botocore.exceptions.ClientError:
|
||||
error_code = sys.exc_info()[1].response['Error']['Code']
|
||||
if error_code == 'InvalidSnapshot.NotFound':
|
||||
raise exceptions.NotFound()
|
||||
raise
|
||||
|
||||
@classmethod
|
||||
def get_snapshot_waiter(cls):
|
||||
return EC2Waiter(cls._snapshot_get_state)
|
||||
|
||||
@classmethod
|
||||
def _image_get_state(cls, image_id):
|
||||
try:
|
||||
data = cls.client.describe_images(ImageIds=[image_id])
|
||||
if not data['Images']:
|
||||
raise exceptions.NotFound()
|
||||
return data['Images'][0]['State']
|
||||
except botocore.exceptions.ClientError:
|
||||
error_code = sys.exc_info()[1].response['Error']['Code']
|
||||
if error_code == 'InvalidAMIID.NotFound':
|
||||
raise exceptions.NotFound()
|
||||
raise
|
||||
|
||||
@classmethod
|
||||
def get_image_waiter(cls):
|
||||
return EC2Waiter(cls._image_get_state)
|
||||
|
||||
@classmethod
|
||||
def _vpn_gateway_get_attachment_state(cls, vpn_gateway_id):
|
||||
try:
|
||||
data = cls.client.describe_vpn_gateways(
|
||||
VpnGatewayIds=[vpn_gateway_id])
|
||||
attachments = data['VpnGateways'][0].get('VpcAttachments')
|
||||
if (not attachments or
|
||||
attachments[0]['State'] == 'detached'):
|
||||
raise exceptions.NotFound()
|
||||
return attachments[0]['State']
|
||||
except botocore.exceptions.ClientError as ex:
|
||||
error_code = ex.response['Error']['Code']
|
||||
if error_code == 'InvalidVpnGatewayID.NotFound':
|
||||
raise exceptions.NotFound()
|
||||
raise
|
||||
|
||||
@classmethod
|
||||
def get_vpn_gateway_attachment_waiter(cls):
|
||||
return EC2Waiter(cls._vpn_gateway_get_attachment_state)
|
||||
|
||||
@classmethod
|
||||
def _vpn_object_get_state(cls, func, kwargs, data_key, error_not_found):
|
||||
# NOTE(andrey-mp): use this for vpn_connection, vpn_gateway,
|
||||
# customer_gateway due to similar states
|
||||
try:
|
||||
data = func(**kwargs)
|
||||
if not data[data_key]:
|
||||
raise exceptions.NotFound()
|
||||
if data[data_key][0]['State'] == 'deleted':
|
||||
raise exceptions.NotFound()
|
||||
return data[data_key][0]['State']
|
||||
except botocore.exceptions.ClientError as ex:
|
||||
error_code = ex.response['Error']['Code']
|
||||
if error_code == error_not_found:
|
||||
raise exceptions.NotFound()
|
||||
raise
|
||||
|
||||
@classmethod
|
||||
def _vpn_connection_get_state(cls, vpn_connection_id):
|
||||
return cls._vpn_object_get_state(
|
||||
cls.client.describe_vpn_connections,
|
||||
{'VpnConnectionIds': [vpn_connection_id]},
|
||||
'VpnConnections',
|
||||
'InvalidVpnConnectionID.NotFound')
|
||||
|
||||
@classmethod
|
||||
def get_vpn_connection_waiter(cls):
|
||||
return EC2Waiter(cls._vpn_connection_get_state)
|
||||
|
||||
@classmethod
|
||||
def _customer_gateway_get_state(cls, customer_gateway_id):
|
||||
return cls._vpn_object_get_state(
|
||||
cls.client.describe_customer_gateways,
|
||||
{'CustomerGatewayIds': [customer_gateway_id]},
|
||||
'CustomerGateways',
|
||||
'InvalidCustomerGatewayID.NotFound')
|
||||
|
||||
@classmethod
|
||||
def get_customer_gateway_waiter(cls):
|
||||
return EC2Waiter(cls._customer_gateway_get_state)
|
||||
|
||||
@classmethod
|
||||
def _vpn_gateway_get_state(cls, vpn_gateway_id):
|
||||
return cls._vpn_object_get_state(
|
||||
cls.client.describe_vpn_gateways,
|
||||
{'VpnGatewayIds': [vpn_gateway_id]},
|
||||
'VpnGateways',
|
||||
'InvalidVpnGatewayID.NotFound')
|
||||
|
||||
@classmethod
|
||||
def get_vpn_gateway_waiter(cls):
|
||||
return EC2Waiter(cls._vpn_gateway_get_state)
|
||||
|
||||
@classmethod
|
||||
def _vpn_connection_get_route_state(cls, vpn_connection_id,
|
||||
destination_cidr_block=None):
|
||||
try:
|
||||
data = cls.client.describe_vpn_connections(
|
||||
VpnConnectionIds=[vpn_connection_id])
|
||||
try:
|
||||
route = next(
|
||||
r for r in data['VpnConnections'][0]['Routes']
|
||||
if r['DestinationCidrBlock'] == destination_cidr_block)
|
||||
except StopIteration:
|
||||
raise exceptions.NotFound()
|
||||
if route['State'] == 'deleted':
|
||||
raise exceptions.NotFound()
|
||||
return route['State']
|
||||
except botocore.exceptions.ClientError as ex:
|
||||
error_code = ex.response['Error']['Code']
|
||||
if error_code == 'InvalidVpnGatewayID.NotFound':
|
||||
raise exceptions.NotFound()
|
||||
raise
|
||||
|
||||
@classmethod
|
||||
def get_vpn_connection_route_waiter(cls, destination_cidr_block):
|
||||
return EC2Waiter(
|
||||
functools.partial(cls._vpn_connection_get_route_state,
|
||||
destination_cidr_block=destination_cidr_block))
|
||||
|
||||
@classmethod
|
||||
def _vpn_connection_get_tunnel_up_state(cls, vpn_connection_id):
|
||||
data = cls.client.describe_vpn_connections(
|
||||
VpnConnectionIds=[vpn_connection_id])
|
||||
for item in data['VpnConnections'][0].get('VgwTelemetry', []):
|
||||
if 'UP' == item['Status']:
|
||||
return 'UP'
|
||||
raise exceptions.NotFound()
|
||||
|
||||
@classmethod
|
||||
def get_vpn_connection_tunnel_waiter(cls):
|
||||
return EC2Waiter(cls._vpn_connection_get_tunnel_up_state)
|
||||
|
||||
@classmethod
|
||||
def delete_vpc_failed(cls, vpc_id):
|
||||
try:
|
||||
LOG.warning('VpnGateways: ' +
|
||||
str(cls.client.describe_vpn_gateways(
|
||||
Filters=[{'Name': 'attachment.vpc-id', 'Values': [vpc_id]}]
|
||||
)['VpnGateways']))
|
||||
LOG.warning('RouteTables: ' +
|
||||
str(cls.client.describe_route_tables(
|
||||
Filters=[{'Name': 'vpc-id', 'Values': [vpc_id]}]
|
||||
)['RouteTables']))
|
||||
return True
|
||||
except Exception:
|
||||
LOG.exception('Error occurred during "delete_vpc_failed" hook')
|
||||
return False
|
||||
|
||||
def assertEmpty(self, list_obj, msg=None):
|
||||
self.assertTrue(len(list_obj) == 0, msg)
|
||||
|
||||
def assertNotEmpty(self, list_obj, msg=None):
|
||||
self.assertTrue(len(list_obj) > 0, msg)
|
||||
|
||||
def assertRaises(self, error_code, fn, rollback_fn=None, **kwargs):
|
||||
try:
|
||||
fn_data = fn(**kwargs)
|
||||
if rollback_fn:
|
||||
try:
|
||||
rollback_fn(fn_data)
|
||||
except Exception:
|
||||
LOG.exception('Rollback failed')
|
||||
msg = ("%s hasn't returned exception for params %s"
|
||||
% (str(fn.__name__), str(kwargs)))
|
||||
raise self.failureException(msg)
|
||||
except botocore.exceptions.ClientError as e:
|
||||
self.assertEqual(error_code, e.response['Error']['Code'])
|
||||
|
||||
# NOTE(andrey-mp): Helpers zone
|
||||
|
||||
def get_instance(self, instance_id):
|
||||
data = self.client.describe_instances(InstanceIds=[instance_id])
|
||||
self.assertEqual(1, len(data.get('Reservations', [])))
|
||||
instances = data['Reservations'][0].get('Instances', [])
|
||||
self.assertEqual(1, len(instances))
|
||||
return instances[0]
|
||||
|
||||
def get_instance_bdm(self, instance_id, device_name):
|
||||
# device_name=None means getting bdm of root instance device
|
||||
instance = self.get_instance(instance_id)
|
||||
if not device_name:
|
||||
device_name = instance.get('RootDeviceName')
|
||||
if not device_name:
|
||||
return None
|
||||
bdms = instance.get('BlockDeviceMappings')
|
||||
if bdms is None:
|
||||
return None
|
||||
bdt = [bdt for bdt in bdms if bdt['DeviceName'] == device_name]
|
||||
return None if len(bdt) == 0 else bdt[0]
|
||||
|
||||
def run_instance(self, clean_dict=None, **kwargs):
|
||||
kwargs.setdefault('ImageId', CONF.aws.image_id)
|
||||
kwargs.setdefault('InstanceType', CONF.aws.instance_type)
|
||||
kwargs.setdefault('Placement', {'AvailabilityZone': CONF.aws.aws_zone})
|
||||
kwargs['MinCount'] = 1
|
||||
kwargs['MaxCount'] = 1
|
||||
data = self.client.run_instances(*[], **kwargs)
|
||||
instance_id = data['Instances'][0]['InstanceId']
|
||||
res_clean = self.addResourceCleanUp(self.client.terminate_instances,
|
||||
InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_available(instance_id,
|
||||
final_set=('running'))
|
||||
|
||||
if clean_dict is not None:
|
||||
clean_dict['instance'] = res_clean
|
||||
|
||||
return instance_id
|
||||
|
||||
def create_vpc_and_subnet(self, cidr):
|
||||
data = self.client.create_vpc(CidrBlock=cidr)
|
||||
vpc_id = data['Vpc']['VpcId']
|
||||
self.addResourceCleanUp(self.client.delete_vpc, VpcId=vpc_id)
|
||||
self.get_vpc_waiter().wait_available(vpc_id)
|
||||
|
||||
data = self.client.create_subnet(VpcId=vpc_id, CidrBlock=cidr,
|
||||
AvailabilityZone=CONF.aws.aws_zone)
|
||||
subnet_id = data['Subnet']['SubnetId']
|
||||
self.addResourceCleanUp(self.client.delete_subnet, SubnetId=subnet_id)
|
||||
|
||||
return vpc_id, subnet_id
|
||||
|
||||
def prepare_route(self, vpc_id, gw_id):
|
||||
data = self.client.describe_route_tables(
|
||||
Filters=[{'Name': 'vpc-id', 'Values': [vpc_id]}])
|
||||
self.assertEqual(1, len(data['RouteTables']))
|
||||
route_table_id = data['RouteTables'][0]['RouteTableId']
|
||||
|
||||
kwargs = {
|
||||
'DestinationCidrBlock': '0.0.0.0/0',
|
||||
'RouteTableId': route_table_id,
|
||||
'GatewayId': gw_id
|
||||
}
|
||||
self.client.create_route(*[], **kwargs)
|
||||
|
||||
return route_table_id
|
||||
|
||||
def create_and_attach_internet_gateway(self, vpc_id):
|
||||
data = self.client.create_internet_gateway()
|
||||
gw_id = data['InternetGateway']['InternetGatewayId']
|
||||
self.addResourceCleanUp(self.client.delete_internet_gateway,
|
||||
InternetGatewayId=gw_id)
|
||||
data = self.client.attach_internet_gateway(VpcId=vpc_id,
|
||||
InternetGatewayId=gw_id)
|
||||
self.addResourceCleanUp(self.client.detach_internet_gateway,
|
||||
VpcId=vpc_id,
|
||||
InternetGatewayId=gw_id)
|
||||
|
||||
return gw_id
|
|
@ -1,45 +0,0 @@
|
|||
# Copyright 2015 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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 botocore.session
|
||||
from oslo_config import types
|
||||
|
||||
|
||||
def _get_client(client_name, url, region, access, secret, ca_bundle):
|
||||
connection_data = {
|
||||
'config_file': (None, 'AWS_CONFIG_FILE', None, None),
|
||||
'region': ('region', 'AWS_DEFAULT_REGION', region, None),
|
||||
}
|
||||
session = botocore.session.get_session(connection_data)
|
||||
kwargs = {
|
||||
'region_name': region,
|
||||
'endpoint_url': url,
|
||||
'aws_access_key_id': access,
|
||||
'aws_secret_access_key': secret
|
||||
}
|
||||
if ca_bundle:
|
||||
try:
|
||||
kwargs['verify'] = types.Boolean()(ca_bundle)
|
||||
except Exception:
|
||||
kwargs['verify'] = ca_bundle
|
||||
return session.create_client(client_name, **kwargs)
|
||||
|
||||
|
||||
def get_ec2_client(url, region, access, secret, ca_bundle=None):
|
||||
return _get_client('ec2', url, region, access, secret, ca_bundle)
|
||||
|
||||
|
||||
def get_s3_client(url, region, access, secret, ca_bundle=None):
|
||||
return _get_client('s3', url, region, access, secret, ca_bundle)
|
|
@ -1,88 +0,0 @@
|
|||
# Copyright 2012 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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 logging as std_logging
|
||||
import os
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
|
||||
from ec2api_tempest_plugin import config_opts
|
||||
|
||||
|
||||
LOG = logging.getLogger('ec2api')
|
||||
|
||||
|
||||
# this should never be called outside of this class
|
||||
class ConfigPrivate(object):
|
||||
"""Provides OpenStack configuration information."""
|
||||
|
||||
DEFAULT_CONFIG_FILE = "functional_tests.conf"
|
||||
|
||||
def __init__(self):
|
||||
"""Initialize a configuration from a conf directory and conf file."""
|
||||
super(ConfigPrivate, self).__init__()
|
||||
|
||||
# if this was run from tempest runner then config already parsed
|
||||
if config_opts.aws_group.name in cfg.CONF:
|
||||
self.aws = cfg.CONF.aws
|
||||
self.service_available = cfg.CONF.service_available
|
||||
return
|
||||
|
||||
# Environment variables override defaults...
|
||||
conf_file = os.environ.get('TEST_CONFIG', self.DEFAULT_CONFIG_FILE)
|
||||
conf_dirs = list()
|
||||
if os.environ.get('TEST_CONFIG_DIR'):
|
||||
conf_dirs.append(os.environ.get('TEST_CONFIG_DIR'))
|
||||
conf_dirs.append('.')
|
||||
conf_dirs.append(os.path.dirname(os.path.dirname(
|
||||
os.path.dirname(os.path.dirname(__file__)))))
|
||||
for _dir in conf_dirs:
|
||||
path = os.path.join(_dir, conf_file)
|
||||
if os.path.isfile(path):
|
||||
break
|
||||
else:
|
||||
raise Exception('Config could not be found')
|
||||
|
||||
LOG.info("Using ec2api config file %s" % path)
|
||||
conf = cfg.CONF
|
||||
conf([], project='ec2api', default_config_files=[path])
|
||||
|
||||
conf.register_group(config_opts.aws_group)
|
||||
group_name = config_opts.aws_group.name
|
||||
for opt in config_opts.AWSGroup:
|
||||
conf.register_opt(opt, group=group_name)
|
||||
self.aws = cfg.CONF.aws
|
||||
|
||||
conf.register_group(config_opts.service_available_group)
|
||||
group_name = config_opts.service_available_group.name
|
||||
for opt in config_opts.ServiceAvailableGroup:
|
||||
conf.register_opt(opt, group=group_name)
|
||||
self.service_available = cfg.CONF.service_available
|
||||
|
||||
conf.log_opt_values(LOG, std_logging.DEBUG)
|
||||
|
||||
|
||||
class ConfigProxy(object):
|
||||
_config = None
|
||||
|
||||
def __getattr__(self, attr):
|
||||
if not self._config:
|
||||
self._config = ConfigPrivate()
|
||||
|
||||
return getattr(self._config, attr)
|
||||
|
||||
|
||||
CONF = ConfigProxy()
|
|
@ -1,99 +0,0 @@
|
|||
# Copyright 2012 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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.
|
||||
|
||||
from oslo_config import cfg
|
||||
|
||||
service_available_group = cfg.OptGroup(name="service_available",
|
||||
title="Available OpenStack Services")
|
||||
|
||||
ServiceAvailableGroup = [
|
||||
cfg.BoolOpt("ec2api",
|
||||
default=True,
|
||||
help="Whether or not ec2-api is expected to be available"),
|
||||
]
|
||||
|
||||
|
||||
aws_group = cfg.OptGroup(name='aws',
|
||||
title='AWS options')
|
||||
AWSGroup = [
|
||||
cfg.StrOpt('ec2_url',
|
||||
default="http://localhost:8788/",
|
||||
help="EC2 URL"),
|
||||
cfg.StrOpt('s3_url',
|
||||
default="http://localhost:3334/",
|
||||
help="S3 URL"),
|
||||
cfg.StrOpt('ca_bundle',
|
||||
default=None,
|
||||
help="The CA certificate bundle to use when verifying "
|
||||
"SSL certificates. Or True/False to pass to botocore."),
|
||||
cfg.StrOpt('aws_secret',
|
||||
default=None,
|
||||
help="AWS Secret Key",
|
||||
secret=True),
|
||||
cfg.StrOpt('aws_access',
|
||||
default=None,
|
||||
help="AWS Access Key"),
|
||||
cfg.StrOpt('aws_region',
|
||||
default="RegionOne",
|
||||
help="AWS region for EC2 tests"),
|
||||
cfg.StrOpt('aws_zone',
|
||||
default='nova',
|
||||
help="AWS zone inside region for EC2 tests"),
|
||||
cfg.IntOpt('build_timeout',
|
||||
default=120,
|
||||
help="Status Change Timeout"),
|
||||
cfg.IntOpt('build_interval',
|
||||
default=1,
|
||||
help="Status Change Test Interval"),
|
||||
cfg.StrOpt('instance_type',
|
||||
default="m1.tiny",
|
||||
help="Instance type"),
|
||||
cfg.StrOpt('instance_type_alt',
|
||||
default=None,
|
||||
help="Instance type"),
|
||||
cfg.StrOpt('image_id',
|
||||
default=None,
|
||||
help="Image ID for instance running(can be cirros). "
|
||||
"It must be any instance with instance-store "
|
||||
"root device type."),
|
||||
cfg.StrOpt('ebs_image_id',
|
||||
default=None,
|
||||
help="EBS Image ID for testing snapshots, volumes, instances."),
|
||||
cfg.StrOpt('image_user',
|
||||
default='cirros',
|
||||
help="User for sshing into instance based on configured image"),
|
||||
cfg.StrOpt('image_id_ubuntu',
|
||||
default=None,
|
||||
help="Fully functional image ID for instance running. "
|
||||
"For some tests it must be ubuntu-trusty-i386."),
|
||||
cfg.StrOpt('image_user_ubuntu',
|
||||
default='ubuntu',
|
||||
help="User for sshing into instance based on configured image"),
|
||||
cfg.BoolOpt('run_incompatible_tests',
|
||||
default=False,
|
||||
help='Will run all tests plus incompatible with Amazon.'),
|
||||
cfg.BoolOpt('run_long_tests',
|
||||
default=False,
|
||||
help='Will run all long tests also.'),
|
||||
cfg.StrOpt('ami_image_location',
|
||||
default=None,
|
||||
help="S3 URL with manifest of AMI Machine Image."),
|
||||
cfg.BoolOpt('run_ssh',
|
||||
default=True,
|
||||
help='Can block all tests that wants to ssh into instance.'),
|
||||
cfg.BoolOpt('vpnaas_enabled',
|
||||
default=False,
|
||||
help='Enable VPN-related tests'),
|
||||
]
|
|
@ -1,52 +0,0 @@
|
|||
# Copyright 2012 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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
|
||||
|
||||
from tempest import config
|
||||
from tempest.test_discover import plugins
|
||||
|
||||
from ec2api_tempest_plugin import config_opts as aws_config
|
||||
|
||||
|
||||
class AWSTempestPlugin(plugins.TempestPlugin):
|
||||
def load_tests(self):
|
||||
base_path = os.path.split(os.path.dirname(
|
||||
os.path.abspath(__file__)))[0]
|
||||
test_dir = "ec2api_tempest_plugin"
|
||||
full_test_dir = os.path.join(base_path, test_dir)
|
||||
return full_test_dir, base_path
|
||||
|
||||
def register_opts(self, conf):
|
||||
group_name = aws_config.service_available_group.name
|
||||
if group_name not in conf:
|
||||
config.register_opt_group(
|
||||
conf, aws_config.service_available_group,
|
||||
aws_config.ServiceAvailableGroup)
|
||||
else:
|
||||
for opt in aws_config.ServiceAvailableGroup:
|
||||
conf.register_opt(opt, group=group_name)
|
||||
|
||||
if aws_config.aws_group.name not in conf:
|
||||
config.register_opt_group(conf, aws_config.aws_group,
|
||||
aws_config.AWSGroup)
|
||||
|
||||
def get_opt_lists(self):
|
||||
return [
|
||||
(aws_config.service_available_group.name,
|
||||
aws_config.ServiceAvailableGroup),
|
||||
(aws_config.aws_group.name,
|
||||
aws_config.AWSGroup)
|
||||
]
|
|
@ -1,135 +0,0 @@
|
|||
# Copyright 2015 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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 time
|
||||
|
||||
from oslo_log import log
|
||||
from tempest.lib.common.utils import data_utils
|
||||
|
||||
from ec2api_tempest_plugin import base
|
||||
from ec2api_tempest_plugin import config
|
||||
|
||||
CONF = config.CONF
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
|
||||
class BaseScenarioTest(base.EC2TestCase):
|
||||
|
||||
def get_instance_ip(self, instance_id):
|
||||
instance = self.get_instance(instance_id)
|
||||
public_ip = instance.get('PublicIpAddress')
|
||||
if public_ip:
|
||||
return public_ip
|
||||
|
||||
is_vpc = 'VpcId' in instance
|
||||
alloc_id, public_ip = self.allocate_address(is_vpc)
|
||||
|
||||
kwargs = {'InstanceId': instance_id}
|
||||
if is_vpc:
|
||||
kwargs['AllocationId'] = alloc_id
|
||||
else:
|
||||
kwargs['PublicIp'] = public_ip
|
||||
data = self.client.associate_address(*[], **kwargs)
|
||||
if is_vpc:
|
||||
self.addResourceCleanUp(self.client.disassociate_address,
|
||||
AssociationId=data['AssociationId'])
|
||||
self.get_address_assoc_waiter().wait_available(
|
||||
{'AllocationId': alloc_id})
|
||||
else:
|
||||
self.addResourceCleanUp(self.client.disassociate_address,
|
||||
PublicIp=public_ip)
|
||||
self.get_address_assoc_waiter().wait_available(
|
||||
{'PublicIp': public_ip})
|
||||
|
||||
return public_ip
|
||||
|
||||
def allocate_address(self, is_vpc):
|
||||
kwargs = dict()
|
||||
if is_vpc:
|
||||
kwargs['Domain'] = 'vpc'
|
||||
data = self.client.allocate_address(*[], **kwargs)
|
||||
alloc_id = data.get('AllocationId')
|
||||
public_ip = data['PublicIp']
|
||||
if is_vpc:
|
||||
self.addResourceCleanUp(self.client.release_address,
|
||||
AllocationId=alloc_id)
|
||||
else:
|
||||
self.addResourceCleanUp(self.client.release_address,
|
||||
PublicIp=public_ip)
|
||||
|
||||
return alloc_id, public_ip
|
||||
|
||||
def create_key_pair(self, key_name):
|
||||
data = self.client.create_key_pair(KeyName=key_name)
|
||||
self.addResourceCleanUp(self.client.delete_key_pair, KeyName=key_name)
|
||||
return data.get('KeyMaterial')
|
||||
|
||||
def create_standard_security_group(self):
|
||||
name = data_utils.rand_name('sgName')
|
||||
desc = data_utils.rand_name('sgDesc')
|
||||
kwargs = {'GroupName': name, 'Description': desc}
|
||||
self.client.create_security_group(*[], **kwargs)
|
||||
self.addResourceCleanUp(self.client.delete_security_group,
|
||||
GroupName=name)
|
||||
time.sleep(2)
|
||||
|
||||
kwargs = {
|
||||
'GroupName': name,
|
||||
'IpPermissions': [{
|
||||
'IpProtocol': 'icmp',
|
||||
'FromPort': -1,
|
||||
'ToPort': -1,
|
||||
'IpRanges': [{
|
||||
'CidrIp': '0.0.0.0/0'
|
||||
}],
|
||||
}, {
|
||||
'IpProtocol': 'tcp',
|
||||
'FromPort': 22,
|
||||
'ToPort': 22,
|
||||
'IpRanges': [{
|
||||
'CidrIp': '0.0.0.0/0'
|
||||
}],
|
||||
}]
|
||||
}
|
||||
self.client.authorize_security_group_ingress(*[], **kwargs)
|
||||
|
||||
return name
|
||||
|
||||
def prepare_vpc_default_security_group(self, vpc_id):
|
||||
data = self.client.describe_security_groups(
|
||||
Filters=[{'Name': 'vpc-id', 'Values': [vpc_id]}])
|
||||
self.assertEqual(1, len(data['SecurityGroups']))
|
||||
group_id = data['SecurityGroups'][0]['GroupId']
|
||||
kwargs = {
|
||||
'GroupId': group_id,
|
||||
'IpPermissions': [{
|
||||
'IpProtocol': '-1',
|
||||
'FromPort': -1,
|
||||
'ToPort': -1,
|
||||
'IpRanges': [{
|
||||
'CidrIp': '0.0.0.0/0'
|
||||
}],
|
||||
}]
|
||||
}
|
||||
self.client.authorize_security_group_ingress(*[], **kwargs)
|
||||
|
||||
def create_network_interface(self, subnet_id):
|
||||
data = self.client.create_network_interface(SubnetId=subnet_id)
|
||||
ni_id = data['NetworkInterface']['NetworkInterfaceId']
|
||||
self.addResourceCleanUp(self.client.delete_network_interface,
|
||||
NetworkInterfaceId=ni_id)
|
||||
self.get_network_interface_waiter().wait_available(ni_id)
|
||||
|
||||
return ni_id
|
|
@ -1,452 +0,0 @@
|
|||
# Copyright 2014
|
||||
# The Cloudscaling Group, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import math
|
||||
|
||||
from oslo_log import log
|
||||
from tempest.lib.common.utils import data_utils
|
||||
from tempest.lib import decorators
|
||||
import testtools
|
||||
|
||||
from ec2api_tempest_plugin import base
|
||||
from ec2api_tempest_plugin import config
|
||||
|
||||
CONF = config.CONF
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
|
||||
class EC2_EBSInstanceTuneBDM(base.EC2TestCase):
|
||||
"""Test change root device attributes at instance launch."""
|
||||
@classmethod
|
||||
@base.safe_setup
|
||||
def setUpClass(cls):
|
||||
super(EC2_EBSInstanceTuneBDM, cls).setUpClass()
|
||||
if not CONF.aws.ebs_image_id:
|
||||
raise cls.skipException('aws EBS image does not provided')
|
||||
cls.image_id = CONF.aws.ebs_image_id
|
||||
cls.zone = CONF.aws.aws_zone
|
||||
|
||||
data = cls.client.describe_images(ImageIds=[cls.image_id])
|
||||
assert 1 == len(data['Images'])
|
||||
image = data['Images'][0]
|
||||
cls.root_device_name = image['RootDeviceName']
|
||||
bdm = image['BlockDeviceMappings']
|
||||
bdm = [v for v in bdm if v['DeviceName'] == cls.root_device_name]
|
||||
assert 1 == len(bdm)
|
||||
ebs = bdm[0]['Ebs']
|
||||
cls.root_device_size = ebs.get('VolumeSize')
|
||||
if not cls.root_device_size:
|
||||
snapshotId = ebs.get('SnapshotId')
|
||||
data = cls.client.describe_snapshots(SnapshotIds=[snapshotId])
|
||||
assert 1 == len(data['Snapshots'])
|
||||
cls.root_device_size = data['Snapshots'][0]['VolumeSize']
|
||||
|
||||
@decorators.idempotent_id('2f51dd78-ff1e-494a-bcbc-f47580df17cb')
|
||||
def test_launch_ebs_instance_with_persistent_root_device(self):
|
||||
"""Launch EBS-backed instance with persistent root device"""
|
||||
instance_id = self.run_instance(ImageId=self.image_id,
|
||||
BlockDeviceMappings=[{'DeviceName': self.root_device_name,
|
||||
'Ebs': {'DeleteOnTermination': False}}])
|
||||
|
||||
bdt = self.get_instance_bdm(instance_id, self.root_device_name)
|
||||
self.assertIsNotNone(bdt)
|
||||
volume_id = bdt['Ebs'].get('VolumeId')
|
||||
res_clean_vol = self.addResourceCleanUp(self.client.delete_volume,
|
||||
VolumeId=volume_id)
|
||||
|
||||
self.assertIsNotNone(volume_id)
|
||||
self.assertFalse(bdt['Ebs']['DeleteOnTermination'])
|
||||
|
||||
data = self.client.describe_volumes(VolumeIds=[volume_id])
|
||||
self.assertEqual(1, len(data['Volumes']))
|
||||
|
||||
self.client.terminate_instances(InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_delete(instance_id)
|
||||
|
||||
self.get_volume_waiter().wait_available(volume_id)
|
||||
|
||||
self.client.delete_volume(VolumeId=volume_id)
|
||||
self.cancelResourceCleanUp(res_clean_vol)
|
||||
self.get_volume_waiter().wait_delete(volume_id)
|
||||
|
||||
@decorators.idempotent_id('0c820ed3-2e2f-4384-9649-cea907f00bf4')
|
||||
def test_launch_ebs_instance_with_resized_root_device(self):
|
||||
"""Launch EBS-backed instance with resizing root device."""
|
||||
new_size = int(math.ceil(self.root_device_size * 1.1))
|
||||
|
||||
instance_id = self.run_instance(ImageId=self.image_id,
|
||||
BlockDeviceMappings=[{'DeviceName': self.root_device_name,
|
||||
'Ebs': {'VolumeSize': new_size}}])
|
||||
|
||||
bdt = self.get_instance_bdm(instance_id, self.root_device_name)
|
||||
self.assertIsNotNone(bdt)
|
||||
volume_id = bdt['Ebs'].get('VolumeId')
|
||||
self.assertIsNotNone(volume_id)
|
||||
self.assertTrue(bdt['Ebs']['DeleteOnTermination'])
|
||||
|
||||
data = self.client.describe_volumes(VolumeIds=[volume_id])
|
||||
self.assertEqual(1, len(data['Volumes']))
|
||||
volume = data['Volumes'][0]
|
||||
self.assertEqual(new_size, volume['Size'])
|
||||
|
||||
self.client.terminate_instances(InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_delete(instance_id)
|
||||
|
||||
@decorators.idempotent_id('a0dbb3bd-167f-4f35-bb9d-aa53233e3123')
|
||||
def test_launch_ebs_instance_with_creating_blank_volume(self):
|
||||
"""Launch instance with creating blank volume."""
|
||||
device_name_prefix = base.get_device_name_prefix(self.root_device_name)
|
||||
device_name = device_name_prefix + 'b'
|
||||
|
||||
instance_id = self.run_instance(ImageId=self.image_id,
|
||||
BlockDeviceMappings=[{'DeviceName': device_name,
|
||||
'Ebs': {'VolumeSize': 1}}])
|
||||
|
||||
bdt = self.get_instance_bdm(instance_id, device_name)
|
||||
self.assertIsNotNone(bdt)
|
||||
volume_id = bdt['Ebs'].get('VolumeId')
|
||||
self.assertIsNotNone(volume_id)
|
||||
self.assertTrue(bdt['Ebs']['DeleteOnTermination'])
|
||||
|
||||
data = self.client.describe_volumes(VolumeIds=[volume_id])
|
||||
self.assertEqual(1, len(data['Volumes']))
|
||||
volume = data['Volumes'][0]
|
||||
self.assertEqual(1, volume['Size'])
|
||||
|
||||
self.client.terminate_instances(InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_delete(instance_id)
|
||||
|
||||
|
||||
class EC2_EBSInstanceAttaching(base.EC2TestCase):
|
||||
"""Test attaching cases
|
||||
|
||||
Launch instance with two attached volumes. One at first free slot (xxdb,
|
||||
other at some free slot (xxdh). Use full device name for the first and
|
||||
short device name for the second. Check used device names.
|
||||
Detach devices and reattach their back with same names. Check used device
|
||||
names again.
|
||||
Detach devices and attach their in next slots (xxdc and xxdi). First with
|
||||
full name, and second with short. Check useed device names.
|
||||
Sometimes this test case failed in AWS because volumes get attach state
|
||||
'busy'. Then it's need to give a pause and rerun test case.
|
||||
Some dublicate tests are hidden to less output information.
|
||||
"""
|
||||
@classmethod
|
||||
@base.safe_setup
|
||||
def setUpClass(cls):
|
||||
super(EC2_EBSInstanceAttaching, cls).setUpClass()
|
||||
|
||||
if not CONF.aws.run_incompatible_tests:
|
||||
raise cls.skipException('Decsribe returns full device name while '
|
||||
'we boot with short name.')
|
||||
|
||||
if not CONF.aws.ebs_image_id:
|
||||
raise cls.skipException('aws EBS image does not provided')
|
||||
cls.image_id = CONF.aws.ebs_image_id
|
||||
cls.zone = CONF.aws.aws_zone
|
||||
|
||||
data = cls.client.describe_images(ImageIds=[cls.image_id])
|
||||
assert 1 == len(data['Images'])
|
||||
image = data['Images'][0]
|
||||
root_device_name = image['RootDeviceName']
|
||||
|
||||
device_name_prefix = base.get_device_name_prefix(root_device_name)
|
||||
cls.full_device_name_prefix = device_name_prefix
|
||||
cls.short_device_name_prefix = device_name_prefix[len("/dev/"):]
|
||||
|
||||
data = cls.client.create_volume(AvailabilityZone=cls.zone,
|
||||
Size=1)
|
||||
cls.volume_id = data['VolumeId']
|
||||
cls.addResourceCleanUpStatic(cls.client.delete_volume,
|
||||
VolumeId=cls.volume_id)
|
||||
cls.get_volume_waiter().wait_available(cls.volume_id)
|
||||
|
||||
data = cls.client.create_snapshot(VolumeId=cls.volume_id)
|
||||
cls.snapshot_id = data['SnapshotId']
|
||||
cls.addResourceCleanUpStatic(cls.client.delete_snapshot,
|
||||
SnapshotId=cls.snapshot_id)
|
||||
cls.get_snapshot_waiter().wait_available(cls.snapshot_id,
|
||||
final_set=('completed'))
|
||||
|
||||
instance_type = CONF.aws.instance_type
|
||||
cls.device1_name = cls.full_device_name_prefix + "d"
|
||||
cls.device2_name = cls.short_device_name_prefix + "h"
|
||||
data = cls.client.run_instances(
|
||||
ImageId=cls.image_id, InstanceType=instance_type,
|
||||
Placement={'AvailabilityZone': cls.zone}, MinCount=1, MaxCount=1,
|
||||
BlockDeviceMappings=[{'DeviceName': cls.device1_name,
|
||||
'Ebs': {'SnapshotId': cls.snapshot_id,
|
||||
'DeleteOnTermination': True}},
|
||||
{'DeviceName': cls.device2_name,
|
||||
'Ebs': {'SnapshotId': cls.snapshot_id,
|
||||
'DeleteOnTermination': True}}])
|
||||
instance_id = data['Instances'][0]['InstanceId']
|
||||
cls.instance_id = instance_id
|
||||
cls.addResourceCleanUpStatic(cls.client.terminate_instances,
|
||||
InstanceIds=[instance_id])
|
||||
cls.get_instance_waiter().wait_available(instance_id,
|
||||
final_set=('running'))
|
||||
|
||||
data = cls.client.describe_instances(InstanceIds=[instance_id])
|
||||
assert 1 == len(data.get('Reservations', []))
|
||||
instances = data['Reservations'][0].get('Instances', [])
|
||||
assert 1 == len(instances)
|
||||
instance = instances[0]
|
||||
bdms = instance['BlockDeviceMappings']
|
||||
for bdt in bdms:
|
||||
if bdt['DeviceName'] == cls.device1_name:
|
||||
cls.volume_id1 = bdt['Ebs']['VolumeId']
|
||||
if bdt['DeviceName'] == cls.device2_name:
|
||||
cls.volume_id2 = bdt['Ebs']['VolumeId']
|
||||
assert cls.volume_id1
|
||||
assert cls.volume_id2
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
super(EC2_EBSInstanceAttaching, cls).tearDownClass()
|
||||
# NOTE(andrey-mp): Amazon resets flag DeleteOnTermination after
|
||||
# reattaching volume, so we need delete them manually
|
||||
for volume_id in [cls.volume_id1, cls.volume_id2]:
|
||||
try:
|
||||
cls.cleanUpItem(cls.client.delete_volume, [],
|
||||
{'VolumeId': volume_id})
|
||||
except BaseException:
|
||||
LOG.exception('EBSInstanceAttaching.tearDownClass failure')
|
||||
|
||||
def _test_attaching(self, volume_id, device_name, device_prefix,
|
||||
new_device_name_letter):
|
||||
self.client.detach_volume(VolumeId=volume_id)
|
||||
clean_v = self.addResourceCleanUp(self.client.delete_volume,
|
||||
VolumeId=volume_id)
|
||||
self.get_volume_attachment_waiter().wait_delete(volume_id)
|
||||
|
||||
bdt = self.get_instance_bdm(self.instance_id, device_name)
|
||||
self.assertIsNone(bdt)
|
||||
|
||||
self.client.attach_volume(InstanceId=self.instance_id,
|
||||
VolumeId=volume_id,
|
||||
Device=device_name)
|
||||
self.cancelResourceCleanUp(clean_v)
|
||||
self.get_volume_attachment_waiter().wait_available(
|
||||
volume_id, final_set=('attached'))
|
||||
|
||||
data = self.client.describe_volumes(VolumeIds=[volume_id])
|
||||
self.assertEqual(1, len(data['Volumes']))
|
||||
self.assertEqual('in-use', data['Volumes'][0]['State'])
|
||||
|
||||
bdt = self.get_instance_bdm(self.instance_id, device_name)
|
||||
self.assertIsNotNone(bdt)
|
||||
|
||||
self.client.detach_volume(VolumeId=volume_id)
|
||||
clean_v = self.addResourceCleanUp(self.client.delete_volume,
|
||||
VolumeId=volume_id)
|
||||
self.get_volume_attachment_waiter().wait_delete(volume_id)
|
||||
|
||||
bdt = self.get_instance_bdm(self.instance_id, device_name)
|
||||
self.assertIsNone(bdt)
|
||||
|
||||
new_device_name = device_prefix + new_device_name_letter
|
||||
self.client.attach_volume(InstanceId=self.instance_id,
|
||||
VolumeId=volume_id,
|
||||
Device=new_device_name)
|
||||
self.cancelResourceCleanUp(clean_v)
|
||||
self.get_volume_attachment_waiter().wait_available(
|
||||
volume_id, final_set=('attached'))
|
||||
|
||||
data = self.client.describe_volumes(VolumeIds=[volume_id])
|
||||
self.assertEqual(1, len(data['Volumes']))
|
||||
self.assertEqual('in-use', data['Volumes'][0]['State'])
|
||||
|
||||
bdt = self.get_instance_bdm(self.instance_id, new_device_name)
|
||||
self.assertIsNotNone(bdt)
|
||||
|
||||
@decorators.idempotent_id('2176d935-5254-4e2a-9eb4-fc899f63c530')
|
||||
def test_attaching_by_full_name(self):
|
||||
"""Attach and reattach device by full name."""
|
||||
self._test_attaching(self.volume_id1, self.device1_name,
|
||||
self.full_device_name_prefix, "e")
|
||||
|
||||
@decorators.idempotent_id('43af092e-3f04-45a7-bec7-8da39cde1f4c')
|
||||
def test_attaching_by_short_name(self):
|
||||
"""Attach and reattach device by short name."""
|
||||
self._test_attaching(self.volume_id2, self.device2_name,
|
||||
self.short_device_name_prefix, "i")
|
||||
|
||||
|
||||
class EC2_EBSInstanceSnapshot(base.EC2TestCase):
|
||||
"""Test instance's snapshotting
|
||||
|
||||
Launch EBS-backed image, snapshot root device, register image,
|
||||
and launch another instance from the image
|
||||
(http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/
|
||||
instance-launch-snapshot.html)
|
||||
"""
|
||||
@classmethod
|
||||
@base.safe_setup
|
||||
def setUpClass(cls):
|
||||
super(EC2_EBSInstanceSnapshot, cls).setUpClass()
|
||||
if not CONF.aws.ebs_image_id:
|
||||
raise cls.skipException('aws EBS image does not provided')
|
||||
cls.image_id = CONF.aws.ebs_image_id
|
||||
cls.zone = CONF.aws.aws_zone
|
||||
|
||||
@decorators.idempotent_id('07caac78-750c-48a1-975d-d3a6bd988108')
|
||||
def test_create_ebs_instance_snapshot(self):
|
||||
"""Create snapshot of EBS-backed instance and check it."""
|
||||
|
||||
instance_id = self.run_instance(ImageId=self.image_id)
|
||||
|
||||
instance = self.get_instance(instance_id)
|
||||
bdt = self.get_instance_bdm(instance_id, None)
|
||||
self.assertIsNotNone(bdt)
|
||||
volume_id = bdt['Ebs'].get('VolumeId')
|
||||
self.assertIsNotNone(volume_id)
|
||||
|
||||
self.client.stop_instances(InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_available(instance_id,
|
||||
final_set=('stopped'))
|
||||
|
||||
self.addResourceCleanUp(self.client.delete_volume,
|
||||
VolumeId=volume_id)
|
||||
data = self.client.create_snapshot(VolumeId=volume_id)
|
||||
snapshot_id = data['SnapshotId']
|
||||
self.addResourceCleanUp(self.client.delete_snapshot,
|
||||
SnapshotId=snapshot_id)
|
||||
self.get_snapshot_waiter().wait_available(snapshot_id,
|
||||
final_set=('completed'))
|
||||
|
||||
self.client.terminate_instances(InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_delete(instance_id)
|
||||
|
||||
kwargs = {
|
||||
'Name': data_utils.rand_name('ebs-ami'),
|
||||
'RootDeviceName': instance['RootDeviceName'],
|
||||
'BlockDeviceMappings': [{'DeviceName': instance['RootDeviceName'],
|
||||
'Ebs': {'SnapshotId': snapshot_id,
|
||||
'DeleteOnTermination': True}}]
|
||||
}
|
||||
if 'Architecture' in instance:
|
||||
kwargs['Architecture'] = instance['Architecture']
|
||||
if 'KernelId' in instance:
|
||||
kwargs['KernelId'] = instance['KernelId']
|
||||
if 'RamdiskId' in instance:
|
||||
kwargs['RamdiskId'] = instance['RamdiskId']
|
||||
data = self.client.register_image(*[], **kwargs)
|
||||
image_id = data['ImageId']
|
||||
clean_i = self.addResourceCleanUp(self.client.deregister_image,
|
||||
ImageId=image_id)
|
||||
self.get_image_waiter().wait_available(image_id)
|
||||
|
||||
instance_id = self.run_instance(ImageId=image_id)
|
||||
|
||||
# NOTE(andrey-mp): if instance will run then test will pass
|
||||
|
||||
self.client.terminate_instances(InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_delete(instance_id)
|
||||
|
||||
self.client.deregister_image(ImageId=image_id)
|
||||
self.cancelResourceCleanUp(clean_i)
|
||||
|
||||
|
||||
class EC2_EBSInstanceResizeRootDevice(base.EC2TestCase):
|
||||
"""Test resizing root device on instance
|
||||
|
||||
Launch EBS-backed instance, stop instance, detach root volume, snapshot it,
|
||||
create volume from snapshot with increased size, attach new root volume,
|
||||
start instance
|
||||
(http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ebs-expand-volume.html)
|
||||
"""
|
||||
@classmethod
|
||||
@base.safe_setup
|
||||
def setUpClass(cls):
|
||||
super(EC2_EBSInstanceResizeRootDevice, cls).setUpClass()
|
||||
if not CONF.aws.ebs_image_id:
|
||||
raise cls.skipException('aws EBS image does not provided')
|
||||
cls.image_id = CONF.aws.ebs_image_id
|
||||
cls.zone = CONF.aws.aws_zone
|
||||
|
||||
@decorators.idempotent_id('0ea1dee6-c2c3-4cad-9676-5bf6e7ae54a8')
|
||||
@testtools.skipUnless(
|
||||
CONF.aws.run_incompatible_tests,
|
||||
"Error from nova: "
|
||||
"Unexpected Forbidden raised: Can't detach root device volume")
|
||||
def test_resize_root_ebs_device(self):
|
||||
"""Resize root device of launched instance."""
|
||||
clean_dict = dict()
|
||||
instance_id = self.run_instance(clean_dict=clean_dict,
|
||||
ImageId=self.image_id)
|
||||
res_clean = clean_dict['instance']
|
||||
instance = self.get_instance(instance_id)
|
||||
|
||||
bdt = self.get_instance_bdm(instance_id, None)
|
||||
self.assertIsNotNone(bdt)
|
||||
volume_id = bdt['Ebs'].get('VolumeId')
|
||||
self.assertIsNotNone(volume_id)
|
||||
|
||||
self.client.stop_instances(InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_available(instance_id,
|
||||
final_set=('stopped'))
|
||||
|
||||
self.client.detach_volume(VolumeId=volume_id)
|
||||
clean_v = self.addResourceCleanUp(self.client.delete_volume,
|
||||
VolumeId=volume_id)
|
||||
self.get_volume_attachment_waiter().wait_delete(volume_id)
|
||||
|
||||
data = self.client.create_snapshot(VolumeId=volume_id)
|
||||
snapshot_id = data['SnapshotId']
|
||||
clean_s = self.addResourceCleanUp(self.client.delete_snapshot,
|
||||
SnapshotId=snapshot_id)
|
||||
self.get_snapshot_waiter().wait_available(snapshot_id,
|
||||
final_set=('completed'))
|
||||
|
||||
new_size = int(math.ceil(data['VolumeSize'] * 1.1))
|
||||
data = self.client.create_volume(AvailabilityZone=self.zone,
|
||||
Size=new_size,
|
||||
SnapshotId=snapshot_id)
|
||||
volume_id2 = data['VolumeId']
|
||||
clean_v2 = self.addResourceCleanUp(self.client.delete_volume,
|
||||
VolumeId=volume_id2)
|
||||
self.get_volume_waiter().wait_available(volume_id2)
|
||||
|
||||
self.client.delete_snapshot(SnapshotId=snapshot_id)
|
||||
self.cancelResourceCleanUp(clean_s)
|
||||
|
||||
self.client.delete_volume(VolumeId=volume_id)
|
||||
self.cancelResourceCleanUp(clean_v)
|
||||
self.get_volume_waiter().wait_delete(volume_id)
|
||||
|
||||
self.client.attach_volume(
|
||||
InstanceId=instance_id, VolumeId=volume_id2,
|
||||
Device=instance['RootDeviceName'])
|
||||
self.get_volume_attachment_waiter().wait_available(
|
||||
volume_id2, final_set=('attached'))
|
||||
|
||||
# NOTE(andrey-mp): move this cleanup operation to the end of trash
|
||||
# (it will remove first)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
res_clean = self.addResourceCleanUp(self.client.terminate_instances,
|
||||
InstanceIds=[instance_id])
|
||||
|
||||
self.client.start_instances(InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_available(instance_id,
|
||||
final_set=('running'))
|
||||
|
||||
# NOTE(andrey-mp): if instance will run then test will pass
|
||||
|
||||
self.client.terminate_instances(InstanceIds=[instance_id])
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
self.get_instance_waiter().wait_delete(instance_id)
|
||||
|
||||
self.client.delete_volume(VolumeId=volume_id2)
|
||||
self.cancelResourceCleanUp(clean_v2)
|
|
@ -1,95 +0,0 @@
|
|||
# Copyright 2015 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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.
|
||||
|
||||
from oslo_log import log
|
||||
from tempest.lib.common.utils import data_utils
|
||||
from tempest.lib import decorators
|
||||
import testtools
|
||||
|
||||
from ec2api_tempest_plugin import base
|
||||
from ec2api_tempest_plugin import config
|
||||
from ec2api_tempest_plugin.scenario import base as scenario_base
|
||||
from ec2api_tempest_plugin import ssh
|
||||
|
||||
CONF = config.CONF
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
|
||||
class InstanceRestartTest(scenario_base.BaseScenarioTest):
|
||||
|
||||
@decorators.idempotent_id('8ae801a5-3e4a-4a34-903a-45e34ff9eccd')
|
||||
@testtools.skipUnless(CONF.aws.run_ssh, 'SSH tests are disabled.')
|
||||
@testtools.skipUnless(CONF.aws.run_long_tests, 'Slow test has skipped.')
|
||||
@testtools.skipUnless(CONF.aws.image_id_ubuntu,
|
||||
"ubuntu image id is not defined")
|
||||
def test_stop_start_instance(self):
|
||||
key_name = data_utils.rand_name('testkey')
|
||||
pkey = self.create_key_pair(key_name)
|
||||
sec_group_name = self.create_standard_security_group()
|
||||
instance_id = self.run_instance(KeyName=key_name,
|
||||
ImageId=CONF.aws.image_id_ubuntu,
|
||||
SecurityGroups=[sec_group_name])
|
||||
|
||||
ip_address = self.get_instance_ip(instance_id)
|
||||
ssh_client = ssh.Client(ip_address, CONF.aws.image_user_ubuntu,
|
||||
pkey=pkey)
|
||||
ssh_client.exec_command('last -x')
|
||||
|
||||
self.client.stop_instances(InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_available(instance_id,
|
||||
final_set=('stopped'))
|
||||
|
||||
self.client.start_instances(InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_available(instance_id,
|
||||
final_set=('running'))
|
||||
|
||||
# Amazon can change auto-assigned public ip
|
||||
ip_address = self.get_instance_ip(instance_id)
|
||||
ssh_client = ssh.Client(ip_address, CONF.aws.image_user_ubuntu,
|
||||
pkey=pkey)
|
||||
data = ssh_client.exec_command('last -x')
|
||||
self.assertIn("shutdown", data)
|
||||
|
||||
@decorators.idempotent_id('ae1cce79-882c-4f37-b9e9-2f7156712721')
|
||||
@testtools.skipUnless(CONF.aws.run_ssh, 'SSH tests are disabled.')
|
||||
@testtools.skipUnless(CONF.aws.run_long_tests, 'Slow test has skipped.')
|
||||
@testtools.skipUnless(CONF.aws.image_id_ubuntu,
|
||||
"ubuntu image id is not defined")
|
||||
def test_reboot_instance(self):
|
||||
key_name = data_utils.rand_name('testkey')
|
||||
pkey = self.create_key_pair(key_name)
|
||||
sec_group_name = self.create_standard_security_group()
|
||||
instance_id = self.run_instance(KeyName=key_name,
|
||||
ImageId=CONF.aws.image_id_ubuntu,
|
||||
SecurityGroups=[sec_group_name])
|
||||
ip_address = self.get_instance_ip(instance_id)
|
||||
|
||||
ssh_client = ssh.Client(ip_address, CONF.aws.image_user_ubuntu,
|
||||
pkey=pkey)
|
||||
last_lines = ssh_client.exec_command('last -x').split('\n')
|
||||
|
||||
self.client.reboot_instances(InstanceIds=[instance_id])
|
||||
|
||||
def _last_state():
|
||||
current = ssh_client.exec_command('last -x').split('\n')
|
||||
if len(current) > len(last_lines):
|
||||
return
|
||||
raise Exception()
|
||||
|
||||
waiter = base.EC2Waiter(_last_state)
|
||||
waiter.wait_no_exception()
|
||||
|
||||
data = ssh_client.exec_command('last -x')
|
||||
self.assertIn("shutdown", data)
|
|
@ -1,182 +0,0 @@
|
|||
# Copyright 2015 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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 base64
|
||||
import os
|
||||
|
||||
from oslo_log import log
|
||||
import six
|
||||
|
||||
from tempest.lib.common.utils import data_utils
|
||||
from tempest.lib import decorators
|
||||
|
||||
from ec2api_tempest_plugin import base
|
||||
from ec2api_tempest_plugin import config
|
||||
from ec2api_tempest_plugin.scenario import base as scenario_base
|
||||
from ec2api_tempest_plugin import ssh
|
||||
|
||||
import testtools
|
||||
|
||||
CONF = config.CONF
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
PRIVATE_KEY_MATERIAL = (
|
||||
'-----BEGIN RSA PRIVATE KEY-----\n'
|
||||
'MIIEpAIBAAKCAQEAxkaf7L0BoNmyzlWPh29WPsaUP2+kV2vuoCQrO2FWliV8OOUP\n'
|
||||
'+OIPvqRF+XtcCWc5LIQrSzKnitazJmoUO1m/J7fwxv2Qf2kbKVLrLqP7AUh1pAgG\n'
|
||||
'DUqnBS8F5+2kPsMRKAE+xz1uJDpnP5ktIzpn1hWDVCoG80/jP7d7YSi0KlIYMHVx\n'
|
||||
'E3WegrQ5IWw/BI62LR1KOe2YBSrv1n9SDc2w69QbfrnsZOpNKAnv/+G7LIqeHKP1\n'
|
||||
'G5YMh2iWtEzdDgHqWa+HvtifhS3AzdtG7zgpmpwq8JYheYXLC+S/qxdZSGFx3p5s\n'
|
||||
'JKr7kiAcxWqTsYEEtJdbYKDYfmu1e+k5hP901wIDAQABAoIBAFJkDJaSX7fYXq3Q\n'
|
||||
'7giIYl1JpVbK7I6LQih3fyN4qkNQJlN6E+4G+iXtG0q1USRzKVXvQhJIZUiTOPSQ\n'
|
||||
'hgG3pHA7xijaOw5GvcupMiM6btY0pvXXg7RIPikwRhL/NA4Efv+RrOWcCEWzoy3R\n'
|
||||
'V+lYnsdePyldIXA/1R2n//P6twsSP+055XCabN/HVEJMtYmeVnZsoffRgos5cDlT\n'
|
||||
'afpq29W93kI7kXTDIlNxdQXzOa1rKqmUK/nBf0caMwaGy9Di9s3OP8M+Xs4Y/L0b\n'
|
||||
'+QOuILwBNjMMj3yqdDyDT698kQoO0oX458L70MUk660PItdaqyPT1KAaCIz7xTFJ\n'
|
||||
'7OQM10kCgYEA+ES8irwqkkSocZ0QQzCR5qxIp3cVrnw1kaaqWuZOgojMPvRpzFJO\n'
|
||||
'x4IB6VbvcpPPqHBhCGuJYIDYXuM1Ke0YR4TllNec9ZvSPvUYFNNQLeXmAyaWKtIE\n'
|
||||
'91BoONyEMsbpWr/hsG60y4cFoqNZVqILHTNS48TMVtB4Lv8IgOv3OVsCgYEAzHNV\n'
|
||||
'YZzUMdBN5rEuNwJ5NtModung7H08g9jOiGHMo0ZQvhKhFYgieQmJRGXOhMpbNPL4\n'
|
||||
'9RLQjAVr4mrFdk+sDqVmscqu07q2/jjT1U1x2rprBpzckOvmmw7TKveiGfgcwqZ+\n'
|
||||
'Qs3tWoiLc8m74loJyT/7c0tpyZxjbPJL7jVQzzUCgYEAqnNuywWDaObwiwhduPOo\n'
|
||||
'yCmyvB87aI9oq/Y0cbI7Zs2LBRIDbT95TOqKa2y/evfWk3uMcx55tCLh6sutnXpl\n'
|
||||
't/ybLwSVg98Wixj1Dp9CJjD4KWOdqAqHVFEFLTzhGoeMgTzKM7reL/okuVPTK3KX\n'
|
||||
'lNW+7BgafuQkD4gTi4f2NY8CgYEAiUNlr4N7c3ZG1vtd69DdUNGz+SJMwHnUhzCo\n'
|
||||
'eSgwG+65huM7AxnDC0A7yJARd1Xkpkf6nY9kNJ3vMLQ+npAfFDY4HGXXuo9BDK1a\n'
|
||||
'i3rTVeaStH3cF/BJgxEQ9WgMjSLnLEhbvL5E/ONvvO1UF0QcDeHHEEExZQp6Nkr2\n'
|
||||
'b5ecCYECgYBtL4kr0qttoowbfj+pXjwiJjbwb6GBaMBVNQTtJBKdl5AeyDm9qh2o\n'
|
||||
'vF60vnm+wWFfUs8nlvPMT/FNHwjHtFOBLPhw6tUcyrzh1ba4v/FE40FW4NxgqSK/\n'
|
||||
'VS0+XhPxet+E9kXjMMrVUaDrHHR2+zM5OyOLG0a/JIcsFuf7qZgAMQ==\n'
|
||||
'-----END RSA PRIVATE KEY-----'
|
||||
)
|
||||
PUBLIC_KEY_MATERIAL = (
|
||||
'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDGRp/svQGg2bLOVY+Hb1Y+xpQ/'
|
||||
'b6RXa+6gJCs7YVaWJXw45Q/44g++pEX5e1wJZzkshCtLMqeK1rMmahQ7Wb8nt/DG'
|
||||
'/ZB/aRspUusuo/sBSHWkCAYNSqcFLwXn7aQ+wxEoAT7HPW4kOmc/mS0jOmfWFYNU'
|
||||
'KgbzT+M/t3thKLQqUhgwdXETdZ6CtDkhbD8EjrYtHUo57ZgFKu/Wf1INzbDr1Bt+'
|
||||
'uexk6k0oCe//4bssip4co/UblgyHaJa0TN0OAepZr4e+2J+FLcDN20bvOCmanCrw'
|
||||
'liF5hcsL5L+rF1lIYXHenmwkqvuSIBzFapOxgQS0l1tgoNh+a7V76TmE/3TX '
|
||||
'ubuntu@test.com'
|
||||
)
|
||||
|
||||
|
||||
class InstancesTest(scenario_base.BaseScenarioTest):
|
||||
|
||||
@decorators.idempotent_id('c25defc4-b075-4794-9fa6-3b67353c4079')
|
||||
@testtools.skipUnless(CONF.aws.run_ssh, 'SSH tests are disabled.')
|
||||
@testtools.skipUnless(CONF.aws.image_id, "image id is not defined")
|
||||
def test_metadata(self):
|
||||
key_name = data_utils.rand_name('testkey')
|
||||
self.client.import_key_pair(KeyName=key_name,
|
||||
PublicKeyMaterial=PUBLIC_KEY_MATERIAL)
|
||||
self.addResourceCleanUp(self.client.delete_key_pair, KeyName=key_name)
|
||||
|
||||
sec_group_name = self.create_standard_security_group()
|
||||
user_data = six.text_type(data_utils.rand_uuid()) + six.unichr(1071)
|
||||
instance_id = self.run_instance(KeyName=key_name, UserData=user_data,
|
||||
SecurityGroups=[sec_group_name])
|
||||
|
||||
data = self.client.describe_instance_attribute(
|
||||
InstanceId=instance_id, Attribute='userData')
|
||||
self.assertEqual(
|
||||
data['UserData']['Value'],
|
||||
base64.b64encode(user_data.encode("utf-8")).decode("utf-8"))
|
||||
|
||||
ip_address = self.get_instance_ip(instance_id)
|
||||
|
||||
ssh_client = ssh.Client(ip_address, CONF.aws.image_user,
|
||||
pkey=PRIVATE_KEY_MATERIAL)
|
||||
|
||||
url = 'http://169.254.169.254'
|
||||
data = ssh_client.exec_command('curl %s/latest/user-data' % url)
|
||||
if isinstance(data, six.binary_type):
|
||||
data = data.decode("utf-8")
|
||||
self.assertEqual(user_data, data)
|
||||
|
||||
data = ssh_client.exec_command('curl %s/latest/meta-data/ami-id' % url)
|
||||
self.assertEqual(CONF.aws.image_id, data)
|
||||
|
||||
data = ssh_client.exec_command(
|
||||
'curl %s/latest/meta-data/public-keys/0/openssh-key' % url)
|
||||
# compare only keys. without 'sha-rsa' and owner
|
||||
self.assertEqual(PUBLIC_KEY_MATERIAL.split()[1], data.split()[1])
|
||||
|
||||
@decorators.idempotent_id('9fd254b1-dad1-4bb6-959f-f2cf937873c7')
|
||||
@testtools.skipUnless(CONF.aws.run_ssh, 'SSH tests are disabled.')
|
||||
@testtools.skipUnless(CONF.aws.image_id, "image id is not defined")
|
||||
def test_compare_console_output(self):
|
||||
key_name = data_utils.rand_name('testkey')
|
||||
pkey = self.create_key_pair(key_name)
|
||||
sec_group_name = self.create_standard_security_group()
|
||||
instance_id = self.run_instance(KeyName=key_name,
|
||||
SecurityGroups=[sec_group_name])
|
||||
|
||||
data_to_check = data_utils.rand_uuid()
|
||||
ip_address = self.get_instance_ip(instance_id)
|
||||
ssh_client = ssh.Client(ip_address, CONF.aws.image_user, pkey=pkey)
|
||||
cmd = 'sudo sh -c "echo \\"%s\\" >/dev/console"' % data_to_check
|
||||
ssh_client.exec_command(cmd)
|
||||
|
||||
waiter = base.EC2Waiter(self.client.get_console_output)
|
||||
waiter.wait_no_exception(InstanceId=instance_id)
|
||||
|
||||
def _compare_console_output():
|
||||
data = self.client.get_console_output(InstanceId=instance_id)
|
||||
self.assertEqual(instance_id, data['InstanceId'])
|
||||
self.assertIsNotNone(data['Timestamp'])
|
||||
self.assertIn('Output', data)
|
||||
self.assertIn(data_to_check, data['Output'])
|
||||
|
||||
waiter = base.EC2Waiter(_compare_console_output)
|
||||
waiter.wait_no_exception()
|
||||
|
||||
@decorators.idempotent_id('df1bb8f2-193c-46ba-aa99-3981bbc367db')
|
||||
@testtools.skipUnless(CONF.aws.run_ssh, 'SSH tests are disabled.')
|
||||
@testtools.skipUnless(CONF.aws.ami_image_location, "Image is absent in S3")
|
||||
def test_run_and_ping_registered_image(self):
|
||||
image_name = data_utils.rand_name("ami-name")
|
||||
data = self.client.register_image(
|
||||
Name=image_name, ImageLocation=CONF.aws.ami_image_location)
|
||||
image_id = data['ImageId']
|
||||
self.addResourceCleanUp(self.client.deregister_image, ImageId=image_id)
|
||||
self.get_image_waiter().wait_available(image_id)
|
||||
|
||||
# launch this image
|
||||
sec_group_name = self.create_standard_security_group()
|
||||
instance_id = self.run_instance(ImageId=image_id,
|
||||
SecurityGroups=[sec_group_name])
|
||||
|
||||
waiter = base.EC2Waiter(self.client.get_console_output)
|
||||
waiter.wait_no_exception(InstanceId=instance_id)
|
||||
|
||||
def _compare_console_output():
|
||||
data = self.client.get_console_output(InstanceId=instance_id)
|
||||
self.assertEqual(instance_id, data['InstanceId'])
|
||||
self.assertIsNotNone(data['Timestamp'])
|
||||
self.assertIn('Output', data)
|
||||
self.assertNotEqual('', data['Output'])
|
||||
|
||||
waiter = base.EC2Waiter(_compare_console_output)
|
||||
waiter.wait_no_exception()
|
||||
|
||||
# check ping
|
||||
ip_address = self.get_instance_ip(instance_id)
|
||||
|
||||
def _ping():
|
||||
response = os.system("ping -c 1 " + ip_address + " > /dev/null")
|
||||
self.assertEqual(0, response)
|
||||
|
||||
waiter = base.EC2Waiter(_ping)
|
||||
waiter.wait_no_exception()
|
|
@ -1,173 +0,0 @@
|
|||
# Copyright 2015 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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 netaddr
|
||||
from oslo_log import log
|
||||
|
||||
from tempest.lib.common.utils import data_utils
|
||||
from tempest.lib import decorators
|
||||
from tempest.lib import exceptions
|
||||
import testtools
|
||||
|
||||
from ec2api_tempest_plugin import base
|
||||
from ec2api_tempest_plugin import config
|
||||
from ec2api_tempest_plugin.scenario import base as scenario_base
|
||||
from ec2api_tempest_plugin import ssh
|
||||
|
||||
CONF = config.CONF
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
|
||||
class InstancesInVPCTest(scenario_base.BaseScenarioTest):
|
||||
|
||||
def _test_instances(self, subnet_size):
|
||||
cidr = netaddr.IPNetwork('10.20.0.0/8')
|
||||
cidr.prefixlen = subnet_size
|
||||
vpc_id, subnet_id = self.create_vpc_and_subnet(str(cidr))
|
||||
gw_id = self.create_and_attach_internet_gateway(vpc_id)
|
||||
self.prepare_vpc_default_security_group(vpc_id)
|
||||
self.prepare_route(vpc_id, gw_id)
|
||||
|
||||
key_name = data_utils.rand_name('testkey')
|
||||
pkey = self.create_key_pair(key_name)
|
||||
|
||||
first_ip = str(netaddr.IPAddress(cidr.first + 4))
|
||||
last_ip = str(netaddr.IPAddress(cidr.last - 1))
|
||||
instance_id1 = self.run_instance(KeyName=key_name, SubnetId=subnet_id,
|
||||
PrivateIpAddress=first_ip)
|
||||
instance_id2 = self.run_instance(KeyName=key_name, SubnetId=subnet_id,
|
||||
PrivateIpAddress=last_ip)
|
||||
instance = self.get_instance(instance_id1)
|
||||
self.assertEqual(first_ip, instance['PrivateIpAddress'])
|
||||
instance = self.get_instance(instance_id2)
|
||||
self.assertEqual(last_ip, instance['PrivateIpAddress'])
|
||||
|
||||
ip_address = self.get_instance_ip(instance_id1)
|
||||
ssh_client = ssh.Client(ip_address, CONF.aws.image_user, pkey=pkey)
|
||||
|
||||
waiter = base.EC2Waiter(ssh_client.exec_command)
|
||||
waiter.wait_no_exception('ping %s -c 1' % last_ip)
|
||||
|
||||
@base.skip_without_vpc()
|
||||
@decorators.idempotent_id('b986708e-9559-493d-aeb3-97fc992a65cf')
|
||||
@testtools.skipUnless(CONF.aws.run_ssh, 'SSH tests are disabled.')
|
||||
@testtools.skipUnless(CONF.aws.image_id, "image id is not defined")
|
||||
def test_instances_in_min_subnet(self):
|
||||
self._test_instances(28)
|
||||
|
||||
@base.skip_without_vpc()
|
||||
@decorators.idempotent_id('7bf8e80c-cd05-4ccb-944a-e4b09825d151')
|
||||
@testtools.skipUnless(CONF.aws.run_ssh, 'SSH tests are disabled.')
|
||||
@testtools.skipUnless(CONF.aws.image_id, "image id is not defined")
|
||||
def test_instances_in_max_subnet(self):
|
||||
self._test_instances(16)
|
||||
|
||||
@base.skip_without_vpc()
|
||||
@decorators.idempotent_id('9c3a8066-68b2-4bd0-85e0-6d4a0d7cb053')
|
||||
@testtools.skipUnless(CONF.aws.run_ssh, 'SSH tests are disabled.')
|
||||
@testtools.skipUnless(CONF.aws.image_id, "image id is not defined")
|
||||
@testtools.skipUnless(CONF.aws.run_incompatible_tests,
|
||||
'skip due to bug #1818499')
|
||||
def test_default_gateway(self):
|
||||
novpc_group = self.create_standard_security_group()
|
||||
novpc_instance_id = self.run_instance(SecurityGroups=[novpc_group])
|
||||
ping_destination = self.get_instance_ip(novpc_instance_id)
|
||||
|
||||
data = self.client.create_vpc(CidrBlock='10.10.0.0/16')
|
||||
vpc_id = data['Vpc']['VpcId']
|
||||
self.addResourceCleanUp(self.client.delete_vpc, VpcId=vpc_id)
|
||||
self.get_vpc_waiter().wait_available(vpc_id)
|
||||
|
||||
data = self.client.create_subnet(
|
||||
VpcId=vpc_id, CidrBlock='10.10.1.0/24',
|
||||
AvailabilityZone=CONF.aws.aws_zone)
|
||||
subnet_1_id = data['Subnet']['SubnetId']
|
||||
self.addResourceCleanUp(self.client.delete_subnet,
|
||||
SubnetId=subnet_1_id)
|
||||
|
||||
data = self.client.create_subnet(
|
||||
VpcId=vpc_id, CidrBlock='10.10.2.0/24',
|
||||
AvailabilityZone=CONF.aws.aws_zone)
|
||||
subnet_2_id = data['Subnet']['SubnetId']
|
||||
self.addResourceCleanUp(self.client.delete_subnet,
|
||||
SubnetId=subnet_2_id)
|
||||
|
||||
data = self.client.create_internet_gateway()
|
||||
gw_id = data['InternetGateway']['InternetGatewayId']
|
||||
self.addResourceCleanUp(self.client.delete_internet_gateway,
|
||||
InternetGatewayId=gw_id)
|
||||
data = self.client.attach_internet_gateway(VpcId=vpc_id,
|
||||
InternetGatewayId=gw_id)
|
||||
self.addResourceCleanUp(self.client.detach_internet_gateway,
|
||||
VpcId=vpc_id, InternetGatewayId=gw_id)
|
||||
|
||||
self.prepare_route(vpc_id, gw_id)
|
||||
|
||||
data = self.client.create_route_table(VpcId=vpc_id)
|
||||
rt_id = data['RouteTable']['RouteTableId']
|
||||
self.addResourceCleanUp(self.client.delete_route_table,
|
||||
RouteTableId=rt_id)
|
||||
data = self.client.associate_route_table(RouteTableId=rt_id,
|
||||
SubnetId=subnet_2_id)
|
||||
assoc_id = data['AssociationId']
|
||||
self.addResourceCleanUp(self.client.disassociate_route_table,
|
||||
AssociationId=assoc_id)
|
||||
|
||||
self.prepare_vpc_default_security_group(vpc_id)
|
||||
key_name = data_utils.rand_name('testkey')
|
||||
pkey = self.create_key_pair(key_name)
|
||||
|
||||
instance_2_id = self.run_instance(KeyName=key_name,
|
||||
SubnetId=subnet_2_id)
|
||||
instance_1_id = self.run_instance(KeyName=key_name,
|
||||
SubnetId=subnet_1_id,
|
||||
UserData=pkey)
|
||||
ip_address = self.get_instance_ip(instance_1_id)
|
||||
ip_private_address_1 = self.get_instance(
|
||||
instance_1_id)['PrivateIpAddress']
|
||||
ip_private_address_2 = self.get_instance(
|
||||
instance_2_id)['PrivateIpAddress']
|
||||
|
||||
ssh_client = ssh.Client(ip_address, CONF.aws.image_user, pkey=pkey,
|
||||
channel_timeout=30)
|
||||
|
||||
ssh_client.exec_command(
|
||||
'curl http://169.254.169.254/latest/user-data > key.pem && '
|
||||
'chmod 400 key.pem')
|
||||
if 'cirros' in ssh_client.exec_command('cat /etc/issue'):
|
||||
ssh_client.exec_command(
|
||||
'dropbearconvert openssh dropbear key.pem key.db && '
|
||||
'mv key.db key.pem')
|
||||
extra_ssh_opts = '-y'
|
||||
else:
|
||||
extra_ssh_opts = ('-o UserKnownHostsFile=/dev/null '
|
||||
'-o StrictHostKeyChecking=no')
|
||||
|
||||
ssh_client.exec_command('ping -c 1 %s' % ip_private_address_2)
|
||||
ssh_client.exec_command('ping -c 1 %s' % ping_destination)
|
||||
remote_ping_template = (
|
||||
'ssh -i key.pem %(extra_opts)s %(user)s@%(ip)s '
|
||||
'ping -c 1 %%s' %
|
||||
{'extra_opts': extra_ssh_opts,
|
||||
'user': CONF.aws.image_user,
|
||||
'ip': ip_private_address_2})
|
||||
ssh_client.exec_command(remote_ping_template % ip_private_address_1)
|
||||
try:
|
||||
resp = ssh_client.exec_command(remote_ping_template %
|
||||
ping_destination)
|
||||
except exceptions.SSHExecCommandFailed:
|
||||
pass
|
||||
else:
|
||||
self.assertEqual('', resp)
|
|
@ -1,411 +0,0 @@
|
|||
# Copyright 2015 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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.
|
||||
|
||||
from six.moves import range
|
||||
import time
|
||||
|
||||
import botocore.exceptions
|
||||
from oslo_log import log
|
||||
from tempest.lib.common.utils import data_utils
|
||||
from tempest.lib import decorators
|
||||
|
||||
from ec2api_tempest_plugin import base
|
||||
from ec2api_tempest_plugin import config
|
||||
from ec2api_tempest_plugin.scenario import base as scenario_base
|
||||
|
||||
CONF = config.CONF
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
|
||||
class TagsPagingTest(scenario_base.BaseScenarioTest):
|
||||
|
||||
# NOTE(andrey-mp): limit for tags for one resource in amazon
|
||||
TAGS_COUNT = 10
|
||||
|
||||
@classmethod
|
||||
@base.safe_setup
|
||||
def setUpClass(cls):
|
||||
super(TagsPagingTest, cls).setUpClass()
|
||||
if 'amazon' in CONF.aws.ec2_url:
|
||||
raise cls.skipException('Paging is broken in Amazon.')
|
||||
|
||||
def _create_volume_and_tags(self):
|
||||
data = self.client.create_volume(
|
||||
Size=1, AvailabilityZone=CONF.aws.aws_zone)
|
||||
volume_id = data['VolumeId']
|
||||
self.addResourceCleanUp(self.client.delete_volume, VolumeId=volume_id)
|
||||
self.get_volume_waiter().wait_available(volume_id)
|
||||
|
||||
keys = list()
|
||||
for dummy in range(0, self.TAGS_COUNT):
|
||||
key = data_utils.rand_name('key')
|
||||
value = 'aaa' if dummy < 6 else 'bbb'
|
||||
data = self.client.create_tags(Resources=[volume_id],
|
||||
Tags=[{'Key': key, 'Value': value}])
|
||||
keys.append(key)
|
||||
|
||||
return volume_id, keys
|
||||
|
||||
@decorators.idempotent_id('8df6e612-07cd-466d-99de-9f37954a6c9a')
|
||||
def test_simple_tags_paging_with_many_results(self):
|
||||
volume_id = self._create_volume_and_tags()[0]
|
||||
|
||||
data = self.client.describe_tags(MaxResults=500,
|
||||
Filters=[{'Name': 'resource-id', 'Values': [volume_id]}])
|
||||
self.assertNotIn('NextToken', data)
|
||||
self.assertNotEmpty(data['Tags'])
|
||||
self.assertEqual(self.TAGS_COUNT, len(data['Tags']))
|
||||
|
||||
@decorators.idempotent_id('683883d5-9a94-43f2-a1eb-d193db0e44e9')
|
||||
def test_simple_tags_paging_with_min_results(self):
|
||||
volume_id = self._create_volume_and_tags()[0]
|
||||
|
||||
data = self.client.describe_tags(
|
||||
MaxResults=5,
|
||||
Filters=[{'Name': 'resource-id', 'Values': [volume_id]},
|
||||
{'Name': 'tag-value', 'Values': ['aaa']}])
|
||||
self.assertIn('NextToken', data)
|
||||
self.assertNotEmpty(data['Tags'])
|
||||
|
||||
@decorators.idempotent_id('1db8cc5a-d0b3-4e5f-b411-d84cfa4f21e0')
|
||||
def test_tags_paging_second_page_only_with_token(self):
|
||||
volume_id = self._create_volume_and_tags()[0]
|
||||
|
||||
data = self.client.describe_tags(
|
||||
MaxResults=5,
|
||||
Filters=[{'Name': 'resource-id', 'Values': [volume_id]},
|
||||
{'Name': 'tag-value', 'Values': ['aaa']}])
|
||||
self.assertIn('NextToken', data)
|
||||
self.assertNotEmpty(data['Tags'])
|
||||
data = self.client.describe_tags(
|
||||
NextToken=data['NextToken'],
|
||||
Filters=[{'Name': 'resource-id', 'Values': [volume_id]},
|
||||
{'Name': 'tag-value', 'Values': ['aaa']}])
|
||||
self.assertNotIn('NextToken', data)
|
||||
self.assertNotEmpty(data['Tags'])
|
||||
|
||||
@decorators.idempotent_id('a4d7b315-9616-4f9e-85b7-0f892e09a9a2')
|
||||
def test_tags_paging_with_const_filter(self):
|
||||
volume_id = self._create_volume_and_tags()[0]
|
||||
|
||||
data = self.client.describe_tags(
|
||||
MaxResults=5,
|
||||
Filters=[{'Name': 'resource-id', 'Values': [volume_id]},
|
||||
{'Name': 'tag-value', 'Values': ['aaa']}])
|
||||
self.assertIn('NextToken', data)
|
||||
self.assertNotEmpty(data['Tags'])
|
||||
data = self.client.describe_tags(
|
||||
MaxResults=5, NextToken=data['NextToken'],
|
||||
Filters=[{'Name': 'resource-id', 'Values': [volume_id]},
|
||||
{'Name': 'tag-value', 'Values': ['aaa']}])
|
||||
self.assertNotIn('NextToken', data)
|
||||
self.assertNotEmpty(data['Tags'])
|
||||
|
||||
@decorators.idempotent_id('ad4b793a-8231-4d30-8c26-43736b7b71e4')
|
||||
def test_tags_paging_with_differenet_filters(self):
|
||||
volume_id = self._create_volume_and_tags()[0]
|
||||
|
||||
data = self.client.describe_tags(
|
||||
MaxResults=5,
|
||||
Filters=[{'Name': 'resource-id', 'Values': [volume_id]},
|
||||
{'Name': 'tag-value', 'Values': ['aaa']}])
|
||||
self.assertIn('NextToken', data)
|
||||
self.assertNotEmpty(data['Tags'])
|
||||
data = self.client.describe_tags(
|
||||
MaxResults=5, NextToken=data['NextToken'],
|
||||
Filters=[{'Name': 'resource-id', 'Values': [volume_id]}])
|
||||
self.assertNotEmpty(data['Tags'])
|
||||
self.assertLessEqual(1, len(data['Tags']))
|
||||
|
||||
@decorators.idempotent_id('ec6d68bb-37f3-4c5c-b4c5-000d73fbc1bf')
|
||||
def test_tags_paging_with_tags_deletion(self):
|
||||
volume_id, keys = self._create_volume_and_tags()
|
||||
|
||||
data = self.client.describe_tags(MaxResults=5,
|
||||
Filters=[{'Name': 'resource-id', 'Values': [volume_id]}])
|
||||
self.assertIn('NextToken', data)
|
||||
self.assertNotEmpty(data['Tags'])
|
||||
for key in keys:
|
||||
self.client.delete_tags(Resources=[volume_id], Tags=[{'Key': key}])
|
||||
data = self.client.describe_tags(
|
||||
MaxResults=5, NextToken=data['NextToken'],
|
||||
Filters=[{'Name': 'resource-id', 'Values': [volume_id]}])
|
||||
self.assertNotIn('NextToken', data)
|
||||
self.assertEmpty(data['Tags'])
|
||||
|
||||
@decorators.idempotent_id('37eb0597-998f-4744-8462-d56e5599dcd8')
|
||||
def test_invalid_max_results(self):
|
||||
self.assertRaises('InvalidParameterValue',
|
||||
self.client.describe_tags, MaxResults=4)
|
||||
|
||||
# NOTE(andrey-mp): value more than 1000 in not invalid
|
||||
# but amazon returns 1000 elements
|
||||
self.client.describe_tags(MaxResults=1100)
|
||||
|
||||
|
||||
class VolumesPagingTest(scenario_base.BaseScenarioTest):
|
||||
|
||||
VOLUMES_COUNT = 6
|
||||
|
||||
@classmethod
|
||||
@base.safe_setup
|
||||
def setUpClass(cls):
|
||||
super(VolumesPagingTest, cls).setUpClass()
|
||||
if 'amazon' in CONF.aws.ec2_url:
|
||||
raise cls.skipException('Paging is broken in Amazon.')
|
||||
|
||||
zone = CONF.aws.aws_zone
|
||||
cls.ids = list()
|
||||
for dummy in range(0, cls.VOLUMES_COUNT):
|
||||
data = cls.client.create_volume(Size=1, AvailabilityZone=zone)
|
||||
volume_id = data['VolumeId']
|
||||
cls.addResourceCleanUpStatic(cls.client.delete_volume,
|
||||
VolumeId=volume_id)
|
||||
cls.ids.append(volume_id)
|
||||
for volume_id in cls.ids:
|
||||
cls.get_volume_waiter().wait_available(volume_id)
|
||||
|
||||
@decorators.idempotent_id('d44ea940-d9ae-42a4-b3ce-add296a1678c')
|
||||
def test_simple_volumes_paging_with_many_results(self):
|
||||
data = self.client.describe_volumes(MaxResults=500)
|
||||
self.assertNotIn('NextToken', data)
|
||||
self.assertNotEmpty(data['Volumes'])
|
||||
self.assertLessEqual(self.VOLUMES_COUNT, len(data['Volumes']))
|
||||
|
||||
@decorators.idempotent_id('9780c871-ee90-411c-b6ec-1e2f1785926b')
|
||||
def test_simple_volumes_paging_with_min_results(self):
|
||||
data = self.client.describe_volumes(MaxResults=5)
|
||||
self.assertIn('NextToken', data)
|
||||
self.assertNotEmpty(data['Volumes'])
|
||||
|
||||
@decorators.idempotent_id('692684c4-62bc-457a-899a-07cc5382c9ab')
|
||||
def test_volumes_paging_second_page(self):
|
||||
data = self.client.describe_volumes(MaxResults=5)
|
||||
self.assertIn('NextToken', data)
|
||||
self.assertNotEmpty(data['Volumes'])
|
||||
data = self.client.describe_volumes(
|
||||
MaxResults=5, NextToken=data['NextToken'])
|
||||
self.assertNotIn('NextToken', data)
|
||||
self.assertNotEmpty(data['Volumes'])
|
||||
|
||||
@decorators.idempotent_id('83183fac-bb9b-4c36-8d23-84ed55c57015')
|
||||
def test_invalid_paging(self):
|
||||
self.assertRaises('InvalidParameterValue',
|
||||
self.client.describe_volumes, MaxResults=4)
|
||||
|
||||
self.assertRaises('InvalidParameterCombination',
|
||||
self.client.describe_volumes,
|
||||
MaxResults=5, VolumeIds=[self.ids[0]])
|
||||
|
||||
@decorators.idempotent_id('2a777d78-9f0b-4ab0-a841-73dbaafae0dd')
|
||||
def test_volumes_paging_with_filters(self):
|
||||
data = self.client.describe_volumes(MaxResults=5,
|
||||
Filters=[{'Name': 'volume-id', 'Values': [self.ids[0]]}])
|
||||
self.assertNotEmpty(data['Volumes'])
|
||||
if 'NextToken' in data:
|
||||
# Amazon way
|
||||
data = self.client.describe_volumes(
|
||||
MaxResults=5, NextToken=data['NextToken'],
|
||||
Filters=[{'Name': 'volume-id', 'Values': [self.ids[0]]}])
|
||||
self.assertNotIn('NextToken', data)
|
||||
self.assertEmpty(data['Volumes'])
|
||||
|
||||
data = self.client.describe_volumes(MaxResults=5,
|
||||
Filters=[{'Name': 'volume-id', 'Values': ['vol-*']}])
|
||||
self.assertIn('NextToken', data)
|
||||
self.assertNotEmpty(data['Volumes'])
|
||||
data = self.client.describe_volumes(
|
||||
MaxResults=5, NextToken=data['NextToken'],
|
||||
Filters=[{'Name': 'volume-id', 'Values': ['vol-*']}])
|
||||
self.assertNotEmpty(data['Volumes'])
|
||||
|
||||
|
||||
class SnapshotPagingTest(scenario_base.BaseScenarioTest):
|
||||
|
||||
SNAPSHOTS_COUNT = 6
|
||||
|
||||
@classmethod
|
||||
@base.safe_setup
|
||||
def setUpClass(cls):
|
||||
super(SnapshotPagingTest, cls).setUpClass()
|
||||
if 'amazon' in CONF.aws.ec2_url:
|
||||
raise cls.skipException('Paging is broken in Amazon.')
|
||||
|
||||
zone = CONF.aws.aws_zone
|
||||
|
||||
data = cls.client.create_volume(Size=1, AvailabilityZone=zone)
|
||||
volume_id = data['VolumeId']
|
||||
cls.addResourceCleanUpStatic(cls.client.delete_volume,
|
||||
VolumeId=volume_id)
|
||||
cls.get_volume_waiter().wait_available(volume_id)
|
||||
|
||||
def _create_snapshot():
|
||||
try:
|
||||
return cls.client.create_snapshot(VolumeId=volume_id)
|
||||
except botocore.exceptions.ClientError as e:
|
||||
code = (e.response.get('ResponseMetadata', {})
|
||||
.get('HTTPStatusCode'))
|
||||
if not code or code != 500:
|
||||
raise
|
||||
|
||||
waiter = base.EC2Waiter(_create_snapshot)
|
||||
cls.ids = list()
|
||||
while len(cls.ids) < cls.SNAPSHOTS_COUNT:
|
||||
time.sleep(10)
|
||||
data = waiter.wait_for_result()
|
||||
snapshot_id = data['SnapshotId']
|
||||
cls.addResourceCleanUpStatic(cls.client.delete_snapshot,
|
||||
SnapshotId=snapshot_id)
|
||||
cls.get_snapshot_waiter().wait_available(snapshot_id,
|
||||
final_set=('completed'))
|
||||
cls.ids.append(snapshot_id)
|
||||
|
||||
@decorators.idempotent_id('f44729b1-42d7-4f18-b5e0-f8dc2a03e624')
|
||||
def test_simple_snapshots_paging_with_many_results(self):
|
||||
data = self.client.describe_snapshots(MaxResults=500,
|
||||
OwnerIds=['self'])
|
||||
self.assertNotEmpty(data['Snapshots'])
|
||||
count = 0
|
||||
for s in data['Snapshots']:
|
||||
if s['SnapshotId'] in self.ids:
|
||||
count += 1
|
||||
self.assertEqual(self.SNAPSHOTS_COUNT, count)
|
||||
|
||||
@decorators.idempotent_id('3146c81d-84c0-4817-9318-328f92bece7f')
|
||||
def test_simple_snapshots_paging_with_min_results(self):
|
||||
data = self.client.describe_snapshots(MaxResults=5, OwnerIds=['self'])
|
||||
self.assertIn('NextToken', data)
|
||||
self.assertNotEmpty(data['Snapshots'])
|
||||
|
||||
@decorators.idempotent_id('fef90b60-0a46-4802-a822-98ccb58ff18c')
|
||||
def test_snapshots_paging(self):
|
||||
count = 0
|
||||
max_results = 5
|
||||
kwargs = {'MaxResults': max_results, 'OwnerIds': ['self']}
|
||||
while True:
|
||||
data = self.client.describe_snapshots(*[], **kwargs)
|
||||
self.assertGreaterEqual(max_results, len(data['Snapshots']))
|
||||
for s in data['Snapshots']:
|
||||
if s['SnapshotId'] in self.ids:
|
||||
count += 1
|
||||
if 'NextToken' not in data:
|
||||
break
|
||||
kwargs['NextToken'] = data['NextToken']
|
||||
|
||||
self.assertEqual(self.SNAPSHOTS_COUNT, count)
|
||||
|
||||
@decorators.idempotent_id('8379d875-2979-4573-858f-2fd331ae992c')
|
||||
def test_invalid_paging(self):
|
||||
self.assertRaises('InvalidParameterValue',
|
||||
self.client.describe_snapshots, MaxResults=4)
|
||||
|
||||
self.assertRaises('InvalidParameterCombination',
|
||||
self.client.describe_snapshots,
|
||||
MaxResults=5, SnapshotIds=[self.ids[0]])
|
||||
|
||||
|
||||
class InstancePagingTest(scenario_base.BaseScenarioTest):
|
||||
|
||||
RESERVATIONS_COUNT = 2
|
||||
INSTANCES_IN_RESERVATIONS_COUNT = 3
|
||||
|
||||
@classmethod
|
||||
@base.safe_setup
|
||||
def setUpClass(cls):
|
||||
super(InstancePagingTest, cls).setUpClass()
|
||||
if 'amazon' in CONF.aws.ec2_url:
|
||||
raise cls.skipException('Paging is broken in Amazon.')
|
||||
if not CONF.aws.image_id:
|
||||
raise cls.skipException('aws image_id does not provided')
|
||||
|
||||
cls.ids = list()
|
||||
cls.reservation_ids = list()
|
||||
kwargs = {
|
||||
'ImageId': CONF.aws.image_id,
|
||||
'InstanceType': CONF.aws.instance_type,
|
||||
'Placement': {'AvailabilityZone': CONF.aws.aws_zone},
|
||||
'MinCount': cls.INSTANCES_IN_RESERVATIONS_COUNT,
|
||||
'MaxCount': cls.INSTANCES_IN_RESERVATIONS_COUNT
|
||||
}
|
||||
for dummy in range(0, cls.RESERVATIONS_COUNT):
|
||||
data = cls.client.run_instances(*[], **kwargs)
|
||||
for instance in data['Instances']:
|
||||
cls.ids.append(instance['InstanceId'])
|
||||
cls.reservation_ids.append(data['ReservationId'])
|
||||
|
||||
cls.addResourceCleanUpStatic(cls.client.terminate_instances,
|
||||
InstanceIds=cls.ids)
|
||||
for instance_id in cls.ids:
|
||||
cls.get_instance_waiter().wait_available(instance_id,
|
||||
final_set=('running'))
|
||||
|
||||
@decorators.idempotent_id('703da498-c73f-4fd1-a2be-2feddb5292d0')
|
||||
def test_simple_instances_paging_with_many_results(self):
|
||||
data = self.client.describe_instances(MaxResults=500)
|
||||
self.assertNotIn('NextToken', data)
|
||||
self.assertNotEmpty(data['Reservations'])
|
||||
rcount = 0
|
||||
for r in data['Reservations']:
|
||||
if r['ReservationId'] in self.reservation_ids:
|
||||
rcount += 1
|
||||
self.assertEqual(self.RESERVATIONS_COUNT, rcount)
|
||||
count = self.RESERVATIONS_COUNT * self.INSTANCES_IN_RESERVATIONS_COUNT
|
||||
instances = set()
|
||||
self._collect_own_instances(data, instances)
|
||||
self.assertEqual(count, len(instances))
|
||||
|
||||
@decorators.idempotent_id('f494a2a8-6d75-4ef4-ae15-ac4fd1269107')
|
||||
def test_simple_instances_paging_with_min_results(self):
|
||||
max_results = 5
|
||||
data = self.client.describe_instances(MaxResults=max_results)
|
||||
self.assertIn('NextToken', data)
|
||||
self.assertEqual(max_results, self._count_instances(data))
|
||||
|
||||
@decorators.idempotent_id('429802be-d599-4732-a310-3ffe8274df54')
|
||||
def test_instances_paging(self):
|
||||
max_results = 5
|
||||
kwargs = {'MaxResults': max_results}
|
||||
instances = set()
|
||||
while True:
|
||||
data = self.client.describe_instances(*[], **kwargs)
|
||||
self.assertGreaterEqual(max_results, self._count_instances(data))
|
||||
self._collect_own_instances(data, instances)
|
||||
if 'NextToken' not in data:
|
||||
break
|
||||
kwargs['NextToken'] = data['NextToken']
|
||||
|
||||
count = self.RESERVATIONS_COUNT * self.INSTANCES_IN_RESERVATIONS_COUNT
|
||||
self.assertEqual(count, len(instances))
|
||||
|
||||
@decorators.idempotent_id('061d564d-6d3a-44a8-bec9-9dba04f6f362')
|
||||
def test_invalid_paging(self):
|
||||
self.assertRaises('InvalidParameterValue',
|
||||
self.client.describe_instances, MaxResults=4)
|
||||
|
||||
self.assertRaises('InvalidParameterCombination',
|
||||
self.client.describe_instances,
|
||||
MaxResults=5, InstanceIds=[self.ids[0]])
|
||||
|
||||
def _collect_own_instances(self, data, instances):
|
||||
for reservation in data['Reservations']:
|
||||
for instance in reservation['Instances']:
|
||||
if instance['InstanceId'] in self.ids:
|
||||
instances.add(instance['InstanceId'])
|
||||
|
||||
def _count_instances(self, data):
|
||||
count = 0
|
||||
for reservation in data['Reservations']:
|
||||
count += len(reservation['Instances'])
|
||||
return count
|
|
@ -1,157 +0,0 @@
|
|||
# Copyright 2014 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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 time
|
||||
|
||||
from oslo_log import log
|
||||
from tempest.lib import decorators
|
||||
import testtools
|
||||
|
||||
from ec2api_tempest_plugin import base
|
||||
from ec2api_tempest_plugin import config
|
||||
from ec2api_tempest_plugin.scenario import base as scenario_base
|
||||
|
||||
CONF = config.CONF
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
|
||||
class VpcAddressTest(scenario_base.BaseScenarioTest):
|
||||
|
||||
@base.skip_without_vpc()
|
||||
@decorators.idempotent_id('aa667fc6-fd9e-4664-92b8-23263d643d9e')
|
||||
@testtools.skipUnless(CONF.aws.image_id, "image id is not defined")
|
||||
def test_auto_diassociate_address(self):
|
||||
vpc_id, subnet_id = self.create_vpc_and_subnet('10.3.0.0/20')
|
||||
ni_id1 = self.create_network_interface(subnet_id)
|
||||
gw_id = self.create_and_attach_internet_gateway(vpc_id)
|
||||
self.prepare_route(vpc_id, gw_id)
|
||||
alloc_id1, public_ip1 = self.allocate_address(True)
|
||||
alloc_id2, _ = self.allocate_address(True)
|
||||
|
||||
data = self.client.create_network_interface(SubnetId=subnet_id)
|
||||
ni_id2 = data['NetworkInterface']['NetworkInterfaceId']
|
||||
clean_ni2 = self.addResourceCleanUp(
|
||||
self.client.delete_network_interface, NetworkInterfaceId=ni_id2)
|
||||
self.get_network_interface_waiter().wait_available(ni_id2)
|
||||
|
||||
kwargs = {
|
||||
'ImageId': CONF.aws.image_id,
|
||||
'InstanceType': CONF.aws.instance_type,
|
||||
'MinCount': 1,
|
||||
'MaxCount': 1,
|
||||
'NetworkInterfaces': [
|
||||
{'NetworkInterfaceId': ni_id1, 'DeviceIndex': 0}]
|
||||
}
|
||||
data = self.client.run_instances(*[], **kwargs)
|
||||
instance_id = data['Instances'][0]['InstanceId']
|
||||
clean_i = self.addResourceCleanUp(self.client.terminate_instances,
|
||||
InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_available(instance_id,
|
||||
final_set=('running'))
|
||||
data = self.client.attach_network_interface(DeviceIndex=1,
|
||||
InstanceId=instance_id, NetworkInterfaceId=ni_id2)
|
||||
attachment_id = data['AttachmentId']
|
||||
|
||||
# There are multiple interfaces attached to instance 'i-5310c5af'.
|
||||
# Please specify an interface ID for the operation instead.
|
||||
self.assertRaises('InvalidInstanceID',
|
||||
self.client.associate_address,
|
||||
InstanceId=instance_id, AllocationId=alloc_id1)
|
||||
|
||||
# The networkInterface ID 'eni-ffffffff' does not exist
|
||||
self.assertRaises('InvalidNetworkInterfaceID.NotFound',
|
||||
self.client.associate_address,
|
||||
AllocationId=alloc_id1, NetworkInterfaceId='eni-ffffffff')
|
||||
|
||||
# NOTE(andrey-mp): Amazon needs only network interface if several
|
||||
# present in instance. Error will be there if instance is passed.
|
||||
data = self.client.associate_address(
|
||||
AllocationId=alloc_id1, NetworkInterfaceId=ni_id1)
|
||||
assoc_id1 = data['AssociationId']
|
||||
clean_aa1 = self.addResourceCleanUp(self.client.disassociate_address,
|
||||
AssociationId=assoc_id1)
|
||||
self.get_address_assoc_waiter().wait_available(
|
||||
{'AllocationId': alloc_id1})
|
||||
|
||||
instance = self.get_instance(instance_id)
|
||||
nis = instance.get('NetworkInterfaces', [])
|
||||
self.assertEqual(2, len(nis))
|
||||
for ni in nis:
|
||||
if ni['NetworkInterfaceId'] == ni_id1:
|
||||
self.assertIsNotNone(ni.get('Association'))
|
||||
self.assertEqual(public_ip1, ni['Association']['PublicIp'])
|
||||
elif ni['NetworkInterfaceId'] == ni_id2:
|
||||
self.assertIsNone(ni.get('Association'))
|
||||
else:
|
||||
self.assertTrue(False, 'Unknown interface found: ' + str(ni))
|
||||
|
||||
data = self.client.describe_network_interfaces(
|
||||
NetworkInterfaceIds=[ni_id1, ni_id2])
|
||||
self.assertEqual(2, len(data['NetworkInterfaces']))
|
||||
self.assertEqual('in-use', data['NetworkInterfaces'][0]['Status'])
|
||||
self.assertEqual('in-use', data['NetworkInterfaces'][1]['Status'])
|
||||
|
||||
# NOTE(andrery-mp): associate second address and set delete on
|
||||
# termination to True for interface
|
||||
data = self.client.associate_address(
|
||||
AllocationId=alloc_id2, NetworkInterfaceId=ni_id2)
|
||||
assoc_id2 = data['AssociationId']
|
||||
clean_aa2 = self.addResourceCleanUp(self.client.disassociate_address,
|
||||
AssociationId=assoc_id2)
|
||||
self.get_address_assoc_waiter().wait_available(
|
||||
{'AllocationId': alloc_id2})
|
||||
|
||||
kwargs = {
|
||||
'NetworkInterfaceId': ni_id2,
|
||||
'Attachment': {
|
||||
'AttachmentId': attachment_id,
|
||||
'DeleteOnTermination': True,
|
||||
}
|
||||
}
|
||||
self.client.modify_network_interface_attribute(*[], **kwargs)
|
||||
|
||||
# NOTE(andrey-mp): cleanup
|
||||
time.sleep(3)
|
||||
|
||||
self.client.terminate_instances(InstanceIds=[instance_id])
|
||||
self.cancelResourceCleanUp(clean_i)
|
||||
self.get_instance_waiter().wait_delete(instance_id)
|
||||
|
||||
self.assertRaises('InvalidNetworkInterfaceID.NotFound',
|
||||
self.client.describe_network_interfaces,
|
||||
NetworkInterfaceIds=[ni_id2])
|
||||
self.cancelResourceCleanUp(clean_ni2)
|
||||
self.cancelResourceCleanUp(clean_aa2)
|
||||
|
||||
data = self.client.describe_network_interfaces(
|
||||
NetworkInterfaceIds=[ni_id1])
|
||||
self.assertEqual(1, len(data['NetworkInterfaces']))
|
||||
self.assertEqual('available', data['NetworkInterfaces'][0]['Status'])
|
||||
ni = data['NetworkInterfaces'][0]
|
||||
self.assertIsNotNone(ni.get('Association'))
|
||||
self.assertEqual(public_ip1, ni['Association']['PublicIp'])
|
||||
|
||||
data = self.client.describe_addresses(AllocationIds=[alloc_id1,
|
||||
alloc_id2])
|
||||
for address in data['Addresses']:
|
||||
if address['AllocationId'] == alloc_id1:
|
||||
self.assertIsNotNone(address.get('AssociationId'))
|
||||
elif address['AllocationId'] == alloc_id2:
|
||||
self.assertIsNone(address.get('AssociationId'))
|
||||
|
||||
self.client.disassociate_address(AssociationId=assoc_id1)
|
||||
self.cancelResourceCleanUp(clean_aa1)
|
||||
self.get_address_assoc_waiter().wait_delete(
|
||||
{'AllocationId': alloc_id1})
|
|
@ -1,280 +0,0 @@
|
|||
# Copyright 2014 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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 six
|
||||
from six.moves.urllib.request import urlopen
|
||||
import sys
|
||||
import time
|
||||
|
||||
from lxml import etree
|
||||
from oslo_log import log
|
||||
import paramiko
|
||||
from tempest.lib.common.utils import data_utils
|
||||
from tempest.lib import decorators
|
||||
import testtools
|
||||
|
||||
from ec2api_tempest_plugin import base
|
||||
from ec2api_tempest_plugin import config
|
||||
from ec2api_tempest_plugin.scenario import base as scenario_base
|
||||
from ec2api_tempest_plugin import ssh
|
||||
|
||||
CONF = config.CONF
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
|
||||
class VpnTest(scenario_base.BaseScenarioTest):
|
||||
|
||||
CUSTOMER_GATEWAY_IP = '198.51.100.77'
|
||||
CUSTOMER_VPN_CIDR = '172.16.25.0/24'
|
||||
OPENSWAN_LINK = ('http://mirrors.kernel.org/ubuntu/pool/universe/o/'
|
||||
'openswan/openswan_2.6.38-1_i386.deb')
|
||||
|
||||
@classmethod
|
||||
@base.safe_setup
|
||||
def setUpClass(cls):
|
||||
super(VpnTest, cls).setUpClass()
|
||||
if not base.TesterStateHolder().get_vpc_enabled():
|
||||
raise cls.skipException('VPC is disabled')
|
||||
base.check_vpnaas_enabled()
|
||||
|
||||
@testtools.skip("Some unknown bug. Will fix this later")
|
||||
@decorators.idempotent_id('63c2ac38-cfee-45d3-b765-c9b43859660d')
|
||||
def test_vpn_routing(self):
|
||||
vpc_id, _subnet_id = self.create_vpc_and_subnet('10.42.0.0/20')
|
||||
|
||||
vpn_data = self._create_and_configure_vpn(
|
||||
vpc_id, self.CUSTOMER_GATEWAY_IP, self.CUSTOMER_VPN_CIDR)
|
||||
vgw_id = vpn_data['VpnGatewayId']
|
||||
|
||||
data = self.client.describe_route_tables(
|
||||
Filters=[{'Name': 'vpc-id', 'Values': [vpc_id]}])
|
||||
rtb_id = data['RouteTables'][0]['RouteTableId']
|
||||
data = self.client.describe_route_tables(RouteTableIds=[rtb_id])
|
||||
data = data['RouteTables'][0]
|
||||
route = next((r for r in data['Routes']
|
||||
if r['DestinationCidrBlock'] == self.CUSTOMER_VPN_CIDR),
|
||||
None)
|
||||
if route:
|
||||
self.assertEqual('active', route['State'])
|
||||
self.assertEqual('EnableVgwRoutePropagation', route['Origin'])
|
||||
self.assertIn('PropagatingVgws', data)
|
||||
self.assertNotEmpty(data['PropagatingVgws'])
|
||||
self.assertEqual(vgw_id, data['PropagatingVgws'][0]['GatewayId'])
|
||||
|
||||
@decorators.idempotent_id('9e284d9e-8fee-43c7-bcfb-8ed0dfa27dbc')
|
||||
@testtools.skipUnless(CONF.aws.run_ssh, 'SSH tests are disabled.')
|
||||
@testtools.skipUnless(CONF.aws.run_long_tests, 'Slow test has skipped.')
|
||||
@testtools.skipUnless(CONF.aws.image_id_ubuntu,
|
||||
"ubuntu image id is not defined")
|
||||
@testtools.skipUnless(CONF.aws.image_id,
|
||||
"image id is not defined")
|
||||
def test_vpn_connectivity(self):
|
||||
is_amazon = 'amazon' in CONF.aws.ec2_url
|
||||
|
||||
response = urlopen(self.OPENSWAN_LINK, timeout=30)
|
||||
content = response.read()
|
||||
if not is_amazon:
|
||||
# NOTE(andrey-mp): gating in openstack doesn't have internet access
|
||||
# so we need to download this package and install it with dpkg
|
||||
filename = os.path.basename(self.OPENSWAN_LINK)
|
||||
f = open(filename, 'wb')
|
||||
f.write(content)
|
||||
f.close()
|
||||
|
||||
key_name = data_utils.rand_name('testkey')
|
||||
pkey = self.create_key_pair(key_name)
|
||||
|
||||
# run ubuntu instance to create one of VPN endpoint inside
|
||||
sec_group_name = self.create_standard_security_group()
|
||||
instance_id_ubuntu = self.run_instance(
|
||||
KeyName=key_name, ImageId=CONF.aws.image_id_ubuntu,
|
||||
SecurityGroups=[sec_group_name])
|
||||
public_ip_ubuntu = self.get_instance_ip(instance_id_ubuntu)
|
||||
instance = self.get_instance(instance_id_ubuntu)
|
||||
private_ip_ubuntu = instance['PrivateIpAddress']
|
||||
|
||||
# create VPC, ..., VPN
|
||||
vpc_id, subnet_id = self.create_vpc_and_subnet('10.43.0.0/20')
|
||||
self.prepare_vpc_default_security_group(vpc_id)
|
||||
vpn_data = self._create_and_configure_vpn(
|
||||
vpc_id, public_ip_ubuntu, private_ip_ubuntu + '/32')
|
||||
|
||||
# run general instance inside VPC
|
||||
instance_id = self.run_instance(KeyName=key_name,
|
||||
ImageId=CONF.aws.image_id,
|
||||
SubnetId=subnet_id)
|
||||
instance = self.get_instance(instance_id)
|
||||
private_ip_in_vpc = instance['PrivateIpAddress']
|
||||
|
||||
# configure ubuntu, install openswan and run it
|
||||
ssh_client = ssh.Client(public_ip_ubuntu, CONF.aws.image_user_ubuntu,
|
||||
pkey=pkey)
|
||||
if not is_amazon:
|
||||
self._upload_file(ssh_client, filename, filename)
|
||||
ssh_client.exec_command('sudo DEBIAN_FRONTEND=noninteractive'
|
||||
' dpkg -i ' + filename)
|
||||
else:
|
||||
ssh_client.exec_command('DEBIAN_FRONTEND=noninteractive sudo '
|
||||
'apt-get install -fqy openswan')
|
||||
ssh_client.exec_command('sudo -s su -c "'
|
||||
'echo 1 > /proc/sys/net/ipv4/ip_forward"')
|
||||
ssh_client.exec_command(
|
||||
'for vpn in /proc/sys/net/ipv4/conf/*; do sudo -s su -c'
|
||||
' "echo 0 > $vpn/accept_redirects; echo 0 > $vpn/send_redirects";'
|
||||
' done')
|
||||
sysctl_additions = [
|
||||
'net.ipv4.ip_forward = 1',
|
||||
'net.ipv4.conf.all.accept_redirects = 0',
|
||||
'net.ipv4.conf.all.send_redirects = 0']
|
||||
for item in sysctl_additions:
|
||||
ssh_client.exec_command(
|
||||
'sudo -s su -c "echo \'' + item + '\' >> /etc/sysctl.conf"')
|
||||
ssh_client.exec_command('sudo sysctl -p')
|
||||
ipsec_conf, ipsec_secrets = self._get_ipsec_conf(
|
||||
vpn_data['VpnConnectionId'], private_ip_ubuntu)
|
||||
ssh_client.exec_command('sudo -s su -c "echo \'\' > /etc/ipsec.conf"')
|
||||
for fstr in ipsec_conf:
|
||||
ssh_client.exec_command(
|
||||
'sudo -s su -c "echo \'%s\' >> /etc/ipsec.conf"' % fstr)
|
||||
ssh_client.exec_command(
|
||||
'sudo -s su -c "echo \'%s\' > /etc/ipsec.secrets"' % ipsec_secrets)
|
||||
|
||||
ssh_client.exec_command('sudo service ipsec restart')
|
||||
|
||||
try:
|
||||
self.get_vpn_connection_tunnel_waiter().wait_available(
|
||||
vpn_data['VpnConnectionId'], ('UP'))
|
||||
except Exception:
|
||||
exc_info = sys.exc_info()
|
||||
try:
|
||||
output = ssh_client.exec_command('sudo ipsec auto --status')
|
||||
LOG.warning(output)
|
||||
except Exception:
|
||||
pass
|
||||
six.reraise(exc_info[1], None, exc_info[2])
|
||||
time.sleep(10)
|
||||
|
||||
ssh_client.exec_command('ping -c 4 %s' % private_ip_in_vpc)
|
||||
|
||||
def _upload_file(self, ssh_client, local_path, remote_path):
|
||||
ssh = ssh_client._get_ssh_connection()
|
||||
transport = ssh.get_transport()
|
||||
sftp_client = paramiko.SFTPClient.from_transport(transport)
|
||||
sftp_client.put(local_path, remote_path)
|
||||
|
||||
def _create_and_configure_vpn(self, vpc_id, cgw_ip, customer_subnet):
|
||||
data = self.client.create_customer_gateway(
|
||||
Type='ipsec.1', PublicIp=cgw_ip, BgpAsn=65000)
|
||||
cgw_id = data['CustomerGateway']['CustomerGatewayId']
|
||||
self.addResourceCleanUp(
|
||||
self.client.delete_customer_gateway, CustomerGatewayId=cgw_id)
|
||||
self.get_customer_gateway_waiter().wait_available(cgw_id)
|
||||
|
||||
data = self.client.create_vpn_gateway(
|
||||
Type='ipsec.1', AvailabilityZone=CONF.aws.aws_zone)
|
||||
vgw_id = data['VpnGateway']['VpnGatewayId']
|
||||
self.addResourceCleanUp(
|
||||
self.client.delete_vpn_gateway, VpnGatewayId=vgw_id)
|
||||
self.get_vpn_gateway_waiter().wait_available(vgw_id)
|
||||
|
||||
data = self.client.attach_vpn_gateway(VpnGatewayId=vgw_id,
|
||||
VpcId=vpc_id)
|
||||
self.addResourceCleanUp(self.client.detach_vpn_gateway,
|
||||
VpnGatewayId=vgw_id, VpcId=vpc_id)
|
||||
self.get_vpn_gateway_attachment_waiter().wait_available(
|
||||
vgw_id, 'attached')
|
||||
|
||||
data = self.client.describe_route_tables(
|
||||
Filters=[{'Name': 'vpc-id', 'Values': [vpc_id]}])
|
||||
rtb_id = data['RouteTables'][0]['RouteTableId']
|
||||
data = self.client.enable_vgw_route_propagation(RouteTableId=rtb_id,
|
||||
GatewayId=vgw_id)
|
||||
self.addResourceCleanUp(self.client.disable_vgw_route_propagation,
|
||||
RouteTableId=rtb_id, GatewayId=vgw_id)
|
||||
|
||||
data = self.client.create_vpn_connection(
|
||||
CustomerGatewayId=cgw_id, VpnGatewayId=vgw_id,
|
||||
Options={'StaticRoutesOnly': True}, Type='ipsec.1')
|
||||
vpn_data = data['VpnConnection']
|
||||
vpn_id = data['VpnConnection']['VpnConnectionId']
|
||||
self.addResourceCleanUp(self.client.delete_vpn_connection,
|
||||
VpnConnectionId=vpn_id)
|
||||
self.get_vpn_connection_waiter().wait_available(vpn_id)
|
||||
|
||||
data = self.client.create_vpn_connection_route(
|
||||
VpnConnectionId=vpn_id,
|
||||
DestinationCidrBlock=customer_subnet)
|
||||
self.get_vpn_connection_route_waiter(customer_subnet).wait_available(
|
||||
vpn_id)
|
||||
|
||||
return vpn_data
|
||||
|
||||
def _get_ipsec_conf(self, vpn_connection_id, private_ip_ubuntu):
|
||||
data = self.client.describe_vpn_connections(
|
||||
VpnConnectionIds=[vpn_connection_id])
|
||||
vpn_data = data['VpnConnections'][0]
|
||||
vpn_config = etree.fromstring(
|
||||
vpn_data['CustomerGatewayConfiguration'])
|
||||
psks = vpn_config.xpath(
|
||||
'/vpn_connection/ipsec_tunnel/ike/pre_shared_key')
|
||||
self.assertNotEmpty(psks)
|
||||
vgw_ip = vpn_config.xpath(
|
||||
'/vpn_connection/ipsec_tunnel/vpn_gateway/tunnel_outside_address'
|
||||
'/ip_address')
|
||||
self.assertTrue(vgw_ip)
|
||||
|
||||
ipsec_key = psks[0].text
|
||||
vgw_ip = vgw_ip[0].text
|
||||
|
||||
ipsec_conf = []
|
||||
for item in self._ipsec_conf:
|
||||
ipsec_conf.append(item % {
|
||||
'vpc_cidr': '10.43.0.0/20',
|
||||
'vgw_ip': vgw_ip,
|
||||
'private_ip_ubuntu': private_ip_ubuntu})
|
||||
|
||||
ipsec_secrets = ('%(private_ip_ubuntu)s %(vgw_ip)s: '
|
||||
'PSK \\"%(ipsec_key)s\\"' % {
|
||||
'private_ip_ubuntu': private_ip_ubuntu,
|
||||
'vgw_ip': vgw_ip,
|
||||
'ipsec_key': ipsec_key})
|
||||
|
||||
return ipsec_conf, ipsec_secrets
|
||||
|
||||
_ipsec_conf = [
|
||||
'## general configuration parameters ##',
|
||||
'config setup',
|
||||
' plutodebug=all',
|
||||
' plutostderrlog=/var/log/pluto.log',
|
||||
' protostack=netkey',
|
||||
' nat_traversal=yes',
|
||||
' virtual_private=%%v4:%(vpc_cidr)s',
|
||||
' nhelpers=0',
|
||||
'## connection definition in Debian ##',
|
||||
'conn my-conn',
|
||||
' authby=secret',
|
||||
' auto=start',
|
||||
' pfs=yes',
|
||||
' type=tunnel',
|
||||
' #left side (myside)',
|
||||
' left=%(private_ip_ubuntu)s',
|
||||
' leftsubnet=%(private_ip_ubuntu)s/32',
|
||||
' leftnexthop=%(vgw_ip)s',
|
||||
' leftsourceip=%(private_ip_ubuntu)s',
|
||||
' #right security gateway (VPN side)',
|
||||
' right=%(vgw_ip)s',
|
||||
' rightsubnet=%(vpc_cidr)s',
|
||||
' rightnexthop=%(private_ip_ubuntu)s']
|
|
@ -1,90 +0,0 @@
|
|||
# Copyright 2012 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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 socket
|
||||
import time
|
||||
import warnings
|
||||
|
||||
from oslo_log import log as logging
|
||||
|
||||
from tempest.lib.common import ssh
|
||||
|
||||
from tempest.lib import exceptions
|
||||
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("ignore")
|
||||
import paramiko
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
DIS_ALG = dict(pubkeys=['rsa-sha2-256', 'rsa-sha2-512'])
|
||||
|
||||
|
||||
class Client(ssh.Client):
|
||||
|
||||
def _get_ssh_connection(self, sleep=1.5, backoff=1):
|
||||
"""Returns an ssh connection to the specified host."""
|
||||
bsleep = sleep
|
||||
ssh = paramiko.SSHClient()
|
||||
ssh.set_missing_host_key_policy(
|
||||
paramiko.AutoAddPolicy())
|
||||
_start_time = time.time()
|
||||
if self.pkey is not None:
|
||||
LOG.info("Creating ssh connection to '%s:%d' as '%s'"
|
||||
" with public key authentication",
|
||||
self.host, self.port, self.username)
|
||||
else:
|
||||
LOG.info("Creating ssh connection to '%s:%d' as '%s'"
|
||||
" with password %s",
|
||||
self.host, self.port, self.username, str(self.password))
|
||||
attempts = 0
|
||||
while True:
|
||||
if self.proxy_client is not None:
|
||||
proxy_chan = self._get_proxy_channel()
|
||||
else:
|
||||
proxy_chan = None
|
||||
try:
|
||||
ssh.connect(self.host, port=self.port,
|
||||
username=self.username,
|
||||
password=self.password,
|
||||
look_for_keys=self.look_for_keys,
|
||||
key_filename=self.key_filename,
|
||||
timeout=self.channel_timeout, pkey=self.pkey,
|
||||
sock=proxy_chan,
|
||||
disabled_algorithms=DIS_ALG)
|
||||
LOG.info("ssh connection to %s@%s successfully created",
|
||||
self.username, self.host)
|
||||
return ssh
|
||||
except (EOFError,
|
||||
socket.error, socket.timeout,
|
||||
paramiko.SSHException) as e:
|
||||
ssh.close()
|
||||
if self._is_timed_out(_start_time):
|
||||
LOG.exception("Failed to establish authenticated ssh"
|
||||
" connection to %s@%s after %d attempts. "
|
||||
"Proxy client: %s",
|
||||
self.username, self.host, attempts,
|
||||
self._get_proxy_client_info())
|
||||
raise exceptions.SSHTimeout(host=self.host,
|
||||
user=self.username,
|
||||
password=self.password)
|
||||
bsleep += backoff
|
||||
attempts += 1
|
||||
LOG.warning("Failed to establish authenticated ssh"
|
||||
" connection to %s@%s (%s). Number attempts: %s."
|
||||
" Retry after %d seconds.",
|
||||
self.username, self.host, e, attempts, bsleep)
|
||||
time.sleep(bsleep)
|
|
@ -1,14 +0,0 @@
|
|||
# The order of packages is significant, because pip processes them in the order
|
||||
# of appearance. Changing the order has an impact on the overall integration
|
||||
# process, which may cause wedges in the gate later.
|
||||
|
||||
pbr!=2.1.0,>=2.0.0 # Apache-2.0
|
||||
botocore>=1.5.1 # Apache-2.0
|
||||
oslo.config>=5.2.0 # Apache-2.0
|
||||
oslo.log>=3.36.0 # Apache-2.0
|
||||
six>=1.10.0 # MIT
|
||||
testtools>=2.2.0 # MIT
|
||||
paramiko>=2.0.0 # LGPLv2.1+
|
||||
netaddr>=0.7.18 # BSD
|
||||
lxml!=3.7.0,>=3.4.1 # BSD
|
||||
tempest>=17.1.0 # Apache-2.0
|
42
setup.cfg
42
setup.cfg
|
@ -1,42 +0,0 @@
|
|||
[metadata]
|
||||
name = ec2api-tempest-plugin
|
||||
summary = Tempest plugin for ec2-api
|
||||
description-file =
|
||||
README.rst
|
||||
author = OpenStack
|
||||
author-email = openstack-discuss@lists.openstack.org
|
||||
home-page = https://opendev.org/openstack/ec2api-tempest-plugin
|
||||
classifier =
|
||||
Environment :: OpenStack
|
||||
Intended Audience :: Information Technology
|
||||
Intended Audience :: System Administrators
|
||||
License :: OSI Approved :: Apache Software License
|
||||
Operating System :: POSIX :: Linux
|
||||
Programming Language :: Python
|
||||
Programming Language :: Python :: 3
|
||||
Programming Language :: Python :: 3.5
|
||||
Programming Language :: Python :: 3.6
|
||||
Programming Language :: Python :: 3.7
|
||||
Programming Language :: Python :: 3.8
|
||||
|
||||
[files]
|
||||
packages =
|
||||
ec2api_tempest_plugin
|
||||
|
||||
[compile_catalog]
|
||||
directory = ec2api_tempest_plugin/locale
|
||||
domain = ec2api_tempest_plugin
|
||||
|
||||
[update_catalog]
|
||||
domain = ec2api_tempest_plugin
|
||||
output_dir = ec2api_tempest_plugin/locale
|
||||
input_file = ec2api_tempest_plugin/locale/ec2api_tempest_plugin.pot
|
||||
|
||||
[extract_messages]
|
||||
keywords = _ gettext ngettext l_ lazy_gettext
|
||||
mapping_file = babel.cfg
|
||||
output_file = ec2api_tempest_plugin/locale/ec2api_tempest_plugin.pot
|
||||
|
||||
[entry_points]
|
||||
tempest.test_plugins =
|
||||
aws_tests = ec2api_tempest_plugin.plugin:AWSTempestPlugin
|
29
setup.py
29
setup.py
|
@ -1,29 +0,0 @@
|
|||
# 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.
|
||||
|
||||
# THIS FILE IS MANAGED BY THE GLOBAL REQUIREMENTS REPO - DO NOT EDIT
|
||||
import setuptools
|
||||
|
||||
# In python < 2.7.4, a lazy loading of package `pbr` will break
|
||||
# setuptools if some other modules registered functions in `atexit`.
|
||||
# solution from: http://bugs.python.org/issue15881#msg170215
|
||||
try:
|
||||
import multiprocessing # noqa
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
setuptools.setup(
|
||||
setup_requires=['pbr>=2.0.0'],
|
||||
pbr=True)
|
|
@ -1,5 +0,0 @@
|
|||
# The order of packages is significant, because pip processes them in the order
|
||||
# of appearance. Changing the order has an impact on the overall integration
|
||||
# process, which may cause wedges in the gate later.
|
||||
|
||||
hacking>=3.2.0 # Apache-2.0
|
48
tox.ini
48
tox.ini
|
@ -1,48 +0,0 @@
|
|||
[tox]
|
||||
minversion = 3.18.0
|
||||
envlist = py37,pep8
|
||||
skipsdist = True
|
||||
ignore_basepython_conflict = True
|
||||
|
||||
[testenv]
|
||||
usedevelop = True
|
||||
basepython = python3
|
||||
# tox is silly... these need to be separated by a newline....
|
||||
allowlist_externals = bash
|
||||
find
|
||||
rm
|
||||
env
|
||||
install_command = pip install -c{env:UPPER_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master} {opts} {packages}
|
||||
setenv =
|
||||
VIRTUAL_ENV={envdir}
|
||||
OS_STDOUT_CAPTURE=1
|
||||
OS_STDERR_CAPTURE=1
|
||||
OS_TEST_TIMEOUT=60
|
||||
PYTHONWARNINGS=default::DeprecationWarning
|
||||
LANG=en_US.UTF-8
|
||||
LANGUAGE=en_US:en
|
||||
LC_ALL=C
|
||||
deps = -r{toxinidir}/test-requirements.txt
|
||||
commands =
|
||||
find . -type f -name "*.pyc" -delete
|
||||
rm -f .testrepository/times.dbm
|
||||
|
||||
[testenv:pep8]
|
||||
commands = flake8 {posargs}
|
||||
|
||||
[testenv:venv]
|
||||
commands = {posargs}
|
||||
|
||||
[testenv:debug]
|
||||
commands = oslo_debug_helper {posargs}
|
||||
|
||||
[flake8]
|
||||
# E123, E125 skipped as they are invalid PEP-8.
|
||||
|
||||
show-source = True
|
||||
ignore = E122,E123,E125,E126,E127,E128,W503,W504
|
||||
builtins = _
|
||||
# H106: Don't put vim configuration in source files
|
||||
# H203: Use assertIs(Not)None to check for None
|
||||
enable-extensions=H106,H203
|
||||
exclude=.venv,.git,.tox,dist,doc,*lib/python*,*egg,build
|
Loading…
Reference in New Issue