Merge "Removed non-testing suggestions"
diff --git a/etc/config.ini.sample b/etc/config.ini.sample
index c27bb04..97ca732 100644
--- a/etc/config.ini.sample
+++ b/etc/config.ini.sample
@@ -1,7 +1,7 @@
[environment]
-kernel = include/sample_vm/natty-server-uec-amd64-vmlinuz-virtual
-#initrd = include/sample_vm/natty-server-uec-amd64-initrd-virtual
-image = include/sample_vm/natty-server-uec-amd64.img
+aki_location = include/sample_vm/natty-server-cloudimg-amd64-vmlinuz-virtual
+#ari_location = include/sample_vm/natty-server-cloudimg-amd64-loader
+ami_location = include/sample_vm/natty-server-cloudimg-amd64.img
[swift]
auth_host = 10.0.0.100
@@ -36,8 +36,9 @@
flavor_ref_alt = 2
[keystone]
-host = 10.0.0.100
-port = 5000
+service_host = 10.0.0.100
+service_port = 5000
apiver = v1.1
user = admin
password = password
+tenant_id = 1
diff --git a/include/sample_vm/README.txt b/include/sample_vm/README.txt
index e8895ea..51b609d 100644
--- a/include/sample_vm/README.txt
+++ b/include/sample_vm/README.txt
@@ -2,5 +2,5 @@
Will also need to update the tests to reference this new image.
You could use e.g. the Ubuntu Natty cloud images (this matches the sample configuration):
-$ wget http://cloud-images.ubuntu.com/releases/natty/release/ubuntu-11.04-server-uec-amd64.tar.gz
-$ tar xvzf ubuntu-11.04-server-uec-amd64.tar.gz
+$ wget http://cloud-images.ubuntu.com/releases/natty/release/ubuntu-11.04-server-cloudimg-amd64.tar.gz
+$ tar xvzf ubuntu-11.04-server-cloudimg-amd64.tar.gz
diff --git a/kong/keystone.py b/kong/keystone.py
new file mode 100644
index 0000000..cfd9e82
--- /dev/null
+++ b/kong/keystone.py
@@ -0,0 +1,34 @@
+import json
+
+import kong.common.http
+from kong import exceptions
+
+
+class API(kong.common.http.Client):
+ """Barebones Keystone HTTP API client."""
+
+ def __init__(self, service_host, service_port):
+ super(API, self).__init__(service_host, service_port, 'v2.0')
+
+ #TODO(bcwaldon): This is a hack, we should clean up the superclass
+ self.management_url = self.base_url
+
+ def get_token(self, user, password, tenant_id):
+ headers = {'content-type': 'application/json'}
+
+ body = {
+ "auth": {
+ "passwordCredentials":{
+ "username": user,
+ "password": password,
+ },
+ "tenantId": tenant_id,
+ },
+ }
+
+ response, content = self.request('POST', '/tokens',
+ headers=headers,
+ body=json.dumps(body))
+
+ res_body = json.loads(content)
+ return res_body['access']['token']['id']
diff --git a/kong/tests/996_test_glance.py b/kong/tests/996_test_glance.py
deleted file mode 100644
index 01cb110..0000000
--- a/kong/tests/996_test_glance.py
+++ /dev/null
@@ -1,206 +0,0 @@
-# vim: tabstop=4 shiftwidth=4 softtabstop=4
-
-# Copyright 2011 OpenStack, LLC
-# 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.
-"""Validate a working Glance deployment"""
-
-import httplib2
-import json
-import os
-from pprint import pprint
-
-from kong import tests
-
-
-class TestGlanceAPI(tests.FunctionalTest):
- def test_001_connect_to_glance_api(self):
- """
- Verifies ability to connect to glance api,
- expects glance to return an empty set
- """
- if 'apiver' in self.glance:
- path = "http://%s:%s/%s/images" % (self.glance['host'],
- self.glance['port'], self.glance['apiver'])
- else:
- path = "http://%s:%s/images" % (self.glance['host'],
- self.glance['port'])
- http = httplib2.Http()
- response, content = http.request(path, 'GET')
- self.assertEqual(200, response.status)
- data = json.loads(content)
- self.assertTrue('images' in data)
- test_001_connect_to_glance_api.tags = ['glance']
-
- def test_002_upload_kernel_to_glance(self):
- """
- Uploads a test kernal to glance api
- """
- kernel = self.config['environment']['kernel']
- if 'apiver' in self.glance:
- path = "http://%s:%s/%s/images" % (self.glance['host'],
- self.glance['port'], self.glance['apiver'])
- else:
- path = "http://%s:%s/images" % (self.glance['host'],
- self.glance['port'])
- headers = {'x-image-meta-is-public': 'true',
- 'x-image-meta-name': 'test-kernel',
- 'x-image-meta-disk-format': 'aki',
- 'x-image-meta-container-format': 'aki',
- 'Content-Length': '%d' % os.path.getsize(kernel),
- 'Content-Type': 'application/octet-stream'}
- image_file = open(kernel, "rb")
- http = httplib2.Http()
- response, content = http.request(path, 'POST',
- headers=headers,
- body=image_file)
- image_file.close()
- self.assertEqual(201, response.status)
- data = json.loads(content)
- self.glance['kernel_id'] = data['image']['id']
- self.assertEqual(data['image']['name'], "test-kernel")
- self.assertEqual(data['image']['checksum'], self._md5sum_file(kernel))
- test_002_upload_kernel_to_glance.tags = ['glance', 'nova']
-
- def test_003_upload_initrd_to_glance(self):
- """
- Uploads a test initrd to glance api
- """
- if not 'initrd' in self.config['environment']:
- self.glance['ramdisk_id'] = None
- return
-
- initrd = self.config['environment']['initrd']
-
- if 'apiver' in self.glance:
- path = "http://%s:%s/%s/images" % (self.glance['host'],
- self.glance['port'], self.glance['apiver'])
- else:
- path = "http://%s:%s/images" % (self.glance['host'],
- self.glance['port'])
- headers = {'x-image-meta-is-public': 'true',
- 'x-image-meta-name': 'test-ramdisk',
- 'x-image-meta-disk-format': 'ari',
- 'x-image-meta-container-format': 'ari',
- 'Content-Length': '%d' % os.path.getsize(initrd),
- 'Content-Type': 'application/octet-stream'}
- image_file = open(initrd, "rb")
- http = httplib2.Http()
- response, content = http.request(path,
- 'POST',
- headers=headers,
- body=image_file)
- image_file.close()
- self.assertEqual(201, response.status)
- data = json.loads(content)
- self.glance['ramdisk_id'] = data['image']['id']
- self.assertEqual(data['image']['name'], "test-ramdisk")
- self.assertEqual(data['image']['checksum'], self._md5sum_file(initrd))
- test_003_upload_initrd_to_glance.tags = ['glance', 'nova']
-
- def test_004_upload_image_to_glance(self):
- """
- Uploads a test image to glance api, and
- links it to the initrd and kernel uploaded
- earlier
- """
- image = self.config['environment']['image']
- upload_data = ""
- for chunk in self._read_in_chunks(image):
- upload_data += chunk
- if 'apiver' in self.glance:
- path = "http://%s:%s/%s/images" % (self.glance['host'],
- self.glance['port'], self.glance['apiver'])
- else:
- path = "http://%s:%s/images" % (self.glance['host'],
- self.glance['port'])
- headers = {'x-image-meta-is-public': 'true',
- 'x-image-meta-name': 'test-image',
- 'x-image-meta-disk-format': 'ami',
- 'x-image-meta-container-format': 'ami',
- 'x-image-meta-property-Kernel_id': '%s' % \
- self.glance['kernel_id'],
- 'Content-Length': '%d' % os.path.getsize(image),
- 'Content-Type': 'application/octet-stream'}
-
- if self.glance['ramdisk_id']:
- ramdisk_id = '%s' % self.glance['ramdisk_id']
- headers['x-image-meta-property-Ramdisk_id'] = ramdisk_id
-
- http = httplib2.Http()
- response, content = http.request(path, 'POST',
- headers=headers,
- body=upload_data)
- self.assertEqual(201, response.status)
- data = json.loads(content)
- self.glance['image_id'] = data['image']['id']
- self.assertEqual(data['image']['name'], "test-image")
- self.assertEqual(data['image']['checksum'], self._md5sum_file(image))
- test_004_upload_image_to_glance.tags = ['glance', 'nova']
-
- def test_005_set_image_meta_property(self):
- if 'apiver' in self.glance:
- path = "http://%s:%s/%s/images/%s" % (self.glance['host'],
- self.glance['port'], self.glance['apiver'],
- self.glance['image_id'])
- else:
- path = "http://%s:%s/images/%s" % (self.glance['host'],
- self.glance['port'], self.glance['image_id'])
- headers = {'X-Image-Meta-Property-Distro': 'Ubuntu',
- 'X-Image-Meta-Property-Arch': 'x86_64',
- 'X-Image-Meta-Property-Kernel_id': '%s' % \
- self.glance['kernel_id']}
-
- if self.glance['ramdisk_id']:
- ramdisk_id = '%s' % self.glance['ramdisk_id']
- headers['X-Image-Meta-Property-Ramdisk_id'] = ramdisk_id
-
- http = httplib2.Http()
- response, content = http.request(path, 'PUT', headers=headers)
- self.assertEqual(response.status, 200)
- data = json.loads(content)
- self.assertEqual(data['image']['properties']['arch'], "x86_64")
- self.assertEqual(data['image']['properties']['distro'], "Ubuntu")
- self.assertEqual(data['image']['properties']['kernel_id'],
- str(self.glance['kernel_id']))
- if self.glance['ramdisk_id']:
- self.assertEqual(data['image']['properties']['ramdisk_id'],
- str(self.glance['ramdisk_id']))
- test_005_set_image_meta_property.tags = ['glance']
-
- def test_006_list_image_metadata(self):
- image = self.config['environment']['image']
- if 'apiver' in self.glance:
- path = "http://%s:%s/%s/images/%s" % (self.glance['host'],
- self.glance['port'], self.glance['apiver'],
- self.glance['image_id'])
- else:
- path = "http://%s:%s/images/%s" % (self.glance['host'],
- self.glance['port'], self.glance['image_id'])
- http = httplib2.Http()
- response, content = http.request(path, 'HEAD')
- self.assertEqual(response.status, 200)
- self.assertEqual(response['x-image-meta-name'], "test-image")
- self.assertEqual(response['x-image-meta-checksum'],
- self._md5sum_file(image))
- self.assertEqual(response['x-image-meta-container_format'], "ami")
- self.assertEqual(response['x-image-meta-disk_format'], "ami")
- self.assertEqual(response['x-image-meta-property-arch'], "x86_64")
- self.assertEqual(response['x-image-meta-property-distro'], "Ubuntu")
- self.assertEqual(response['x-image-meta-property-kernel_id'],
- str(self.glance['kernel_id']))
- if self.glance['ramdisk_id']:
- self.assertEqual(response['x-image-meta-property-ramdisk_id'],
- str(self.glance['ramdisk_id']))
- test_006_list_image_metadata.tags = ['glance']
diff --git a/kong/tests/998_test_nova.py b/kong/tests/998_test_nova.py
deleted file mode 100644
index f82a45c..0000000
--- a/kong/tests/998_test_nova.py
+++ /dev/null
@@ -1,394 +0,0 @@
-# vim: tabstop=4 shiftwidth=4 softtabstop=4
-
-# Copyright 2011 OpenStack, LLC
-# 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.
-
-"""Functional test case against the OpenStack Nova API server"""
-
-import json
-import os
-import httplib2
-import time
-
-from pprint import pprint
-
-from kong import tests
-
-
-class TestNovaAPI(tests.FunctionalTest):
- def build_check(self, id):
- self.result = {}
- """
- This is intended to check that a server completes the build process
- and enters an active state upon creation. Due to reporting errors in
- the API we are also testing ping and ssh
- """
- count = 0
- path = "http://%s:%s/%s/servers/%s" % (self.nova['host'],
- self.nova['port'],
- self.nova['ver'],
- id)
- http = httplib2.Http()
- headers = {'X-Auth-User': '%s' % (self.nova['user']),
- 'X-Auth-Token': '%s' % (self.nova['X-Auth-Token'])}
- response, content = http.request(path, 'GET', headers=headers)
- self.assertEqual(response.status, 200)
- data = json.loads(content)
-
- # Get Server status exit when active
- while (data['server']['status'] != 'ACTIVE'):
- response, content = http.request(path, 'GET', headers=headers)
- data = json.loads(content)
- time.sleep(5)
- count = count + 5
- self.result['serverid'] = id
- self.result['status'] = data['server']['status']
-
- # Get IP Address of newly created server
- addr_name = "private"
- if 'vmnet' in data['server']['addresses']:
- ref = data['server']['addresses']['vmnet']
- if len(ref) > 0:
- addr_name = 'vmnet'
- if 'public' in data['server']['addresses']:
- ref = data['server']['addresses']['public']
- if len(ref) > 0:
- addr_name = 'public'
- ref = data['server']['addresses'][addr_name]
- netaddr = ref[0]['addr']
-
- r = "" . join(os.popen('ping -c5 %s' % (netaddr)).readlines())
- if r.find('64 bytes') > 1:
- self.result['ping'] = True
- else:
- self.result['ping'] = False
-
- return self.result
-
- def test_002_verify_nova_auth(self):
- if 'keystone' in self.config:
- path = "http://%s:%s/%s" % (self.keystone['host'],
- self.keystone['port'],
- self.keystone['apiver'])
- headers = {'X-Auth-User': self.keystone['user'],
- 'X-Auth-Key': self.keystone['pass']}
- else:
- path = "http://%s:%s/%s" % (self.nova['host'],
- self.nova['port'],
- self.nova['ver'])
- headers = {'X-Auth-User': self.nova['user'],
- 'X-Auth-Key': self.nova['key']}
-
- http = httplib2.Http()
- response, content = http.request(path, 'HEAD', headers=headers)
- self.assertEqual(response.status, 204)
- self.assertNotEqual(response['x-auth-token'], '')
- self.assertNotEqual(response['x-server-management-url'], '')
-
- # Set up Auth Token for all future API interactions
- self.nova['X-Auth-Token'] = response['x-auth-token']
- test_002_verify_nova_auth.tags = ['nova', 'nova-api']
-
- def test_101_verify_version_selection_default(self):
- path = "http://%s:%s/" % (self.nova['host'],
- self.nova['port'])
- http = httplib2.Http()
- headers = {'X-Auth-Token': self.nova['X-Auth-Token']}
- response, content = http.request(path, 'GET', headers=headers)
- self.assertEqual(response.status, 200)
- data = json.loads(content)
- self.assertEqual(len(data['versions']), 2)
- test_101_verify_version_selection_default.tags = ['nova', 'nova-api']
-
- def test_102_verify_version_selection_json(self):
- path = "http://%s:%s/.json" % (self.nova['host'],
- self.nova['port'])
- http = httplib2.Http()
- headers = {'X-Auth-Token': self.nova['X-Auth-Token']}
- response, content = http.request(path, 'GET', headers=headers)
- self.assertEqual(response.status, 200)
- data = json.loads(content)
- self.assertEqual(len(data['versions']), 2)
- test_102_verify_version_selection_json.tags = ['nova', 'nova-api']
-
- def test_103_verify_version_selection_xml(self):
- path = "http://%s:%s/.xml" % (self.nova['host'],
- self.nova['port'])
- http = httplib2.Http()
- headers = {'X-Auth-Token': self.nova['X-Auth-Token']}
- response, content = http.request(path, 'GET', headers=headers)
- self.assertEqual(response.status, 200)
- self.assertTrue('<versions>' in content)
- test_103_verify_version_selection_xml.tags = ['nova', 'nova-api']
-
- def test_104_bad_user_bad_key(self):
- if 'keystone' in self.config:
- path = "http://%s:%s/%s" % (self.keystone['host'],
- self.keystone['port'],
- self.keystone['apiver'])
- else:
- path = "http://%s:%s/%s" % (self.nova['host'],
- self.nova['port'],
- self.nova['ver'])
- http = httplib2.Http()
- headers = {'X-Auth-User': 'unknown_auth_user',
- 'X-Auth-Key': 'unknown_auth_key'}
- response, content = http.request(path, 'GET', headers=headers)
- self.assertEqual(response.status, 401)
- test_104_bad_user_bad_key.tags = ['nova', 'nova-api']
-
- def test_105_bad_user_good_key(self):
- if 'keystone' in self.config:
- path = "http://%s:%s/%s" % (self.keystone['host'],
- self.keystone['port'],
- self.keystone['apiver'])
- else:
- path = "http://%s:%s/%s" % (self.nova['host'],
- self.nova['port'],
- self.nova['ver'])
- http = httplib2.Http()
- headers = {'X-Auth-User': 'unknown_auth_user',
- 'X-Auth-Key': self.nova['key']}
- response, content = http.request(path, 'GET', headers=headers)
- self.assertEqual(response.status, 401)
- test_105_bad_user_good_key.tags = ['nova', 'nova-api']
-
- def test_106_good_user_bad_key(self):
- if 'keystone' in self.config:
- path = "http://%s:%s/%s" % (self.keystone['host'],
- self.keystone['port'],
- self.keystone['apiver'])
- else:
- path = "http://%s:%s/%s" % (self.nova['host'],
- self.nova['port'],
- self.nova['ver'])
- http = httplib2.Http()
- headers = {'X-Auth-User': self.nova['user'],
- 'X-Auth-Key': 'unknown_auth_key'}
- response, content = http.request(path, 'GET', headers=headers)
- self.assertEqual(response.status, 401)
- test_106_good_user_bad_key.tags = ['nova', 'nova-api']
-
- def test_107_no_key(self):
- if 'keystone' in self.config:
- path = "http://%s:%s/%s" % (self.keystone['host'],
- self.keystone['port'],
- self.keystone['apiver'])
- else:
- path = "http://%s:%s/%s" % (self.nova['host'],
- self.nova['port'],
- self.nova['ver'])
- http = httplib2.Http()
- headers = {'X-Auth-User': self.nova['user']}
- response, content = http.request(path, 'GET', headers=headers)
- self.assertEqual(response.status, 401)
- test_107_no_key.tags = ['nova', 'nova-api']
-
- def test_108_bad_token(self):
- if 'keystone' in self.config:
- path = "http://%s:%s/%s" % (self.keystone['host'],
- self.keystone['port'],
- self.keystone['apiver'])
- else:
- path = "http://%s:%s/%s" % (self.nova['host'],
- self.nova['port'],
- self.nova['ver'])
- http = httplib2.Http()
- headers = {'X-Auth-Token': 'unknown_token'}
- response, content = http.request(path, 'GET', headers=headers)
- self.assertEqual(response.status, 401)
- test_108_bad_token.tags = ['nova', 'nova-api']
-
- def test_109_verify_blank_limits(self):
- path = "http://%s:%s/%s/limits" % (self.nova['host'],
- self.nova['port'],
- self.nova['ver'])
-
- http = httplib2.Http()
- headers = {'X-Auth-User': '%s' % (self.nova['user']),
- 'X-Auth-Token': '%s' % (self.nova['X-Auth-Token'])}
- response, content = http.request(path, 'GET', headers=headers)
- self.assertEqual(response.status, 200)
- self.assertNotEqual(content, '{"limits": []}')
- test_109_verify_blank_limits.tags = ['nova', 'nova-api']
-
- def test_110_list_flavors_v1_1(self):
- path = "http://%s:%s/%s/flavors" % (self.nova['host'],
- self.nova['port'],
- self.nova['ver'])
- http = httplib2.Http()
- headers = {'X-Auth-User': '%s' % (self.nova['user']),
- 'X-Auth-Token': '%s' % (self.nova['X-Auth-Token'])}
- response, content = http.request(path, 'GET', headers=headers)
- self.assertEqual(response.status, 200)
- self.assertNotEqual(content, '{"flavors": []}')
- test_110_list_flavors_v1_1.tags = ['nova', 'nova-api']
-
- def test_111_verify_kernel_active_v1_1(self):
- # for testing purposes change self.glance['kernel_id'] to an active
- # kernel image allow for skipping glance tests
- if not 'kernel_id' in self.glance:
- self.glance['kernel_id'] = "61"
-
- path = "http://%s:%s/%s/images/%s" % (self.nova['host'],
- self.nova['port'],
- self.nova['ver'],
- self.glance['kernel_id'])
- http = httplib2.Http()
- headers = {'X-Auth-User': '%s' % (self.nova['user']),
- 'X-Auth-Token': '%s' % (self.nova['X-Auth-Token'])}
- response, content = http.request(path, 'GET', headers=headers)
- self.assertEqual(response.status, 200)
- data = json.loads(content)
- self.assertEqual(data['image']['status'], 'ACTIVE')
- test_111_verify_kernel_active_v1_1.tags = ['nova']
-
- def test_112_verify_ramdisk_active_v1_1(self):
- # for testing purposes change self.glance['ramdisk_id'] to an active
- # ramdisk image, allows you to skip glance tests
- if not 'ramdisk_id' in self.glance:
- self.glance['ramdisk_id'] = "62"
-
- path = "http://%s:%s/%s/images/%s" % (self.nova['host'],
- self.nova['port'],
- self.nova['ver'],
- self.glance['ramdisk_id'])
- http = httplib2.Http()
- headers = {'X-Auth-User': '%s' % (self.nova['user']),
- 'X-Auth-Token': '%s' % (self.nova['X-Auth-Token'])}
- response, content = http.request(path, 'GET', headers=headers)
- self.assertEqual(response.status, 200)
- data = json.loads(content)
- self.assertEqual(data['image']['status'], 'ACTIVE')
- test_112_verify_ramdisk_active_v1_1.tags = ['nova']
-
- def test_113_verify_image_active_v1_1(self):
- # for testing purposes change self.glance['image_id'] to an active
- # image id allows for skipping glance tests
- if not 'image_id' in self.glance:
- self.glance['image_id'] = "63"
-
- path = "http://%s:%s/%s/images/%s" % (self.nova['host'],
- self.nova['port'],
- self.nova['ver'],
- self.glance['image_id'])
- http = httplib2.Http()
- headers = {'X-Auth-User': '%s' % (self.nova['user']),
- 'X-Auth-Token': '%s' % (self.nova['X-Auth-Token'])}
- response, content = http.request(path, 'GET', headers=headers)
- self.assertEqual(response.status, 200)
- data = json.loads(content)
- self.assertEqual(data['image']['status'], 'ACTIVE')
- test_113_verify_image_active_v1_1.tags = ['nova']
-
- def test_200_create_server(self):
- path = "http://%s:%s/%s/servers" % (self.nova['host'],
- self.nova['port'],
- self.nova['ver'])
- http = httplib2.Http()
- headers = {'X-Auth-User': '%s' % (self.nova['user']),
- 'X-Auth-Token': '%s' % (self.nova['X-Auth-Token']),
- 'Content-Type': 'application/json'}
-
- # Change imageRef to self.glance['image_id']
- json_str = {"server":
- {
- "name": "testing server creation",
- "flavorRef": "http://%s:%s/%s/flavors/2" % (self.nova['host'],
- self.nova['port'],
- self.nova['ver']),
- "imageRef": self.glance['image_id']
-# "imageRef": "http://%s:%s/%s/images/%s" % (self.nova['host'],
-# self.nova['port'],
-# self.nova['ver'],
-# self.glance['image_id'])
- }
- }
- pprint(json_str)
- data = json.dumps(json_str)
- response, content = http.request(path, 'POST', headers=headers,
- body=data)
- try:
- json_return = json.loads(content)
- except ValueError:
- print repr(content)
- raise
- self.assertEqual(response.status, 200)
- self.assertEqual(json_return['server']['status'], "BUILD")
- self.nova['single_server_id'] = json_return['server']['id']
- time.sleep(5)
- build_result = self.build_check(self.nova['single_server_id'])
- self.assertEqual(build_result['status'], "ACTIVE")
- self.assertEqual(build_result['ping'], True)
- test_200_create_server.tags = ['nova']
-
- def test_201_get_server_details(self):
- path = "http://%s:%s/%s/servers/%s" % (self.nova['host'],
- self.nova['port'],
- self.nova['ver'],
- self.nova['single_server_id'])
-
- http = httplib2.Http()
- headers = {'X-Auth-User': '%s' % (self.nova['user']),
- 'X-Auth-Token': '%s' % (self.nova['X-Auth-Token'])}
-
- response, content = http.request(path, 'GET', headers=headers)
- self.assertEqual(response.status, 200)
- test_201_get_server_details.tags = ['nova']
-
- # MOVING TO 999 because it can kill the API
- # Uncomment next line for testing
- # def create_multi(self):
- def test_999_create_multiple(self):
- self.nova['multi_server'] = {}
- path = "http://%s:%s/%s/servers" % (self.nova['host'],
- self.nova['port'],
- self.nova['ver'])
- http = httplib2.Http()
- headers = {'X-Auth-User': '%s' % (self.nova['user']),
- 'X-Auth-Token': '%s' % (self.nova['X-Auth-Token']),
- 'Content-Type': 'application/json'}
-
- for i in range(1, 10):
- # Change imageRef to self.glance['image_id']
- json_str = {"server":
- {
- "name": "test %s" % (i),
- "flavorRef": "http://%s:%s/%s/flavors/2" % (
- self.nova['host'],
- self.nova['port'],
- self.nova['ver']),
- "imageRef": self.glance['image_id']
-# "imageRef": "http://%s:%s/%s/images/%s" % (
-# self.nova['host'],
-# self.nova['port'],
-# self.nova['ver'],
-# self.glance['image_id'])
- }
- }
- data = json.dumps(json_str)
- response, content = http.request(path, 'POST', headers=headers,
- body=data)
- json_return = json.loads(content)
- self.assertEqual(response.status, 200)
- self.assertEqual(json_return['server']['status'], "BUILD")
- self.nova['multi_server']["test %s" % (i)] = \
- json_return['server']['id']
- time.sleep(30)
-
- for k, v in self.nova['multi_server'].iteritems():
- build_result = self.build_check(v)
- self.assertEqual(build_result['ping'], True)
- test_999_create_multiple.tags = ['nova']
diff --git a/kong/tests/__init__.py b/kong/tests/__init__.py
index b288ada..92725cb 100644
--- a/kong/tests/__init__.py
+++ b/kong/tests/__init__.py
@@ -19,7 +19,6 @@
from hashlib import md5
import nose.plugins.skip
import os
-from pprint import pprint
import unittest2
NOVA_DATA = {}
@@ -92,7 +91,6 @@
self.keystone = KEYSTONE_DATA
self._parse_defaults_file()
- pprint(self.config)
# Swift Setup
if 'swift' in self.config:
diff --git a/kong/tests/test_auth.py b/kong/tests/test_auth.py
new file mode 100644
index 0000000..bc040a8
--- /dev/null
+++ b/kong/tests/test_auth.py
@@ -0,0 +1,183 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2011 OpenStack, LLC
+# 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.
+
+"""Functional test case against the OpenStack Nova API server"""
+
+import httplib2
+import json
+import os
+import time
+import uuid
+
+from kong import keystone
+from kong import tests
+
+
+class TestKeystoneAuth(tests.FunctionalTest):
+
+ def setUp(self):
+ super(TestKeystoneAuth, self).setUp()
+
+ api_version = self.keystone['apiver']
+ if api_version != 'v2.0':
+ raise ValueError("Must use Identity API v2.0")
+
+ args = (self.keystone['service_host'],
+ self.keystone['service_port'],
+ api_version)
+
+ self.base_url = "http://%s:%s/%s/tokens" % args
+
+ self.user = self.keystone['user']
+ self.password = self.keystone['password']
+ self.tenant_id = self.keystone['tenant_id']
+
+ def test_can_get_token(self):
+ headers = {'content-type': 'application/json'}
+
+ body = {
+ "auth": {
+ "passwordCredentials":{
+ "username": self.user,
+ "password": self.password,
+ },
+ "tenantId": self.tenant_id,
+ },
+ }
+
+ http = httplib2.Http()
+ response, content = http.request(self.base_url, 'POST',
+ headers=headers,
+ body=json.dumps(body))
+
+ self.assertEqual(response.status, 200)
+ res_body = json.loads(content)
+ self.assertTrue(res_body['access']['token']['id'])
+ test_can_get_token.tags = ['auth']
+
+ def test_bad_user(self):
+ headers = {'content-type': 'application/json'}
+
+ body = {
+ "auth": {
+ "passwordCredentials": {
+ "username": str(uuid.uuid4()),
+ "password": self.password,
+ },
+ "tenantId": self.tenant_id,
+ },
+ }
+
+ http = httplib2.Http()
+ response, content = http.request(self.base_url, 'POST',
+ headers=headers,
+ body=json.dumps(body))
+
+ self.assertEqual(response.status, 401)
+ test_bad_user.tags = ['auth']
+
+ def test_bad_password(self):
+ headers = {'content-type': 'application/json'}
+
+ body = {
+ "auth": {
+ "passwordCredentials": {
+ "username": self.user,
+ "password": str(uuid.uuid4()),
+ },
+ "tenantId": self.tenant_id,
+ },
+ }
+
+ http = httplib2.Http()
+ response, content = http.request(self.base_url, 'POST',
+ headers=headers,
+ body=json.dumps(body))
+
+ self.assertEqual(response.status, 401)
+ test_bad_password.tags = ['auth']
+
+ def test_bad_tenant_id(self):
+ headers = {'content-type': 'application/json'}
+
+ body = {
+ "auth": {
+ "passwordCredentials": {
+ "username": self.user,
+ "password": self.password,
+ },
+ "tenantId": str(uuid.uuid4()),
+ },
+ }
+
+ http = httplib2.Http()
+ response, content = http.request(self.base_url, 'POST',
+ headers=headers,
+ body=json.dumps(body))
+
+ self.assertEqual(response.status, 401)
+ test_bad_tenant_id.tags = ['auth']
+
+
+
+class TestKeystoneAuthWithNova(tests.FunctionalTest):
+
+ def setUp(self):
+ super(TestKeystoneAuthWithNova, self).setUp()
+ args = (self.nova['host'], self.nova['port'],
+ self.nova['ver'], self.nova['project'])
+ self.base_url = "http://%s:%s/%s/%s" % args
+
+ self.keystone_api = keystone.API(self.keystone['service_host'],
+ self.keystone['service_port'])
+
+ def _get_token(self):
+ user = self.keystone['user']
+ password = self.keystone['password']
+ tenant_id = self.keystone['tenant_id']
+ return self.keystone_api.get_token(user, password, tenant_id)
+
+ def test_good_token(self):
+ http = httplib2.Http()
+ url = '%s/flavors' % self.base_url
+ headers = {'x-auth-token': self._get_token()}
+ response, content = http.request(url, 'GET', headers=headers)
+ self.assertEqual(response.status, 200)
+ test_good_token.tags = ['nova', 'auth']
+
+ def test_bad_token(self):
+ http = httplib2.Http()
+ url = '%s/flavors' % self.base_url
+ headers = {'x-auth-token': str(uuid.uuid4())}
+ response, content = http.request(url, 'GET', headers=headers)
+ self.assertEqual(response.status, 401)
+ test_bad_token.tags = ['nova', 'auth']
+
+ def test_no_token(self):
+ http = httplib2.Http()
+ url = '%s/flavors' % self.base_url
+ headers = {'x-auth-token': str(uuid.uuid4())}
+ response, content = http.request(url, 'GET', headers=headers)
+ self.assertEqual(response.status, 401)
+ test_no_token.tags = ['nova', 'auth']
+
+ def test_no_header(self):
+ http = httplib2.Http()
+ url = '%s/flavors' % self.base_url
+ response, content = http.request(url, 'GET')
+ self.assertEqual(response.status, 401)
+ test_no_header.tags = ['nova', 'auth']
diff --git a/kong/tests/test_images.py b/kong/tests/test_images.py
index d8a4721..1163723 100644
--- a/kong/tests/test_images.py
+++ b/kong/tests/test_images.py
@@ -1,3 +1,4 @@
+import httplib2
import json
import os
import re
@@ -6,10 +7,10 @@
from kong import tests
-class ImagesTest(tests.FunctionalTest):
+class TestImagesThroughCompute(tests.FunctionalTest):
def setUp(self):
- super(ImagesTest, self).setUp()
+ super(TestImagesThroughCompute, self).setUp()
self.os = openstack.Manager(self.nova)
def _assert_image_links(self, image):
@@ -82,3 +83,125 @@
for image in resp_body['images']:
self._assert_image_entity_detailed(image)
test_detail.tags = ['nova', 'glance']
+
+
+class TestGlanceAPI(tests.FunctionalTest):
+
+ def setUp(self):
+ super(TestGlanceAPI, self).setUp()
+ self.base_url = "http://%s:%s/%s/images" % (self.glance['host'],
+ self.glance['port'],
+ self.glance['apiver'])
+
+ def test_upload_ami_style_image(self):
+ """Uploads a three-part ami-style image"""
+ aki_location = self.config['environment']['aki_location']
+ headers = {'x-image-meta-is-public': 'true',
+ 'x-image-meta-name': 'test-kernel',
+ 'x-image-meta-disk-format': 'aki',
+ 'x-image-meta-container-format': 'aki',
+ 'Content-Length': '%d' % os.path.getsize(aki_location),
+ 'Content-Type': 'application/octet-stream'}
+ image_file = open(aki_location, "rb")
+ http = httplib2.Http()
+ response, content = http.request(self.base_url, 'POST',
+ headers=headers,body=image_file)
+ image_file.close()
+ self.assertEqual(201, response.status)
+ data = json.loads(content)
+ self.assertEqual(data['image']['name'], "test-kernel")
+ self.assertEqual(data['image']['checksum'],
+ self._md5sum_file(aki_location))
+ kernel_id = data['image']['id']
+
+ ari_location = self.config['environment'].get('ari_location')
+ if ari_location:
+ headers = {'x-image-meta-is-public': 'true',
+ 'x-image-meta-name': 'test-ramdisk',
+ 'x-image-meta-disk-format': 'ari',
+ 'x-image-meta-container-format': 'ari',
+ 'Content-Length': '%d' % os.path.getsize(ari_location),
+ 'Content-Type': 'application/octet-stream'}
+ image_file = open(ari_location, "rb")
+ http = httplib2.Http()
+ response, content = http.request(self.base_url, 'POST',
+ headers=headers, body=image_file)
+ image_file.close()
+ self.assertEqual(201, response.status)
+ data = json.loads(content)
+ self.assertEqual(data['image']['name'], "test-ramdisk")
+ self.assertEqual(data['image']['checksum'],
+ self._md5sum_file(ari_location))
+ ramdisk_id = data['image']['id']
+ else:
+ ramdisk_id = None
+
+ ami_location = self.config['environment']['ami_location']
+ upload_data = ""
+ for chunk in self._read_in_chunks(ami_location):
+ upload_data += chunk
+ headers = {'x-image-meta-is-public': 'true',
+ 'x-image-meta-name': 'test-image',
+ 'x-image-meta-disk-format': 'ami',
+ 'x-image-meta-container-format': 'ami',
+ 'x-image-meta-property-kernel_id': kernel_id,
+ 'Content-Length': '%d' % os.path.getsize(ami_location),
+ 'Content-Type': 'application/octet-stream'}
+
+ if ari_location:
+ headers['x-image-meta-property-ramdisk_id'] = ramdisk_id
+
+ http = httplib2.Http()
+ response, content = http.request(self.base_url, 'POST',
+ headers=headers, body=upload_data)
+ self.assertEqual(201, response.status)
+ data = json.loads(content)
+ self.assertEqual(data['image']['name'], "test-image")
+ self.assertEqual(data['image']['checksum'],
+ self._md5sum_file(ami_location))
+ machine_id = data['image']['id']
+
+ # now ensure we can modify the image properties
+ headers = {'X-Image-Meta-Property-distro': 'Ubuntu',
+ 'X-Image-Meta-Property-arch': 'x86_64',
+ 'X-Image-Meta-Property-kernel_id': kernel_id}
+ if ari_location:
+ headers['X-Image-Meta-Property-ramdisk_id'] = ramdisk_id
+
+ http = httplib2.Http()
+ url = '%s/%s' % (self.base_url, machine_id)
+ response, content = http.request(url, 'PUT', headers=headers)
+ self.assertEqual(response.status, 200)
+ data = json.loads(content)
+ properties = data['image']['properties']
+ self.assertEqual(properties['arch'], "x86_64")
+ self.assertEqual(properties['distro'], "Ubuntu")
+ self.assertEqual(properties['kernel_id'], kernel_id)
+ if ari_location:
+ self.assertEqual(properties['ramdisk_id'], ramdisk_id)
+
+ # list the metadata to ensure the new values stuck
+ http = httplib2.Http()
+ response, content = http.request(url, 'HEAD')
+ self.assertEqual(response.status, 200)
+ self.assertEqual(response['x-image-meta-name'], "test-image")
+ self.assertEqual(response['x-image-meta-checksum'],
+ self._md5sum_file(ami_location))
+ self.assertEqual(response['x-image-meta-container_format'], "ami")
+ self.assertEqual(response['x-image-meta-disk_format'], "ami")
+ self.assertEqual(response['x-image-meta-property-arch'], "x86_64")
+ self.assertEqual(response['x-image-meta-property-distro'], "Ubuntu")
+ self.assertEqual(response['x-image-meta-property-kernel_id'],
+ kernel_id)
+ if ari_location:
+ self.assertEqual(response['x-image-meta-property-ramdisk_id'],
+ ramdisk_id)
+
+ # delete images for which we have non-None ids
+ delete_ids = filter(lambda x: x, (kernel_id, ramdisk_id, machine_id))
+ for image_id in delete_ids:
+ http = httplib2.Http()
+ url = '%s/%s' % (self.base_url, image_id)
+ response, content = http.request(url, 'DELETE')
+
+ test_upload_ami_style_image.tags = ['glance']
diff --git a/kong/tests/test_servers.py b/kong/tests/test_servers.py
index f81f6a2..0957327 100644
--- a/kong/tests/test_servers.py
+++ b/kong/tests/test_servers.py
@@ -1,5 +1,6 @@
import base64
+import datetime
import json
import os
@@ -7,6 +8,7 @@
from kong import exceptions
from kong import tests
from kong.common import ssh
+from kong.common import utils
class ServersTest(tests.FunctionalTest):
@@ -68,17 +70,16 @@
self.assertEqual(server['links'], expected_links)
- def test_build_server(self):
- """Build a server"""
+ def test_build_update_delete(self):
+ """Build and delete a server"""
+
+ server_password = 'testpwd'
expected_server = {
'name': 'testserver',
- 'metadata': {
- 'key1': 'value1',
- 'key2': 'value2',
- },
'imageRef': self.image_ref,
'flavorRef': self.flavor_ref,
+ 'metadata': {'testEntry': 'testValue'},
}
post_body = json.dumps({'server': expected_server})
@@ -86,28 +87,252 @@
'/servers',
body=post_body)
+ # Ensure attributes were returned
self.assertEqual(response.status, 202)
-
_body = json.loads(body)
self.assertEqual(_body.keys(), ['server'])
created_server = _body['server']
- self.server_id = created_server['id'] # for the tearDown
-
admin_pass = created_server.pop('adminPass')
self._assert_server_entity(created_server)
self.assertEqual(expected_server['name'], created_server['name'])
+ self.assertEqual(created_server['accessIPv4'], '')
+ self.assertEqual(created_server['accessIPv6'], '')
self.assertEqual(expected_server['metadata'],
created_server['metadata'])
+ self.server_id = created_server['id']
- self.os.nova.wait_for_server_status(created_server['id'],
+ # Get server again and ensure attributes stuck
+ server = self.os.nova.get_server(self.server_id)
+ self._assert_server_entity(server)
+ self.assertEqual(server['name'], expected_server['name'])
+ self.assertEqual(server['accessIPv4'], '')
+ self.assertEqual(server['accessIPv6'], '')
+ self.assertEqual(server['metadata'], created_server['metadata'])
+
+ # Parse last-updated time
+ update_time = utils.load_isotime(server['created'])
+
+ # Ensure server not returned with future changes-since
+ future_time = utils.dump_isotime(update_time + datetime.timedelta(100))
+ params = 'changes-since=%s' % future_time
+ response, body = self.os.nova.request('GET', '/servers?%s' % params)
+ servers = json.loads(body)['servers']
+ self.assertTrue(len(servers) == 0)
+
+ # Ensure server is returned with past changes-since
+ future_time = utils.dump_isotime(update_time - datetime.timedelta(1))
+ params = 'changes-since=%s' % future_time
+ response, body = self.os.nova.request('GET', '/servers?%s' % params)
+ servers = json.loads(body)['servers']
+ server_ids = map(lambda x: x['id'], servers)
+ self.assertTrue(self.server_id in server_ids)
+
+ # Update name
+ new_name = 'testserver2'
+ new_server = {'name': new_name}
+ put_body = json.dumps({'server': new_server})
+ url = '/servers/%s' % self.server_id
+ resp, body = self.os.nova.request('PUT', url, body=put_body)
+
+ # Output from update should be a full server
+ self.assertEqual(resp.status, 200)
+ data = json.loads(body)
+ self.assertEqual(data.keys(), ['server'])
+ self._assert_server_entity(data['server'])
+ self.assertEqual(new_name, data['server']['name'])
+
+ # Check that name was changed
+ updated_server = self.os.nova.get_server(self.server_id)
+ self._assert_server_entity(updated_server)
+ self.assertEqual(new_name, updated_server['name'])
+
+ # Update accessIPv4
+ new_server = {'accessIPv4': '192.168.0.200'}
+ put_body = json.dumps({'server': new_server})
+ url = '/servers/%s' % self.server_id
+ resp, body = self.os.nova.request('PUT', url, body=put_body)
+
+ # Output from update should be a full server
+ self.assertEqual(resp.status, 200)
+ data = json.loads(body)
+ self.assertEqual(data.keys(), ['server'])
+ self._assert_server_entity(data['server'])
+ self.assertEqual('192.168.0.200', data['server']['accessIPv4'])
+
+ # Check that accessIPv4 was changed
+ updated_server = self.os.nova.get_server(self.server_id)
+ self._assert_server_entity(updated_server)
+ self.assertEqual('192.168.0.200', updated_server['accessIPv4'])
+
+ # Update accessIPv6
+ new_server = {'accessIPv6': 'feed::beef'}
+ put_body = json.dumps({'server': new_server})
+ url = '/servers/%s' % self.server_id
+ resp, body = self.os.nova.request('PUT', url, body=put_body)
+
+ # Output from update should be a full server
+ self.assertEqual(resp.status, 200)
+ data = json.loads(body)
+ self.assertEqual(data.keys(), ['server'])
+ self._assert_server_entity(data['server'])
+ self.assertEqual('feed::beef', data['server']['accessIPv6'])
+
+ # Check that accessIPv6 was changed
+ updated_server = self.os.nova.get_server(self.server_id)
+ self._assert_server_entity(updated_server)
+ self.assertEqual('feed::beef', updated_server['accessIPv6'])
+
+ # Check metadata subresource
+ url = '/servers/%s/metadata' % self.server_id
+ response, body = self.os.nova.request('GET', url)
+ self.assertEqual(200, response.status)
+
+ result = json.loads(body)
+ expected = {'metadata': {'testEntry': 'testValue'}}
+ self.assertEqual(expected, result)
+
+ # Ensure metadata container can be modified
+ expected = {
+ 'metadata': {
+ 'new_meta1': 'new_value1',
+ 'new_meta2': 'new_value2',
+ },
+ }
+ post_body = json.dumps(expected)
+ url = '/servers/%s/metadata' % self.server_id
+ response, body = self.os.nova.request('POST', url, body=post_body)
+ self.assertEqual(200, response.status)
+ result = json.loads(body)
+ expected['metadata']['testEntry'] = 'testValue'
+ self.assertEqual(expected, result)
+
+ # Ensure values stick
+ url = '/servers/%s/metadata' % self.server_id
+ response, body = self.os.nova.request('GET', url)
+ self.assertEqual(200, response.status)
+ result = json.loads(body)
+ self.assertEqual(expected, result)
+
+ # Ensure metadata container can be overwritten
+ expected = {
+ 'metadata': {
+ 'new_meta3': 'new_value3',
+ 'new_meta4': 'new_value4',
+ },
+ }
+ url = '/servers/%s/metadata' % self.server_id
+ post_body = json.dumps(expected)
+ response, body = self.os.nova.request('PUT', url, body=post_body)
+ self.assertEqual(200, response.status)
+ result = json.loads(body)
+ self.assertEqual(expected, result)
+
+ # Ensure values stick
+ url = '/servers/%s/metadata' % self.server_id
+ response, body = self.os.nova.request('GET', url)
+ self.assertEqual(200, response.status)
+ result = json.loads(body)
+ self.assertEqual(expected, result)
+
+ # Set specific key
+ expected_meta = {'meta': {'new_meta5': 'new_value5'}}
+ put_body = json.dumps(expected_meta)
+ url = '/servers/%s/metadata/new_meta5' % self.server_id
+ response, body = self.os.nova.request('PUT', url, body=put_body)
+ self.assertEqual(200, response.status)
+ result = json.loads(body)
+ self.assertDictEqual(expected_meta, result)
+
+ # Ensure value sticks
+ expected_metadata = {
+ 'metadata': {
+ 'new_meta3': 'new_value3',
+ 'new_meta4': 'new_value4',
+ 'new_meta5': 'new_value5',
+ },
+ }
+ url = '/servers/%s/metadata' % self.server_id
+ response, body = self.os.nova.request('GET', url)
+ result = json.loads(body)
+ self.assertDictEqual(expected_metadata, result)
+
+ # Update existing key
+ expected_meta = {'meta': {'new_meta4': 'new_value6'}}
+ put_body = json.dumps(expected_meta)
+ url = '/servers/%s/metadata/new_meta4' % self.server_id
+ response, body = self.os.nova.request('PUT', url, body=put_body)
+ self.assertEqual(200, response.status)
+ result = json.loads(body)
+ self.assertEqual(expected_meta, result)
+
+ # Ensure value sticks
+ expected_metadata = {
+ 'metadata': {
+ 'new_meta3': 'new_value3',
+ 'new_meta4': 'new_value6',
+ 'new_meta5': 'new_value5',
+ },
+ }
+ url = '/servers/%s/metadata' % self.server_id
+ response, body = self.os.nova.request('GET', url)
+ result = json.loads(body)
+ self.assertDictEqual(expected_metadata, result)
+
+ # Delete a certain key
+ url = '/servers/%s/metadata/new_meta3' % self.server_id
+ response, body = self.os.nova.request('DELETE', url)
+ self.assertEquals(204, response.status)
+
+ # Make sure the key is gone
+ url = '/servers/%s/metadata/new_meta3' % self.server_id
+ response, body = self.os.nova.request('GET', url)
+ self.assertEquals(404, response.status)
+
+ # Delete a nonexistant key
+ url = '/servers/%s/metadata/new_meta3' % self.server_id
+ response, body = self.os.nova.request('DELETE', url)
+ self.assertEquals(404, response.status)
+
+ # Wait for instance to boot
+ self.os.nova.wait_for_server_status(self.server_id,
'ACTIVE',
timeout=self.build_timeout)
- server = self.os.nova.get_server(created_server['id'])
+ # Look for 'addresses' attribute on server
+ url = '/servers/%s' % self.server_id
+ response, body = self.os.nova.request('GET', url)
+ self.assertEqual(response.status, 200)
+ body = json.loads(body)
+ self.assertTrue('addresses' in body['server'].keys())
+ server_addresses = body['server']['addresses']
+
+ # Addresses should be available from subresource
+ url = '/servers/%s/ips' % self.server_id
+ response, body = self.os.nova.request('GET', url)
+ self.assertEqual(response.status, 200)
+ body = json.loads(body)
+ self.assertEqual(body.keys(), ['addresses'])
+ ips_addresses = body['addresses']
+
+ # Ensure both resources return identical information
+ self.assertEqual(server_addresses, ips_addresses)
+
+ # Validate entities within network containers
+ for (network, network_data) in ips_addresses.items():
+ url = '/servers/%s/ips/%s' % (self.server_id, network)
+ response, body = self.os.nova.request('GET', url)
+ self.assertEqual(response.status, 200)
+ body = json.loads(body)
+ self.assertEqual(body.keys(), [network])
+ self.assertEqual(body[network], network_data)
+
+ # Check each IP entity
+ for ip_data in network_data:
+ self.assertEqual(set(ip_data.keys()), set(['addr', 'version']))
# Find IP of server
try:
- (_, network) = server['addresses'].popitem()
+ (_, network) = server_addresses.items()[0]
ip = network[0]['addr']
except KeyError:
self.fail("Failed to retrieve IP address from server entity")
@@ -116,10 +341,19 @@
if int(self.nova['ssh_timeout']) > 0:
client = ssh.Client(ip, 'root', admin_pass, self.ssh_timeout)
self.assertTrue(client.test_connection_auth())
- test_build_server.tags = ['nova', 'glance']
- def test_build_server_with_file(self):
- """Build a server with an injected file"""
+ self.os.nova.delete_server(self.server_id)
+
+ # Poll server until deleted
+ try:
+ url = '/servers/%s' % self.server_id
+ self.os.nova.poll_request_status('GET', url, 404)
+ except exceptions.TimeoutException:
+ self.fail("Server deletion timed out")
+ test_build_update_delete.tags = ['nova']
+
+ def test_build_with_password_and_file(self):
+ """Build a server with a custom password and an injected file"""
file_contents = 'testing'
@@ -137,6 +371,7 @@
],
'imageRef': self.image_ref,
'flavorRef': self.flavor_ref,
+ 'adminPass': 'secrete',
}
post_body = json.dumps({'server': expected_server})
@@ -152,6 +387,7 @@
self.server_id = _body['server']['id']
admin_pass = created_server.pop('adminPass', None)
+ self.assertEqual(expected_server['adminPass'], admin_pass)
self._assert_server_entity(created_server)
self.assertEqual(expected_server['name'], created_server['name'])
self.assertEqual(expected_server['metadata'],
@@ -175,62 +411,9 @@
client = ssh.Client(ip, 'root', admin_pass, self.ssh_timeout)
injected_file = client.exec_command('cat /etc/test.txt')
self.assertEqual(injected_file, file_contents)
- test_build_server_with_file.tags = ['nova', 'glance']
+ test_build_with_password_and_file.tags = ['nova']
- def test_build_server_with_password(self):
- """Build a server with a password"""
-
- server_password = 'testpwd'
-
- expected_server = {
- 'name': 'testserver',
- 'metadata': {
- 'key1': 'value1',
- 'key2': 'value2',
- },
- 'adminPass': server_password,
- 'imageRef': self.image_ref,
- 'flavorRef': self.flavor_ref,
- }
-
- post_body = json.dumps({'server': expected_server})
- response, body = self.os.nova.request('POST',
- '/servers',
- body=post_body)
-
- self.assertEqual(response.status, 202)
-
- _body = json.loads(body)
- self.assertEqual(_body.keys(), ['server'])
- created_server = _body['server']
-
- admin_pass = created_server.pop('adminPass', None)
- self._assert_server_entity(created_server)
- self.assertEqual(expected_server['name'], created_server['name'])
- self.assertEqual(expected_server['adminPass'], admin_pass)
- self.assertEqual(expected_server['metadata'],
- created_server['metadata'])
-
- self.os.nova.wait_for_server_status(created_server['id'],
- 'ACTIVE',
- timeout=self.build_timeout)
-
- server = self.os.nova.get_server(created_server['id'])
-
- # Find IP of server
- try:
- (_, network) = server['addresses'].popitem()
- ip = network[0]['addr']
- except KeyError:
- self.fail("Failed to retrieve IP address from server entity")
-
- # Assert password was set to that in request ( if ssh_timeout is > 0
- if int(self.nova['ssh_timeout']) > 0:
- client = ssh.Client(ip, 'root', server_password, self.ssh_timeout)
- self.assertTrue(client.test_connection_auth())
- test_build_server_with_password.tags = ['nova', 'glance']
-
- def test_delete_server_building(self):
+ def test_delete_while_building(self):
"""Delete a server while building"""
# Make create server request
@@ -253,79 +436,9 @@
self.os.nova.poll_request_status('GET', url, 404)
except exceptions.TimeoutException:
self.fail("Server deletion timed out")
- test_delete_server_building.tags = ['nova', 'glance']
+ test_delete_while_building.tags = ['nova']
- def test_delete_server_active(self):
- """Delete a server after fully built"""
-
- expected_server = {
- 'name' : 'testserver',
- 'imageRef' : self.image_ref,
- 'flavorRef' : self.flavor_ref,
- }
-
- created_server = self.os.nova.create_server(expected_server)
- server_id = created_server['id']
-
- self.os.nova.wait_for_server_status(server_id,
- 'ACTIVE',
- timeout=self.build_timeout)
-
- self.os.nova.delete_server(server_id)
-
- # Poll server until deleted
- try:
- url = '/servers/%s' % server_id
- self.os.nova.poll_request_status('GET', url, 404)
- except exceptions.TimeoutException:
- self.fail("Server deletion timed out")
- test_delete_server_active.tags = ['nova', 'glance']
-
- def test_update_server_name(self):
- """Change the name of a server"""
-
- expected_server = {
- 'name' : 'testserver',
- 'imageRef' : self.image_ref,
- 'flavorRef' : self.flavor_ref,
- }
-
- created_server = self.os.nova.create_server(expected_server)
-
- self.assertTrue(expected_server['name'], created_server['name'])
- server_id = created_server['id']
-
- # Wait for it to be built
- self.os.nova.wait_for_server_status(server_id,
- 'ACTIVE',
- timeout=self.build_timeout)
-
- # Update name
- new_server = {'name': 'updatedtestserver'}
- put_body = json.dumps({
- 'server': new_server,
- })
- url = '/servers/%s' % server_id
- resp, body = self.os.nova.request('PUT', url, body=put_body)
-
- self.assertEqual(resp.status, 200)
- data = json.loads(body)
- self.assertEqual(data.keys(), ['server'])
- self._assert_server_entity(data['server'])
- self.assertEqual('updatedtestserver', data['server']['name'])
-
- # Get Server information
- resp, body = self.os.nova.request('GET', '/servers/%s' % server_id)
- self.assertEqual(200, resp.status)
- data = json.loads(body)
- self.assertEqual(data.keys(), ['server'])
- self._assert_server_entity(data['server'])
- self.assertEqual('updatedtestserver', data['server']['name'])
-
- self.os.nova.delete_server(server_id)
- test_update_server_name.tags = ['nova', 'glance']
-
- def test_create_server_invalid_image(self):
+ def test_create_with_invalid_image(self):
"""Create a server with an unknown image"""
post_body = json.dumps({
@@ -349,9 +462,9 @@
}
# KNOWN-ISSUE - The error message is confusing and should be improved
#self.assertEqual(fault, expected_fault)
- test_create_server_invalid_image.tags = ['nova', 'glance']
+ test_create_with_invalid_image.tags = ['nova']
- def test_create_server_invalid_flavor(self):
+ def test_create_with_invalid_flavor(self):
"""Create a server with an unknown flavor"""
post_body = json.dumps({
@@ -375,4 +488,4 @@
}
# KNOWN-ISSUE lp804084
#self.assertEqual(fault, expected_fault)
- test_create_server_invalid_flavor.tags = ['nova', 'glance']
+ test_create_with_invalid_flavor.tags = ['nova']