Adds integration testing for api samples
We have no validation the the samples at api.openstack.org are actually correct. This creates a framework to validate the request and response samples through integration tests. Adds a bit of stubbing in fake_network to return simple network_info along with instance records and adds a call in image/fake to get av valid image. It will create non-templated versions of the samples when the tests are running if GENERATE_SAMPLES is set in the environment when running nova/tests/integrated/test_api_samples.py Change-Id: Id134af0b23f0d0932c8789697439ce94bbe2834b
This commit is contained in:
parent
6293c0b1dc
commit
714047e8eb
@ -15,6 +15,7 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from nova.compute import api as compute_api
|
||||
from nova.compute import manager as compute_manager
|
||||
import nova.context
|
||||
from nova import db
|
||||
@ -396,3 +397,53 @@ def unset_stub_network_methods(stubs):
|
||||
cm = compute_manager.ComputeManager
|
||||
for name in _real_functions:
|
||||
stubs.Set(cm, name, _real_functions[name])
|
||||
|
||||
|
||||
def stub_compute_with_ips(stubs):
|
||||
orig_get = compute_api.API.get
|
||||
orig_get_all = compute_api.API.get_all
|
||||
|
||||
def fake_get(*args, **kwargs):
|
||||
return _get_instances_with_cached_ips(orig_get, *args, **kwargs)
|
||||
|
||||
def fake_get_all(*args, **kwargs):
|
||||
return _get_instances_with_cached_ips(orig_get_all, *args, **kwargs)
|
||||
|
||||
stubs.Set(compute_api.API, 'get', fake_get)
|
||||
stubs.Set(compute_api.API, 'get_all', fake_get_all)
|
||||
|
||||
|
||||
def _get_fake_cache():
|
||||
def _ip(ip, fixed=True, floats=None):
|
||||
ip_dict = {'address': ip, 'type': 'fixed'}
|
||||
if not fixed:
|
||||
ip_dict['type'] = 'floating'
|
||||
if fixed and floats:
|
||||
ip_dict['floating_ips'] = [_ip(f, fixed=False) for f in floats]
|
||||
return ip_dict
|
||||
|
||||
info = [{'address': 'aa:bb:cc:dd:ee:ff',
|
||||
'id': 1,
|
||||
'network': {'bridge': 'br0',
|
||||
'id': 1,
|
||||
'label': 'private',
|
||||
'subnets': [{'cidr': '192.168.0.0/24',
|
||||
'ips': [_ip('192.168.0.3')]}]}}]
|
||||
if FLAGS.use_ipv6:
|
||||
ipv6_addr = 'fe80:b33f::a8bb:ccff:fedd:eeff'
|
||||
info[0]['network']['subnets'].append({'cidr': 'fe80:b33f::/64',
|
||||
'ips': [_ip(ipv6_addr)]})
|
||||
return info
|
||||
|
||||
|
||||
def _get_instances_with_cached_ips(orig_func, *args, **kwargs):
|
||||
"""Kludge the cache into instance(s) without having to create DB
|
||||
entries
|
||||
"""
|
||||
instances = orig_func(*args, **kwargs)
|
||||
if isinstance(instances, list):
|
||||
for instance in instances:
|
||||
instance['info_cache'] = {'network_info': _get_fake_cache()}
|
||||
else:
|
||||
instances['info_cache'] = {'network_info': _get_fake_cache()}
|
||||
return instances
|
||||
|
@ -230,6 +230,10 @@ def FakeImageService_reset():
|
||||
_fakeImageService = _FakeImageService()
|
||||
|
||||
|
||||
def get_valid_image_id():
|
||||
return _fakeImageService.images.keys()[0]
|
||||
|
||||
|
||||
def stub_out_image_service(stubs):
|
||||
def fake_get_remote_image_service(context, image_href):
|
||||
return (FakeImageService(), image_href)
|
||||
|
11
nova/tests/integrated/api_samples/README.rst
Normal file
11
nova/tests/integrated/api_samples/README.rst
Normal file
@ -0,0 +1,11 @@
|
||||
Api Samples
|
||||
===========
|
||||
|
||||
Samples in this directory are automatically generated from the api samples
|
||||
integration tests. To regenerate the samples, simply set GENERATE_SAMPLES
|
||||
in the environment before running the tests. For example:
|
||||
|
||||
GENERATE_SAMPLES=True ./run_tests.py nova.tests.integrated
|
||||
|
||||
If new tests are added or the .tpl files are changed due to bug fixes, the
|
||||
samples should be regenerated so they are in sync with the templates.
|
@ -0,0 +1,68 @@
|
||||
{
|
||||
"server": {
|
||||
"OS-DCF:diskConfig": "AUTO",
|
||||
"OS-EXT-SRV-ATTR:host": "3972bc79fa2a4754b7559153a5a48422",
|
||||
"OS-EXT-SRV-ATTR:hypervisor_hostname": null,
|
||||
"OS-EXT-SRV-ATTR:instance_name": "instance-00000001",
|
||||
"OS-EXT-STS:power_state": 1,
|
||||
"OS-EXT-STS:task_state": null,
|
||||
"OS-EXT-STS:vm_state": "active",
|
||||
"accessIPv4": "",
|
||||
"accessIPv6": "",
|
||||
"addresses": {
|
||||
"private": [
|
||||
{
|
||||
"addr": "192.168.0.3",
|
||||
"version": 4
|
||||
}
|
||||
]
|
||||
},
|
||||
"config_drive": "",
|
||||
"created": "2012-08-20T21:11:06Z",
|
||||
"flavor": {
|
||||
"id": "1",
|
||||
"links": [
|
||||
{
|
||||
"href": "http://openstack.example.com/openstack/flavors/1",
|
||||
"rel": "bookmark"
|
||||
}
|
||||
]
|
||||
},
|
||||
"hostId": "dc23873c80c22f14705d190b645b59398cbc8ed3cdf6145468051c0d",
|
||||
"id": "7dc62bde-85f0-45b5-8c74-5fb209314807",
|
||||
"image": {
|
||||
"id": "70a599e0-31e7-49b7-b260-868f441e862b",
|
||||
"links": [
|
||||
{
|
||||
"href": "http://openstack.example.com/openstack/images/70a599e0-31e7-49b7-b260-868f441e862b",
|
||||
"rel": "bookmark"
|
||||
}
|
||||
]
|
||||
},
|
||||
"key_name": null,
|
||||
"links": [
|
||||
{
|
||||
"href": "http://openstack.example.com/v2/openstack/servers/7dc62bde-85f0-45b5-8c74-5fb209314807",
|
||||
"rel": "self"
|
||||
},
|
||||
{
|
||||
"href": "http://openstack.example.com/openstack/servers/7dc62bde-85f0-45b5-8c74-5fb209314807",
|
||||
"rel": "bookmark"
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"My Server Name": "Apache1"
|
||||
},
|
||||
"name": "new-server-test",
|
||||
"progress": 0,
|
||||
"security_groups": [
|
||||
{
|
||||
"name": "default"
|
||||
}
|
||||
],
|
||||
"status": "ACTIVE",
|
||||
"tenant_id": "openstack",
|
||||
"updated": "2012-08-20T21:11:06Z",
|
||||
"user_id": "fake"
|
||||
}
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
{
|
||||
"server": {
|
||||
"OS-DCF:diskConfig": "AUTO",
|
||||
"OS-EXT-SRV-ATTR:host": "%(compute_host)s",
|
||||
"OS-EXT-SRV-ATTR:hypervisor_hostname": null,
|
||||
"OS-EXT-SRV-ATTR:instance_name": "instance-00000001",
|
||||
"OS-EXT-STS:power_state": 1,
|
||||
"OS-EXT-STS:task_state": null,
|
||||
"OS-EXT-STS:vm_state": "active",
|
||||
"accessIPv4": "",
|
||||
"accessIPv6": "",
|
||||
"addresses": {
|
||||
"private": [
|
||||
{
|
||||
"addr": "%(ip)s",
|
||||
"version": 4
|
||||
}
|
||||
]
|
||||
},
|
||||
"config_drive": "",
|
||||
"created": "%(timestamp)s",
|
||||
"flavor": {
|
||||
"id": "1",
|
||||
"links": [
|
||||
{
|
||||
"href": "%(host)s/openstack/flavors/1",
|
||||
"rel": "bookmark"
|
||||
}
|
||||
]
|
||||
},
|
||||
"hostId": "%(hostid)s",
|
||||
"id": "%(uuid)s",
|
||||
"image": {
|
||||
"id": "%(uuid)s",
|
||||
"links": [
|
||||
{
|
||||
"href": "%(host)s/openstack/images/%(uuid)s",
|
||||
"rel": "bookmark"
|
||||
}
|
||||
]
|
||||
},
|
||||
"key_name": null,
|
||||
"links": [
|
||||
{
|
||||
"href": "%(host)s/v2/openstack/servers/%(uuid)s",
|
||||
"rel": "self"
|
||||
},
|
||||
{
|
||||
"href": "%(host)s/openstack/servers/%(uuid)s",
|
||||
"rel": "bookmark"
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"My Server Name": "Apache1"
|
||||
},
|
||||
"name": "new-server-test",
|
||||
"progress": 0,
|
||||
"security_groups": [
|
||||
{
|
||||
"name": "default"
|
||||
}
|
||||
],
|
||||
"status": "ACTIVE",
|
||||
"tenant_id": "openstack",
|
||||
"updated": "%(timestamp)s",
|
||||
"user_id": "fake"
|
||||
}
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<server xmlns:OS-DCF="http://docs.openstack.org/compute/ext/disk_config/api/v1.1" xmlns:OS-EXT-SRV-ATTR="http://docs.openstack.org/compute/ext/extended_status/api/v1.1" xmlns:OS-EXT-STS="http://docs.openstack.org/compute/ext/extended_status/api/v1.1" xmlns:atom="http://www.w3.org/2005/Atom" xmlns="http://docs.openstack.org/compute/api/v1.1" status="ACTIVE" updated="2012-08-20T21:11:08Z" hostId="96727264c2742d842c80c182cd505afa6108eb16305773070f893e23" name="new-server-test" created="2012-08-20T21:11:08Z" userId="fake" tenantId="openstack" accessIPv4="" accessIPv6="" progress="0" id="2c7a2ff8-63ce-4dcb-a3fa-1c311fe9fb04" config_drive="" key_name="None" OS-EXT-SRV-ATTR:instance_name="instance-00000001" OS-EXT-SRV-ATTR:host="6d7bdd9082cd4294aae7804dc0e5f214" OS-DCF:diskConfig="AUTO" OS-EXT-SRV-ATTR:vm_state="active" OS-EXT-SRV-ATTR:task_state="None" OS-EXT-SRV-ATTR:power_state="1">
|
||||
<image id="70a599e0-31e7-49b7-b260-868f441e862b">
|
||||
<atom:link href="http://openstack.example.com/openstack/images/70a599e0-31e7-49b7-b260-868f441e862b" rel="bookmark"/>
|
||||
</image>
|
||||
<flavor id="1">
|
||||
<atom:link href="http://openstack.example.com/openstack/flavors/1" rel="bookmark"/>
|
||||
</flavor>
|
||||
<metadata>
|
||||
<meta key="My Server Name">Apache1</meta>
|
||||
</metadata>
|
||||
<addresses>
|
||||
<network id="private">
|
||||
<ip version="4" addr="192.168.0.3"/>
|
||||
</network>
|
||||
</addresses>
|
||||
<atom:link href="http://openstack.example.com/v2/openstack/servers/2c7a2ff8-63ce-4dcb-a3fa-1c311fe9fb04" rel="self"/>
|
||||
<atom:link href="http://openstack.example.com/openstack/servers/2c7a2ff8-63ce-4dcb-a3fa-1c311fe9fb04" rel="bookmark"/>
|
||||
<security_groups>
|
||||
<security_group name="default"/>
|
||||
</security_groups>
|
||||
</server>
|
@ -0,0 +1,22 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<server xmlns:OS-DCF="http://docs.openstack.org/compute/ext/disk_config/api/v1.1" xmlns:OS-EXT-SRV-ATTR="http://docs.openstack.org/compute/ext/extended_status/api/v1.1" xmlns:OS-EXT-STS="http://docs.openstack.org/compute/ext/extended_status/api/v1.1" xmlns:atom="http://www.w3.org/2005/Atom" xmlns="http://docs.openstack.org/compute/api/v1.1" status="ACTIVE" updated="%(timestamp)s" hostId="%(hostid)s" name="new-server-test" created="%(timestamp)s" userId="fake" tenantId="openstack" accessIPv4="" accessIPv6="" progress="0" id="%(id)s" config_drive="" key_name="None" OS-EXT-SRV-ATTR:instance_name="instance-00000001" OS-EXT-SRV-ATTR:host="%(compute_host)s" OS-DCF:diskConfig="AUTO" OS-EXT-SRV-ATTR:vm_state="active" OS-EXT-SRV-ATTR:task_state="None" OS-EXT-SRV-ATTR:power_state="1">
|
||||
<image id="%(uuid)s">
|
||||
<atom:link href="%(host)s/openstack/images/%(uuid)s" rel="bookmark"/>
|
||||
</image>
|
||||
<flavor id="1">
|
||||
<atom:link href="%(host)s/openstack/flavors/1" rel="bookmark"/>
|
||||
</flavor>
|
||||
<metadata>
|
||||
<meta key="My Server Name">Apache1</meta>
|
||||
</metadata>
|
||||
<addresses>
|
||||
<network id="private">
|
||||
<ip version="4" addr="%(ip)s"/>
|
||||
</network>
|
||||
</addresses>
|
||||
<atom:link href="%(host)s/v2/openstack/servers/%(uuid)s" rel="self"/>
|
||||
<atom:link href="%(host)s/openstack/servers/%(uuid)s" rel="bookmark"/>
|
||||
<security_groups>
|
||||
<security_group name="default"/>
|
||||
</security_groups>
|
||||
</server>
|
@ -0,0 +1,16 @@
|
||||
{
|
||||
"server": {
|
||||
"flavorRef": "http://openstack.example.com/openstack/flavors/1",
|
||||
"imageRef": "http://openstack.example.com/openstack/images/70a599e0-31e7-49b7-b260-868f441e862b",
|
||||
"metadata": {
|
||||
"My Server Name": "Apache1"
|
||||
},
|
||||
"name": "new-server-test",
|
||||
"personality": [
|
||||
{
|
||||
"contents": "ICAgICAgDQoiQSBjbG91ZCBkb2VzIG5vdCBrbm93IHdoeSBpdCBtb3ZlcyBpbiBqdXN0IHN1Y2ggYSBkaXJlY3Rpb24gYW5kIGF0IHN1Y2ggYSBzcGVlZC4uLkl0IGZlZWxzIGFuIGltcHVsc2lvbi4uLnRoaXMgaXMgdGhlIHBsYWNlIHRvIGdvIG5vdy4gQnV0IHRoZSBza3kga25vd3MgdGhlIHJlYXNvbnMgYW5kIHRoZSBwYXR0ZXJucyBiZWhpbmQgYWxsIGNsb3VkcywgYW5kIHlvdSB3aWxsIGtub3csIHRvbywgd2hlbiB5b3UgbGlmdCB5b3Vyc2VsZiBoaWdoIGVub3VnaCB0byBzZWUgYmV5b25kIGhvcml6b25zLiINCg0KLVJpY2hhcmQgQmFjaA==",
|
||||
"path": "/etc/banner.txt"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
{
|
||||
"server" : {
|
||||
"name" : "new-server-test",
|
||||
"imageRef" : "%(host)s/openstack/images/%(image_id)s",
|
||||
"flavorRef" : "%(host)s/openstack/flavors/1",
|
||||
"metadata" : {
|
||||
"My Server Name" : "Apache1"
|
||||
},
|
||||
"personality" : [
|
||||
{
|
||||
"path" : "/etc/banner.txt",
|
||||
"contents" : "ICAgICAgDQoiQSBjbG91ZCBkb2VzIG5vdCBrbm93IHdoeSBpdCBtb3ZlcyBpbiBqdXN0IHN1Y2ggYSBkaXJlY3Rpb24gYW5kIGF0IHN1Y2ggYSBzcGVlZC4uLkl0IGZlZWxzIGFuIGltcHVsc2lvbi4uLnRoaXMgaXMgdGhlIHBsYWNlIHRvIGdvIG5vdy4gQnV0IHRoZSBza3kga25vd3MgdGhlIHJlYXNvbnMgYW5kIHRoZSBwYXR0ZXJucyBiZWhpbmQgYWxsIGNsb3VkcywgYW5kIHlvdSB3aWxsIGtub3csIHRvbywgd2hlbiB5b3UgbGlmdCB5b3Vyc2VsZiBoaWdoIGVub3VnaCB0byBzZWUgYmV5b25kIGhvcml6b25zLiINCg0KLVJpY2hhcmQgQmFjaA=="
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<server xmlns="http://docs.openstack.org/compute/api/v1.1" imageRef="http://openstack.example.com/openstack/images/70a599e0-31e7-49b7-b260-868f441e862b" flavorRef="http://openstack.example.com/openstack/flavors/1" name="new-server-test">
|
||||
<metadata>
|
||||
<meta key="My Server Name">Apache1</meta>
|
||||
</metadata>
|
||||
<personality>
|
||||
<file path="/etc/banner.txt">
|
||||
ICAgICAgDQoiQSBjbG91ZCBkb2VzIG5vdCBrbm93IHdoeSBp
|
||||
dCBtb3ZlcyBpbiBqdXN0IHN1Y2ggYSBkaXJlY3Rpb24gYW5k
|
||||
IGF0IHN1Y2ggYSBzcGVlZC4uLkl0IGZlZWxzIGFuIGltcHVs
|
||||
c2lvbi4uLnRoaXMgaXMgdGhlIHBsYWNlIHRvIGdvIG5vdy4g
|
||||
QnV0IHRoZSBza3kga25vd3MgdGhlIHJlYXNvbnMgYW5kIHRo
|
||||
ZSBwYXR0ZXJucyBiZWhpbmQgYWxsIGNsb3VkcywgYW5kIHlv
|
||||
dSB3aWxsIGtub3csIHRvbywgd2hlbiB5b3UgbGlmdCB5b3Vy
|
||||
c2VsZiBoaWdoIGVub3VnaCB0byBzZWUgYmV5b25kIGhvcml6
|
||||
b25zLiINCg0KLVJpY2hhcmQgQmFjaA==
|
||||
</file>
|
||||
</personality>
|
||||
</server>
|
@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<server xmlns="http://docs.openstack.org/compute/api/v1.1" imageRef="%(host)s/openstack/images/%(image_id)s" flavorRef="%(host)s/openstack/flavors/1" name="new-server-test">
|
||||
<metadata>
|
||||
<meta key="My Server Name">Apache1</meta>
|
||||
</metadata>
|
||||
<personality>
|
||||
<file path="/etc/banner.txt">
|
||||
ICAgICAgDQoiQSBjbG91ZCBkb2VzIG5vdCBrbm93IHdoeSBp
|
||||
dCBtb3ZlcyBpbiBqdXN0IHN1Y2ggYSBkaXJlY3Rpb24gYW5k
|
||||
IGF0IHN1Y2ggYSBzcGVlZC4uLkl0IGZlZWxzIGFuIGltcHVs
|
||||
c2lvbi4uLnRoaXMgaXMgdGhlIHBsYWNlIHRvIGdvIG5vdy4g
|
||||
QnV0IHRoZSBza3kga25vd3MgdGhlIHJlYXNvbnMgYW5kIHRo
|
||||
ZSBwYXR0ZXJucyBiZWhpbmQgYWxsIGNsb3VkcywgYW5kIHlv
|
||||
dSB3aWxsIGtub3csIHRvbywgd2hlbiB5b3UgbGlmdCB5b3Vy
|
||||
c2VsZiBoaWdoIGVub3VnaCB0byBzZWUgYmV5b25kIGhvcml6
|
||||
b25zLiINCg0KLVJpY2hhcmQgQmFjaA==
|
||||
</file>
|
||||
</personality>
|
||||
</server>
|
@ -0,0 +1,22 @@
|
||||
{
|
||||
"server": {
|
||||
"OS-DCF:diskConfig": "AUTO",
|
||||
"adminPass": "ahW3PjQNAu6r",
|
||||
"id": "e726f5ae-8179-44ba-bbfb-8a0c52b33095",
|
||||
"links": [
|
||||
{
|
||||
"href": "http://openstack.example.com/v2/openstack/servers/e726f5ae-8179-44ba-bbfb-8a0c52b33095",
|
||||
"rel": "self"
|
||||
},
|
||||
{
|
||||
"href": "http://openstack.example.com/openstack/servers/e726f5ae-8179-44ba-bbfb-8a0c52b33095",
|
||||
"rel": "bookmark"
|
||||
}
|
||||
],
|
||||
"security_groups": [
|
||||
{
|
||||
"name": "default"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
{
|
||||
"server": {
|
||||
"OS-DCF:diskConfig": "AUTO",
|
||||
"adminPass": "%(password)s",
|
||||
"id": "%(id)s",
|
||||
"links": [
|
||||
{
|
||||
"href": "%(host)s/v2/openstack/servers/%(uuid)s",
|
||||
"rel": "self"
|
||||
},
|
||||
{
|
||||
"href": "%(host)s/openstack/servers/%(uuid)s",
|
||||
"rel": "bookmark"
|
||||
}
|
||||
],
|
||||
"security_groups": [
|
||||
{
|
||||
"name": "default"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<server xmlns:OS-DCF="http://docs.openstack.org/compute/ext/disk_config/api/v1.1" xmlns:atom="http://www.w3.org/2005/Atom" xmlns="http://docs.openstack.org/compute/api/v1.1" id="7ed84cec-56e4-456c-987b-92684cd28f19" adminPass="gkRBLnnq4dqG" OS-DCF:diskConfig="AUTO">
|
||||
<metadata/>
|
||||
<atom:link href="http://openstack.example.com/v2/openstack/servers/7ed84cec-56e4-456c-987b-92684cd28f19" rel="self"/>
|
||||
<atom:link href="http://openstack.example.com/openstack/servers/7ed84cec-56e4-456c-987b-92684cd28f19" rel="bookmark"/>
|
||||
<security_groups>
|
||||
<security_group name="default"/>
|
||||
</security_groups>
|
||||
</server>
|
@ -0,0 +1,9 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<server xmlns:OS-DCF="http://docs.openstack.org/compute/ext/disk_config/api/v1.1" xmlns:atom="http://www.w3.org/2005/Atom" xmlns="http://docs.openstack.org/compute/api/v1.1" id="%(id)s" adminPass="%(password)s" OS-DCF:diskConfig="AUTO">
|
||||
<metadata/>
|
||||
<atom:link href="%(host)s/v2/openstack/servers/%(uuid)s" rel="self"/>
|
||||
<atom:link href="%(host)s/openstack/servers/%(uuid)s" rel="bookmark"/>
|
||||
<security_groups>
|
||||
<security_group name="default"/>
|
||||
</security_groups>
|
||||
</server>
|
54
nova/tests/integrated/api_samples/server-get-resp.json
Normal file
54
nova/tests/integrated/api_samples/server-get-resp.json
Normal file
@ -0,0 +1,54 @@
|
||||
{
|
||||
"server": {
|
||||
"accessIPv4": "",
|
||||
"accessIPv6": "",
|
||||
"addresses": {
|
||||
"private": [
|
||||
{
|
||||
"addr": "192.168.0.3",
|
||||
"version": 4
|
||||
}
|
||||
]
|
||||
},
|
||||
"created": "2012-08-20T21:11:09Z",
|
||||
"flavor": {
|
||||
"id": "1",
|
||||
"links": [
|
||||
{
|
||||
"href": "http://openstack.example.com/openstack/flavors/1",
|
||||
"rel": "bookmark"
|
||||
}
|
||||
]
|
||||
},
|
||||
"hostId": "65201c14a29663e06d0748e561207d998b343e1d164bfa0aafa9c45d",
|
||||
"id": "893c7791-f1df-4c3d-8383-3caae9656c62",
|
||||
"image": {
|
||||
"id": "70a599e0-31e7-49b7-b260-868f441e862b",
|
||||
"links": [
|
||||
{
|
||||
"href": "http://openstack.example.com/openstack/images/70a599e0-31e7-49b7-b260-868f441e862b",
|
||||
"rel": "bookmark"
|
||||
}
|
||||
]
|
||||
},
|
||||
"links": [
|
||||
{
|
||||
"href": "http://openstack.example.com/v2/openstack/servers/893c7791-f1df-4c3d-8383-3caae9656c62",
|
||||
"rel": "self"
|
||||
},
|
||||
{
|
||||
"href": "http://openstack.example.com/openstack/servers/893c7791-f1df-4c3d-8383-3caae9656c62",
|
||||
"rel": "bookmark"
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"My Server Name": "Apache1"
|
||||
},
|
||||
"name": "new-server-test",
|
||||
"progress": 0,
|
||||
"status": "ACTIVE",
|
||||
"tenant_id": "openstack",
|
||||
"updated": "2012-08-20T21:11:09Z",
|
||||
"user_id": "fake"
|
||||
}
|
||||
}
|
54
nova/tests/integrated/api_samples/server-get-resp.json.tpl
Normal file
54
nova/tests/integrated/api_samples/server-get-resp.json.tpl
Normal file
@ -0,0 +1,54 @@
|
||||
{
|
||||
"server": {
|
||||
"accessIPv4": "",
|
||||
"accessIPv6": "",
|
||||
"addresses": {
|
||||
"private": [
|
||||
{
|
||||
"addr": "%(ip)s",
|
||||
"version": 4
|
||||
}
|
||||
]
|
||||
},
|
||||
"created": "%(timestamp)s",
|
||||
"flavor": {
|
||||
"id": "1",
|
||||
"links": [
|
||||
{
|
||||
"href": "%(host)s/openstack/flavors/1",
|
||||
"rel": "bookmark"
|
||||
}
|
||||
]
|
||||
},
|
||||
"hostId": "%(hostid)s",
|
||||
"id": "%(uuid)s",
|
||||
"image": {
|
||||
"id": "%(uuid)s",
|
||||
"links": [
|
||||
{
|
||||
"href": "%(host)s/openstack/images/%(uuid)s",
|
||||
"rel": "bookmark"
|
||||
}
|
||||
]
|
||||
},
|
||||
"links": [
|
||||
{
|
||||
"href": "%(host)s/v2/openstack/servers/%(uuid)s",
|
||||
"rel": "self"
|
||||
},
|
||||
{
|
||||
"href": "%(host)s/openstack/servers/%(uuid)s",
|
||||
"rel": "bookmark"
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"My Server Name": "Apache1"
|
||||
},
|
||||
"name": "new-server-test",
|
||||
"progress": 0,
|
||||
"status": "ACTIVE",
|
||||
"tenant_id": "openstack",
|
||||
"updated": "%(timestamp)s",
|
||||
"user_id": "fake"
|
||||
}
|
||||
}
|
19
nova/tests/integrated/api_samples/server-get-resp.xml
Normal file
19
nova/tests/integrated/api_samples/server-get-resp.xml
Normal file
@ -0,0 +1,19 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<server xmlns:atom="http://www.w3.org/2005/Atom" xmlns="http://docs.openstack.org/compute/api/v1.1" status="ACTIVE" updated="2012-08-20T21:11:10Z" hostId="1746536de20daadad89a6fab8d6968b1214b0ba9fb37b29e7098e0b9" name="new-server-test" created="2012-08-20T21:11:10Z" userId="fake" tenantId="openstack" accessIPv4="" accessIPv6="" progress="0" id="3f9f7d18-aaf3-4703-b368-ea9b4d609c95">
|
||||
<image id="70a599e0-31e7-49b7-b260-868f441e862b">
|
||||
<atom:link href="http://openstack.example.com/openstack/images/70a599e0-31e7-49b7-b260-868f441e862b" rel="bookmark"/>
|
||||
</image>
|
||||
<flavor id="1">
|
||||
<atom:link href="http://openstack.example.com/openstack/flavors/1" rel="bookmark"/>
|
||||
</flavor>
|
||||
<metadata>
|
||||
<meta key="My Server Name">Apache1</meta>
|
||||
</metadata>
|
||||
<addresses>
|
||||
<network id="private">
|
||||
<ip version="4" addr="192.168.0.3"/>
|
||||
</network>
|
||||
</addresses>
|
||||
<atom:link href="http://openstack.example.com/v2/openstack/servers/3f9f7d18-aaf3-4703-b368-ea9b4d609c95" rel="self"/>
|
||||
<atom:link href="http://openstack.example.com/openstack/servers/3f9f7d18-aaf3-4703-b368-ea9b4d609c95" rel="bookmark"/>
|
||||
</server>
|
19
nova/tests/integrated/api_samples/server-get-resp.xml.tpl
Normal file
19
nova/tests/integrated/api_samples/server-get-resp.xml.tpl
Normal file
@ -0,0 +1,19 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<server xmlns:atom="http://www.w3.org/2005/Atom" xmlns="http://docs.openstack.org/compute/api/v1.1" status="ACTIVE" updated="%(timestamp)s" hostId="%(hostid)s" name="new-server-test" created="%(timestamp)s" userId="fake" tenantId="openstack" accessIPv4="" accessIPv6="" progress="0" id="%(id)s">
|
||||
<image id="%(uuid)s">
|
||||
<atom:link href="%(host)s/openstack/images/%(uuid)s" rel="bookmark"/>
|
||||
</image>
|
||||
<flavor id="1">
|
||||
<atom:link href="%(host)s/openstack/flavors/1" rel="bookmark"/>
|
||||
</flavor>
|
||||
<metadata>
|
||||
<meta key="My Server Name">Apache1</meta>
|
||||
</metadata>
|
||||
<addresses>
|
||||
<network id="private">
|
||||
<ip version="4" addr="%(ip)s"/>
|
||||
</network>
|
||||
</addresses>
|
||||
<atom:link href="%(host)s/v2/openstack/servers/%(uuid)s" rel="self"/>
|
||||
<atom:link href="%(host)s/openstack/servers/%(uuid)s" rel="bookmark"/>
|
||||
</server>
|
16
nova/tests/integrated/api_samples/server-post-req.json
Normal file
16
nova/tests/integrated/api_samples/server-post-req.json
Normal file
@ -0,0 +1,16 @@
|
||||
{
|
||||
"server": {
|
||||
"flavorRef": "http://openstack.example.com/openstack/flavors/1",
|
||||
"imageRef": "http://openstack.example.com/openstack/images/70a599e0-31e7-49b7-b260-868f441e862b",
|
||||
"metadata": {
|
||||
"My Server Name": "Apache1"
|
||||
},
|
||||
"name": "new-server-test",
|
||||
"personality": [
|
||||
{
|
||||
"contents": "ICAgICAgDQoiQSBjbG91ZCBkb2VzIG5vdCBrbm93IHdoeSBpdCBtb3ZlcyBpbiBqdXN0IHN1Y2ggYSBkaXJlY3Rpb24gYW5kIGF0IHN1Y2ggYSBzcGVlZC4uLkl0IGZlZWxzIGFuIGltcHVsc2lvbi4uLnRoaXMgaXMgdGhlIHBsYWNlIHRvIGdvIG5vdy4gQnV0IHRoZSBza3kga25vd3MgdGhlIHJlYXNvbnMgYW5kIHRoZSBwYXR0ZXJucyBiZWhpbmQgYWxsIGNsb3VkcywgYW5kIHlvdSB3aWxsIGtub3csIHRvbywgd2hlbiB5b3UgbGlmdCB5b3Vyc2VsZiBoaWdoIGVub3VnaCB0byBzZWUgYmV5b25kIGhvcml6b25zLiINCg0KLVJpY2hhcmQgQmFjaA==",
|
||||
"path": "/etc/banner.txt"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
16
nova/tests/integrated/api_samples/server-post-req.json.tpl
Normal file
16
nova/tests/integrated/api_samples/server-post-req.json.tpl
Normal file
@ -0,0 +1,16 @@
|
||||
{
|
||||
"server" : {
|
||||
"name" : "new-server-test",
|
||||
"imageRef" : "%(host)s/openstack/images/%(image_id)s",
|
||||
"flavorRef" : "%(host)s/openstack/flavors/1",
|
||||
"metadata" : {
|
||||
"My Server Name" : "Apache1"
|
||||
},
|
||||
"personality" : [
|
||||
{
|
||||
"path" : "/etc/banner.txt",
|
||||
"contents" : "ICAgICAgDQoiQSBjbG91ZCBkb2VzIG5vdCBrbm93IHdoeSBpdCBtb3ZlcyBpbiBqdXN0IHN1Y2ggYSBkaXJlY3Rpb24gYW5kIGF0IHN1Y2ggYSBzcGVlZC4uLkl0IGZlZWxzIGFuIGltcHVsc2lvbi4uLnRoaXMgaXMgdGhlIHBsYWNlIHRvIGdvIG5vdy4gQnV0IHRoZSBza3kga25vd3MgdGhlIHJlYXNvbnMgYW5kIHRoZSBwYXR0ZXJucyBiZWhpbmQgYWxsIGNsb3VkcywgYW5kIHlvdSB3aWxsIGtub3csIHRvbywgd2hlbiB5b3UgbGlmdCB5b3Vyc2VsZiBoaWdoIGVub3VnaCB0byBzZWUgYmV5b25kIGhvcml6b25zLiINCg0KLVJpY2hhcmQgQmFjaA=="
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
19
nova/tests/integrated/api_samples/server-post-req.xml
Normal file
19
nova/tests/integrated/api_samples/server-post-req.xml
Normal file
@ -0,0 +1,19 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<server xmlns="http://docs.openstack.org/compute/api/v1.1" imageRef="http://openstack.example.com/openstack/images/70a599e0-31e7-49b7-b260-868f441e862b" flavorRef="http://openstack.example.com/openstack/flavors/1" name="new-server-test">
|
||||
<metadata>
|
||||
<meta key="My Server Name">Apache1</meta>
|
||||
</metadata>
|
||||
<personality>
|
||||
<file path="/etc/banner.txt">
|
||||
ICAgICAgDQoiQSBjbG91ZCBkb2VzIG5vdCBrbm93IHdoeSBp
|
||||
dCBtb3ZlcyBpbiBqdXN0IHN1Y2ggYSBkaXJlY3Rpb24gYW5k
|
||||
IGF0IHN1Y2ggYSBzcGVlZC4uLkl0IGZlZWxzIGFuIGltcHVs
|
||||
c2lvbi4uLnRoaXMgaXMgdGhlIHBsYWNlIHRvIGdvIG5vdy4g
|
||||
QnV0IHRoZSBza3kga25vd3MgdGhlIHJlYXNvbnMgYW5kIHRo
|
||||
ZSBwYXR0ZXJucyBiZWhpbmQgYWxsIGNsb3VkcywgYW5kIHlv
|
||||
dSB3aWxsIGtub3csIHRvbywgd2hlbiB5b3UgbGlmdCB5b3Vy
|
||||
c2VsZiBoaWdoIGVub3VnaCB0byBzZWUgYmV5b25kIGhvcml6
|
||||
b25zLiINCg0KLVJpY2hhcmQgQmFjaA==
|
||||
</file>
|
||||
</personality>
|
||||
</server>
|
19
nova/tests/integrated/api_samples/server-post-req.xml.tpl
Normal file
19
nova/tests/integrated/api_samples/server-post-req.xml.tpl
Normal file
@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<server xmlns="http://docs.openstack.org/compute/api/v1.1" imageRef="%(host)s/openstack/images/%(image_id)s" flavorRef="%(host)s/openstack/flavors/1" name="new-server-test">
|
||||
<metadata>
|
||||
<meta key="My Server Name">Apache1</meta>
|
||||
</metadata>
|
||||
<personality>
|
||||
<file path="/etc/banner.txt">
|
||||
ICAgICAgDQoiQSBjbG91ZCBkb2VzIG5vdCBrbm93IHdoeSBp
|
||||
dCBtb3ZlcyBpbiBqdXN0IHN1Y2ggYSBkaXJlY3Rpb24gYW5k
|
||||
IGF0IHN1Y2ggYSBzcGVlZC4uLkl0IGZlZWxzIGFuIGltcHVs
|
||||
c2lvbi4uLnRoaXMgaXMgdGhlIHBsYWNlIHRvIGdvIG5vdy4g
|
||||
QnV0IHRoZSBza3kga25vd3MgdGhlIHJlYXNvbnMgYW5kIHRo
|
||||
ZSBwYXR0ZXJucyBiZWhpbmQgYWxsIGNsb3VkcywgYW5kIHlv
|
||||
dSB3aWxsIGtub3csIHRvbywgd2hlbiB5b3UgbGlmdCB5b3Vy
|
||||
c2VsZiBoaWdoIGVub3VnaCB0byBzZWUgYmV5b25kIGhvcml6
|
||||
b25zLiINCg0KLVJpY2hhcmQgQmFjaA==
|
||||
</file>
|
||||
</personality>
|
||||
</server>
|
16
nova/tests/integrated/api_samples/server-post-resp.json
Normal file
16
nova/tests/integrated/api_samples/server-post-resp.json
Normal file
@ -0,0 +1,16 @@
|
||||
{
|
||||
"server": {
|
||||
"adminPass": "MVk5HPrazHcG",
|
||||
"id": "5bbcc3c4-1da2-4437-a48a-66f15b1b13f9",
|
||||
"links": [
|
||||
{
|
||||
"href": "http://openstack.example.com/v2/openstack/servers/5bbcc3c4-1da2-4437-a48a-66f15b1b13f9",
|
||||
"rel": "self"
|
||||
},
|
||||
{
|
||||
"href": "http://openstack.example.com/openstack/servers/5bbcc3c4-1da2-4437-a48a-66f15b1b13f9",
|
||||
"rel": "bookmark"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
16
nova/tests/integrated/api_samples/server-post-resp.json.tpl
Normal file
16
nova/tests/integrated/api_samples/server-post-resp.json.tpl
Normal file
@ -0,0 +1,16 @@
|
||||
{
|
||||
"server": {
|
||||
"adminPass": "%(password)s",
|
||||
"id": "%(id)s",
|
||||
"links": [
|
||||
{
|
||||
"href": "%(host)s/v2/openstack/servers/%(uuid)s",
|
||||
"rel": "self"
|
||||
},
|
||||
{
|
||||
"href": "%(host)s/openstack/servers/%(uuid)s",
|
||||
"rel": "bookmark"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
6
nova/tests/integrated/api_samples/server-post-resp.xml
Normal file
6
nova/tests/integrated/api_samples/server-post-resp.xml
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<server xmlns:atom="http://www.w3.org/2005/Atom" xmlns="http://docs.openstack.org/compute/api/v1.1" id="ea8417a1-7957-4ed5-8b3c-0befc1724308" adminPass="FoFw84XtQj3c">
|
||||
<metadata/>
|
||||
<atom:link href="http://openstack.example.com/v2/openstack/servers/ea8417a1-7957-4ed5-8b3c-0befc1724308" rel="self"/>
|
||||
<atom:link href="http://openstack.example.com/openstack/servers/ea8417a1-7957-4ed5-8b3c-0befc1724308" rel="bookmark"/>
|
||||
</server>
|
@ -0,0 +1,6 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<server xmlns:atom="http://www.w3.org/2005/Atom" xmlns="http://docs.openstack.org/compute/api/v1.1" id="%(id)s" adminPass="%(password)s">
|
||||
<metadata/>
|
||||
<atom:link href="%(host)s/v2/openstack/servers/%(uuid)s" rel="self"/>
|
||||
<atom:link href="%(host)s/openstack/servers/%(uuid)s" rel="bookmark"/>
|
||||
</server>
|
174
nova/tests/integrated/test_api_samples.py
Normal file
174
nova/tests/integrated/test_api_samples.py
Normal file
@ -0,0 +1,174 @@
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
# Copyright 2012 Nebula, 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 os
|
||||
import re
|
||||
|
||||
from lxml import etree
|
||||
|
||||
from nova import flags
|
||||
from nova.openstack.common import jsonutils
|
||||
from nova.openstack.common.log import logging
|
||||
from nova.tests import fake_network
|
||||
from nova.tests.image import fake
|
||||
from nova.tests.integrated import integrated_helpers
|
||||
|
||||
FLAGS = flags.FLAGS
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class ApiSampleTestBase(integrated_helpers._IntegratedTestBase):
|
||||
ctype = 'json'
|
||||
all_extensions = False
|
||||
extension_name = None
|
||||
|
||||
def setUp(self):
|
||||
self.flags(use_ipv6=False,
|
||||
osapi_compute_link_prefix=self._get_host())
|
||||
if not self.all_extensions:
|
||||
ext = [self.extension_name] if self.extension_name else []
|
||||
self.flags(osapi_compute_extension=ext)
|
||||
super(ApiSampleTestBase, self).setUp()
|
||||
fake_network.stub_compute_with_ips(self.stubs)
|
||||
self.generate_samples = os.getenv('GENERATE_SAMPLES') is not None
|
||||
|
||||
def _pretty_data(self, data):
|
||||
if self.ctype == 'json':
|
||||
data = jsonutils.dumps(jsonutils.loads(data), sort_keys=True,
|
||||
indent=4)
|
||||
|
||||
else:
|
||||
data = etree.tostring(etree.XML(data), encoding="UTF-8",
|
||||
xml_declaration=True, pretty_print=True)
|
||||
return '\n'.join(line.rstrip() for line in data.split('\n'))
|
||||
|
||||
@classmethod
|
||||
def _get_sample(cls, name, suffix=''):
|
||||
parts = [os.path.dirname(os.path.abspath(__file__))]
|
||||
parts.append('api_samples')
|
||||
if cls.all_extensions:
|
||||
parts.append('all_extensions')
|
||||
if cls.extension_name:
|
||||
parts.append(cls.extension_name)
|
||||
parts.append(name + "." + cls.ctype + suffix)
|
||||
return os.path.join(*parts)
|
||||
|
||||
@classmethod
|
||||
def _get_template(cls, name):
|
||||
return cls._get_sample(name, suffix='.tpl')
|
||||
|
||||
def _read_template(self, name):
|
||||
with open(self._get_template(name)) as inf:
|
||||
return inf.read().strip()
|
||||
|
||||
def _write_sample(self, name, data):
|
||||
with open(self._get_sample(name), 'w') as outf:
|
||||
outf.write(data)
|
||||
|
||||
def _verify_response(self, name, subs, response):
|
||||
expected = self._read_template(name)
|
||||
|
||||
# NOTE(vish): escape stuff for regex
|
||||
for char in ['[', ']', '<', '>', '?']:
|
||||
expected = expected.replace(char, '\%s' % char)
|
||||
|
||||
expected = expected % subs
|
||||
data = response.read()
|
||||
result = self._pretty_data(data).strip()
|
||||
if self.generate_samples:
|
||||
self._write_sample(name, result)
|
||||
result_lines = result.split('\n')
|
||||
expected_lines = expected.split('\n')
|
||||
if len(result_lines) != len(expected_lines):
|
||||
LOG.info(expected)
|
||||
LOG.info(result)
|
||||
self.fail('Number of lines (%s) incorrect' % (len(expected_lines)))
|
||||
result = None
|
||||
for line, result_line in zip(expected_lines, result_lines):
|
||||
try:
|
||||
match = re.match(line, result_line)
|
||||
except Exception as exc:
|
||||
self.fail(_('Response error on line %(i)s:\n'
|
||||
'%(line)s\n%(result_line)s') % locals())
|
||||
if not match:
|
||||
self.fail(_('Response error on line %(i)s:\n'
|
||||
'%(line)s\n%(result_line)s') % locals())
|
||||
if match.groups():
|
||||
result = match.groups()[0]
|
||||
return result
|
||||
|
||||
def _get_host(self):
|
||||
return 'http://openstack.example.com'
|
||||
|
||||
def _get_regexes(self):
|
||||
return {
|
||||
'timestamp': '[0-9]{4}-[0,1][0-9]-[0-3][0-9]T'
|
||||
'[0-9]{2}:[0-9]{2}:[0-9]{2}Z',
|
||||
'password': '[0-9a-zA-Z]{12}',
|
||||
'ip': '[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}',
|
||||
'id': '([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}'
|
||||
'-[0-9a-f]{4}-[0-9a-f]{12})',
|
||||
'uuid': '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}'
|
||||
'-[0-9a-f]{4}-[0-9a-f]{12}',
|
||||
'host': self._get_host(),
|
||||
'compute_host': self.compute.host,
|
||||
}
|
||||
|
||||
def _get_response(self, url, method, body=None):
|
||||
headers = {}
|
||||
headers['Content-Type'] = 'application/' + self.ctype
|
||||
headers['Accept'] = 'application/' + self.ctype
|
||||
return self.api.api_request(url, body=body, method=method,
|
||||
headers=headers)
|
||||
|
||||
def _do_get(self, url):
|
||||
return self._get_response(url, 'GET')
|
||||
|
||||
def _do_post(self, url, name, subs):
|
||||
body = self._read_template(name) % subs
|
||||
if self.generate_samples:
|
||||
self._write_sample(name, self._pretty_data(body))
|
||||
return self._get_response(url, 'POST', body)
|
||||
|
||||
|
||||
class ServersSampleJsonTest(ApiSampleTestBase):
|
||||
def test_servers_post(self):
|
||||
subs = {
|
||||
'image_id': fake.get_valid_image_id(),
|
||||
'host': self._get_host(),
|
||||
}
|
||||
response = self._do_post('servers', 'server-post-req', subs)
|
||||
self.assertEqual(response.status, 202)
|
||||
subs = self._get_regexes()
|
||||
return self._verify_response('server-post-resp', subs, response)
|
||||
|
||||
def test_servers_get(self):
|
||||
uuid = self.test_servers_post()
|
||||
response = self._do_get('servers/%s' % uuid)
|
||||
subs = self._get_regexes()
|
||||
subs['hostid'] = '[a-f0-9]+'
|
||||
return self._verify_response('server-get-resp', subs, response)
|
||||
|
||||
|
||||
class ServersSampleXmlTest(ServersSampleJsonTest):
|
||||
ctype = 'xml'
|
||||
|
||||
|
||||
class ServersSampleAllExtensionJsonTest(ServersSampleJsonTest):
|
||||
all_extensions = True
|
||||
|
||||
|
||||
class ServersSampleAllExtensionXmlTest(ServersSampleXmlTest):
|
||||
all_extensions = True
|
Loading…
Reference in New Issue
Block a user