388 lines
18 KiB
Python
388 lines
18 KiB
Python
# 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 tempfile
|
|
import unittest
|
|
import httplib2
|
|
import urllib
|
|
import hashlib
|
|
import time
|
|
import os
|
|
|
|
from pprint import pprint
|
|
|
|
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(200, response.status)
|
|
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
|
|
if 'addr' in data['server']['addresses']['vmnet'][0]:
|
|
netaddr = data['server']['addresses']['vmnet'][0]['addr']
|
|
elif 'addr' in data['server']['address']['public'][0]:
|
|
netaddr = data['server']['addresses']['public'][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(204, response.status)
|
|
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(200, response.status)
|
|
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(200, response.status)
|
|
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(200, response.status)
|
|
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(200, response.status)
|
|
self.assertNotEqual('{"limits": []}', content)
|
|
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(200, response.status)
|
|
self.assertNotEqual('{"flavors": []}', content)
|
|
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(200, response.status)
|
|
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(200, response.status)
|
|
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(200, response.status)
|
|
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'])
|
|
}
|
|
}
|
|
data = json.dumps(json_str)
|
|
response, content = http.request(path, 'POST', headers=headers,
|
|
body=data)
|
|
json_return = json.loads(content)
|
|
self.assertEqual(200, response.status)
|
|
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(200, response.status)
|
|
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(200, response.status)
|
|
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']
|