Initial Release
This commit is contained in:
parent
f88913f26e
commit
0d9bbd1471
7
.gitignore
vendored
Normal file
7
.gitignore
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
.kong-venv
|
||||
*.pyc
|
||||
etc/config.ini
|
||||
include/swift_objects/swift_small
|
||||
include/swift_objects/swift_medium
|
||||
include/swift_objects/swift_large
|
||||
*.log
|
41
README.rst
Normal file
41
README.rst
Normal file
@ -0,0 +1,41 @@
|
||||
::
|
||||
|
||||
.-'''-.
|
||||
' _ \
|
||||
. / /` '. \ _..._
|
||||
.'| . | \ ' .' '. .--./)
|
||||
.' | | ' | '. .-. . /.''\\
|
||||
< | \ \ / / | ' ' || | | |
|
||||
| | ____`. ` ..' / | | | | \`-' /
|
||||
| | \ .' '-...-'` | | | | /("'`
|
||||
| |/ . | | | | \ '---.
|
||||
| /\ \ | | | | /'""'.\
|
||||
| | \ \ | | | | || ||
|
||||
' \ \ \ | | | | \'. __//
|
||||
'------' '---' '--' '--' `'---'
|
||||
|
||||
|
||||
kong
|
||||
====
|
||||
|
||||
Kong is a set of tests to be run against a live cluster. Kong sees you when
|
||||
you're sleeping and knows when you've been bad or good.
|
||||
|
||||
|
||||
Quickstart
|
||||
----------
|
||||
|
||||
You're going to want to make your own config.ini file in the /etc/ directory,
|
||||
it needs to point at your running cluster.
|
||||
|
||||
After that try commands such as::
|
||||
|
||||
run_tests.sh --nova
|
||||
run_tests.sh --glance
|
||||
run_tests.sh --swift
|
||||
|
||||
|
||||
Additional Info
|
||||
---------------
|
||||
|
||||
There are additional README files in the various subdirectories of this project.
|
1
etc/README.txt
Normal file
1
etc/README.txt
Normal file
@ -0,0 +1 @@
|
||||
Copy config.ini.sample to config.ini, and update it to reflect your environment.
|
32
etc/config.ini.sample
Normal file
32
etc/config.ini.sample
Normal file
@ -0,0 +1,32 @@
|
||||
[swift]
|
||||
auth_host = 10.0.0.100
|
||||
auth_port = 443
|
||||
auth_prefix = /auth/
|
||||
auth_ssl = yes
|
||||
account = system
|
||||
username = root
|
||||
password = password
|
||||
|
||||
[rabbitmq]
|
||||
host = 10.0.0.100
|
||||
user = guest
|
||||
password =
|
||||
|
||||
[glance]
|
||||
host = 10.0.0.100
|
||||
apiver = v1.0
|
||||
port = 9292
|
||||
|
||||
[nova]
|
||||
host = 10.0.0.100
|
||||
port = 8774
|
||||
apiver = v1.1
|
||||
user = admin
|
||||
key = 24BD8F71-6AD8-439D-B722-7E2E25FD1911
|
||||
|
||||
[keystone]
|
||||
host = 10.0.0.100
|
||||
port = 5000
|
||||
apiver = v1.1
|
||||
user = admin
|
||||
password = password
|
5
include/swift_objects/README.txt
Normal file
5
include/swift_objects/README.txt
Normal file
@ -0,0 +1,5 @@
|
||||
## For the swift tests you will need three objects to upload for the test
|
||||
## examples below are a 512K object, a 500M object, and 1G object
|
||||
dd if=/dev/zero of=swift_small bs=512 count=1024
|
||||
dd if=/dev/zero of=swift_medium bs=512 count=1024000
|
||||
dd if=/dev/zero of=swift_large bs=1024 count=1024000
|
300
run_tests.py
Normal file
300
run_tests.py
Normal file
@ -0,0 +1,300 @@
|
||||
#!/usr/bin/env python
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
import gettext
|
||||
import heapq
|
||||
import os
|
||||
import unittest
|
||||
import sys
|
||||
import time
|
||||
|
||||
from nose import config
|
||||
from nose import result
|
||||
from nose import core
|
||||
|
||||
|
||||
class _AnsiColorizer(object):
|
||||
"""
|
||||
A colorizer is an object that loosely wraps around a stream, allowing
|
||||
callers to write text to the stream in a particular color.
|
||||
|
||||
Colorizer classes must implement C{supported()} and C{write(text, color)}.
|
||||
"""
|
||||
_colors = dict(black=30, red=31, green=32, yellow=33,
|
||||
blue=34, magenta=35, cyan=36, white=37)
|
||||
|
||||
def __init__(self, stream):
|
||||
self.stream = stream
|
||||
|
||||
def supported(cls, stream=sys.stdout):
|
||||
"""
|
||||
A class method that returns True if the current platform supports
|
||||
coloring terminal output using this method. Returns False otherwise.
|
||||
"""
|
||||
if not stream.isatty():
|
||||
return False # auto color only on TTYs
|
||||
try:
|
||||
import curses
|
||||
except ImportError:
|
||||
return False
|
||||
else:
|
||||
try:
|
||||
try:
|
||||
return curses.tigetnum("colors") > 2
|
||||
except curses.error:
|
||||
curses.setupterm()
|
||||
return curses.tigetnum("colors") > 2
|
||||
except:
|
||||
raise
|
||||
# guess false in case of error
|
||||
return False
|
||||
supported = classmethod(supported)
|
||||
|
||||
def write(self, text, color):
|
||||
"""
|
||||
Write the given text to the stream in the given color.
|
||||
|
||||
@param text: Text to be written to the stream.
|
||||
|
||||
@param color: A string label for a color. e.g. 'red', 'white'.
|
||||
"""
|
||||
color = self._colors[color]
|
||||
self.stream.write('\x1b[%s;1m%s\x1b[0m' % (color, text))
|
||||
|
||||
|
||||
class _Win32Colorizer(object):
|
||||
"""
|
||||
See _AnsiColorizer docstring.
|
||||
"""
|
||||
def __init__(self, stream):
|
||||
from win32console import GetStdHandle, STD_OUT_HANDLE, \
|
||||
FOREGROUND_RED, FOREGROUND_BLUE, FOREGROUND_GREEN, \
|
||||
FOREGROUND_INTENSITY
|
||||
red, green, blue, bold = (FOREGROUND_RED, FOREGROUND_GREEN,
|
||||
FOREGROUND_BLUE, FOREGROUND_INTENSITY)
|
||||
self.stream = stream
|
||||
self.screenBuffer = GetStdHandle(STD_OUT_HANDLE)
|
||||
self._colors = {
|
||||
'normal': red | green | blue,
|
||||
'red': red | bold,
|
||||
'green': green | bold,
|
||||
'blue': blue | bold,
|
||||
'yellow': red | green | bold,
|
||||
'magenta': red | blue | bold,
|
||||
'cyan': green | blue | bold,
|
||||
'white': red | green | blue | bold
|
||||
}
|
||||
|
||||
def supported(cls, stream=sys.stdout):
|
||||
try:
|
||||
import win32console
|
||||
screenBuffer = win32console.GetStdHandle(
|
||||
win32console.STD_OUT_HANDLE)
|
||||
except ImportError:
|
||||
return False
|
||||
import pywintypes
|
||||
try:
|
||||
screenBuffer.SetConsoleTextAttribute(
|
||||
win32console.FOREGROUND_RED |
|
||||
win32console.FOREGROUND_GREEN |
|
||||
win32console.FOREGROUND_BLUE)
|
||||
except pywintypes.error:
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
supported = classmethod(supported)
|
||||
|
||||
def write(self, text, color):
|
||||
color = self._colors[color]
|
||||
self.screenBuffer.SetConsoleTextAttribute(color)
|
||||
self.stream.write(text)
|
||||
self.screenBuffer.SetConsoleTextAttribute(self._colors['normal'])
|
||||
|
||||
|
||||
class _NullColorizer(object):
|
||||
"""
|
||||
See _AnsiColorizer docstring.
|
||||
"""
|
||||
def __init__(self, stream):
|
||||
self.stream = stream
|
||||
|
||||
def supported(cls, stream=sys.stdout):
|
||||
return True
|
||||
supported = classmethod(supported)
|
||||
|
||||
def write(self, text, color):
|
||||
self.stream.write(text)
|
||||
|
||||
|
||||
def get_elapsed_time_color(elapsed_time):
|
||||
if elapsed_time > 1.0:
|
||||
return 'red'
|
||||
elif elapsed_time > 0.25:
|
||||
return 'yellow'
|
||||
else:
|
||||
return 'green'
|
||||
|
||||
|
||||
class KongTestResult(result.TextTestResult):
|
||||
def __init__(self, *args, **kw):
|
||||
self.show_elapsed = kw.pop('show_elapsed')
|
||||
result.TextTestResult.__init__(self, *args, **kw)
|
||||
self.num_slow_tests = 5
|
||||
self.slow_tests = [] # this is a fixed-sized heap
|
||||
self._last_case = None
|
||||
self.colorizer = None
|
||||
# NOTE(vish, tfukushima): reset stdout for the terminal check
|
||||
stdout = sys.__stdout__
|
||||
sys.stdout = sys.__stdout__
|
||||
for colorizer in [_Win32Colorizer, _AnsiColorizer, _NullColorizer]:
|
||||
if colorizer.supported():
|
||||
self.colorizer = colorizer(self.stream)
|
||||
break
|
||||
sys.stdout = stdout
|
||||
|
||||
# NOTE(lorinh): Initialize start_time in case a sqlalchemy-migrate
|
||||
# error results in it failing to be initialized later. Otherwise,
|
||||
# _handleElapsedTime will fail, causing the wrong error message to
|
||||
# be outputted.
|
||||
self.start_time = time.time()
|
||||
|
||||
def getDescription(self, test):
|
||||
return str(test)
|
||||
|
||||
def _handleElapsedTime(self, test):
|
||||
self.elapsed_time = time.time() - self.start_time
|
||||
item = (self.elapsed_time, test)
|
||||
# Record only the n-slowest tests using heap
|
||||
if len(self.slow_tests) >= self.num_slow_tests:
|
||||
heapq.heappushpop(self.slow_tests, item)
|
||||
else:
|
||||
heapq.heappush(self.slow_tests, item)
|
||||
|
||||
def _writeElapsedTime(self, test):
|
||||
color = get_elapsed_time_color(self.elapsed_time)
|
||||
self.colorizer.write(" %.2f" % self.elapsed_time, color)
|
||||
|
||||
def _writeResult(self, test, long_result, color, short_result, success):
|
||||
if self.showAll:
|
||||
self.colorizer.write(long_result, color)
|
||||
if self.show_elapsed and success:
|
||||
self._writeElapsedTime(test)
|
||||
self.stream.writeln()
|
||||
elif self.dots:
|
||||
self.stream.write(short_result)
|
||||
self.stream.flush()
|
||||
|
||||
# NOTE(vish, tfukushima): copied from unittest with edit to add color
|
||||
def addSuccess(self, test):
|
||||
unittest.TestResult.addSuccess(self, test)
|
||||
self._handleElapsedTime(test)
|
||||
self._writeResult(test, 'OK', 'green', '.', True)
|
||||
|
||||
# NOTE(vish, tfukushima): copied from unittest with edit to add color
|
||||
def addFailure(self, test, err):
|
||||
unittest.TestResult.addFailure(self, test, err)
|
||||
self._handleElapsedTime(test)
|
||||
self._writeResult(test, 'FAIL', 'red', 'F', False)
|
||||
|
||||
# NOTE(vish, tfukushima): copied from unittest with edit to add color
|
||||
def addError(self, test, err):
|
||||
"""Overrides normal addError to add support for errorClasses.
|
||||
If the exception is a registered class, the error will be added
|
||||
to the list for that class, not errors.
|
||||
"""
|
||||
self._handleElapsedTime(test)
|
||||
stream = getattr(self, 'stream', None)
|
||||
ec, ev, tb = err
|
||||
try:
|
||||
exc_info = self._exc_info_to_string(err, test)
|
||||
except TypeError:
|
||||
# This is for compatibility with Python 2.3.
|
||||
exc_info = self._exc_info_to_string(err)
|
||||
for cls, (storage, label, isfail) in self.errorClasses.items():
|
||||
if result.isclass(ec) and issubclass(ec, cls):
|
||||
if isfail:
|
||||
test.passwd = False
|
||||
storage.append((test, exc_info))
|
||||
# Might get patched into a streamless result
|
||||
if stream is not None:
|
||||
if self.showAll:
|
||||
message = [label]
|
||||
detail = result._exception_detail(err[1])
|
||||
if detail:
|
||||
message.append(detail)
|
||||
stream.writeln(": ".join(message))
|
||||
elif self.dots:
|
||||
stream.write(label[:1])
|
||||
return
|
||||
self.errors.append((test, exc_info))
|
||||
test.passed = False
|
||||
if stream is not None:
|
||||
self._writeResult(test, 'ERROR', 'red', 'E', False)
|
||||
|
||||
def startTest(self, test):
|
||||
unittest.TestResult.startTest(self, test)
|
||||
self.start_time = time.time()
|
||||
current_case = test.test.__class__.__name__
|
||||
|
||||
if self.showAll:
|
||||
if current_case != self._last_case:
|
||||
self.stream.writeln(current_case)
|
||||
self._last_case = current_case
|
||||
|
||||
self.stream.write(
|
||||
' %s' % str(test.test._testMethodName).ljust(60))
|
||||
self.stream.flush()
|
||||
|
||||
|
||||
class KongTestRunner(core.TextTestRunner):
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.show_elapsed = kwargs.pop('show_elapsed')
|
||||
core.TextTestRunner.__init__(self, *args, **kwargs)
|
||||
|
||||
def _makeResult(self):
|
||||
return KongTestResult(self.stream,
|
||||
self.descriptions,
|
||||
self.verbosity,
|
||||
self.config,
|
||||
show_elapsed=self.show_elapsed)
|
||||
|
||||
def _writeSlowTests(self, result_):
|
||||
# Pare out 'fast' tests
|
||||
slow_tests = [item for item in result_.slow_tests
|
||||
if get_elapsed_time_color(item[0]) != 'green']
|
||||
if slow_tests:
|
||||
slow_total_time = sum(item[0] for item in slow_tests)
|
||||
self.stream.writeln("Slowest %i tests took %.2f secs:"
|
||||
% (len(slow_tests), slow_total_time))
|
||||
for elapsed_time, test in sorted(slow_tests, reverse=True):
|
||||
time_str = "%.2f" % elapsed_time
|
||||
self.stream.writeln(" %s %s" % (time_str.ljust(10), test))
|
||||
|
||||
def run(self, test):
|
||||
result_ = core.TextTestRunner.run(self, test)
|
||||
if self.show_elapsed:
|
||||
self._writeSlowTests(result_)
|
||||
return result_
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
show_elapsed = True
|
||||
argv = []
|
||||
for x in sys.argv:
|
||||
if x.startswith('test_'):
|
||||
argv.append('nova.tests.%s' % x)
|
||||
elif x.startswith('--hide-elapsed'):
|
||||
show_elapsed = False
|
||||
else:
|
||||
argv.append(x)
|
||||
|
||||
c = config.Config(stream=sys.stdout,
|
||||
env=os.environ,
|
||||
verbosity=3,
|
||||
plugins=core.DefaultPluginManager())
|
||||
|
||||
runner = KongTestRunner(stream=c.stream,
|
||||
verbosity=c.verbosity,
|
||||
config=c,
|
||||
show_elapsed=show_elapsed)
|
||||
sys.exit(not core.run(config=c, testRunner=runner, argv=argv))
|
94
run_tests.sh
Executable file
94
run_tests.sh
Executable file
@ -0,0 +1,94 @@
|
||||
#!/bin/bash
|
||||
|
||||
function usage {
|
||||
echo "Usage: $0 [OPTION]..."
|
||||
echo "Run the Kong test suite(s)"
|
||||
echo ""
|
||||
echo " -V, --virtual-env Always use virtualenv. Install automatically if not present"
|
||||
echo " -N, --no-virtual-env Don't use virtualenv. Run tests in local environment"
|
||||
echo " -f, --force Force a clean re-build of the virtual environment. Useful when dependencies have been added."
|
||||
echo " -p, --pep8 Just run pep8"
|
||||
echo " --nova Run all tests tagged as \"nova\"."
|
||||
echo " --swift Run all tests tagged as \"swift\"."
|
||||
echo " --glance Run all tests tagged as \"glance\"."
|
||||
echo " -h, --help Print this usage message"
|
||||
echo ""
|
||||
echo "Note: with no options specified, the script will try to run the tests in a virtual environment,"
|
||||
echo " If no virtualenv is found, the script will ask if you would like to create one. If you "
|
||||
echo " prefer to run tests NOT in a virtual environment, simply pass the -N option."
|
||||
exit
|
||||
}
|
||||
|
||||
function process_option {
|
||||
case "$1" in
|
||||
-h|--help) usage;;
|
||||
-V|--virtual-env) let always_venv=1; let never_venv=0;;
|
||||
-N|--no-virtual-env) let always_venv=0; let never_venv=1;;
|
||||
-f|--force) let force=1;;
|
||||
-p|--pep8) let just_pep8=1;;
|
||||
--nova) noseargs="$noseargs -a tags=nova";;
|
||||
--glance) noseargs="$noseargs -a tags=glance";;
|
||||
--swift) noseargs="$noseargs -a tags=swift";;
|
||||
*) noseargs="$noseargs $1"
|
||||
esac
|
||||
}
|
||||
|
||||
venv=.kong-venv
|
||||
with_venv=tools/with_venv.sh
|
||||
always_venv=0
|
||||
never_venv=0
|
||||
force=0
|
||||
noseargs=
|
||||
wrapper=""
|
||||
just_pep8=0
|
||||
|
||||
for arg in "$@"; do
|
||||
process_option $arg
|
||||
done
|
||||
|
||||
function run_tests {
|
||||
# Just run the test suites in current environment
|
||||
${wrapper} $NOSETESTS 2> run_tests.err.log
|
||||
}
|
||||
|
||||
function run_pep8 {
|
||||
echo "Running pep8 ..."
|
||||
PEP8_EXCLUDE=vcsversion.y
|
||||
PEP8_OPTIONS="--exclude=$PEP8_EXCLUDE --repeat --show-pep8 --show-source"
|
||||
PEP8_INCLUDE="tests tools run_tests.py"
|
||||
${wrapper} pep8 $PEP8_OPTIONS $PEP8_INCLUDE || exit 1
|
||||
}
|
||||
NOSETESTS="env python run_tests.py $noseargs"
|
||||
|
||||
if [ $never_venv -eq 0 ]
|
||||
then
|
||||
# Remove the virtual environment if --force used
|
||||
if [ $force -eq 1 ]; then
|
||||
echo "Cleaning virtualenv..."
|
||||
rm -rf ${venv}
|
||||
fi
|
||||
if [ -e ${venv} ]; then
|
||||
wrapper="${with_venv}"
|
||||
else
|
||||
if [ $always_venv -eq 1 ]; then
|
||||
# Automatically install the virtualenv
|
||||
env python tools/install_venv.py
|
||||
wrapper="${with_venv}"
|
||||
else
|
||||
echo -e "No virtual environment found...create one? (Y/n) \c"
|
||||
read use_ve
|
||||
if [ "x$use_ve" = "xY" -o "x$use_ve" = "x" -o "x$use_ve" = "xy" ]; then
|
||||
# Install the virtualenv and run the test suite in it
|
||||
env python tools/install_venv.py
|
||||
wrapper=${with_venv}
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ $just_pep8 -eq 1 ]; then
|
||||
run_pep8
|
||||
exit
|
||||
fi
|
||||
|
||||
run_tests || exit
|
1
sample_vm/README.txt
Normal file
1
sample_vm/README.txt
Normal file
@ -0,0 +1 @@
|
||||
You will need to download an image into this directory.. Will also need to update the tests to reference this new image.
|
55
tests/990_test_skip_examples.py
Normal file
55
tests/990_test_skip_examples.py
Normal file
@ -0,0 +1,55 @@
|
||||
# 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 to check the status of gepetto and
|
||||
set information of hosts etc..
|
||||
"""
|
||||
|
||||
import os
|
||||
import tests
|
||||
import unittest2
|
||||
|
||||
|
||||
class TestSkipExamples(tests.FunctionalTest):
|
||||
@tests.skip_test("testing skipping")
|
||||
def test_absolute_skip(self):
|
||||
x = 1
|
||||
|
||||
@tests.skip_unless(os.getenv("BLAH"),
|
||||
"Skipping -- Environment variable BLAH does not exist")
|
||||
def test_skip_unless_env_blah_exists(self):
|
||||
x = 1
|
||||
|
||||
@tests.skip_unless(os.getenv("USER"),
|
||||
"Not Skipping -- Environment variable USER does not exist")
|
||||
def test_skip_unless_env_user_exists(self):
|
||||
x = 1
|
||||
|
||||
@tests.skip_if(os.getenv("USER"),
|
||||
"Skiping -- Environment variable USER exists")
|
||||
def test_skip_if_env_user_exists(self):
|
||||
x = 1
|
||||
|
||||
@tests.skip_if(os.getenv("BLAH"),
|
||||
"Not Skipping -- Environment variable BLAH exists")
|
||||
def test_skip_if_env_blah_exists(self):
|
||||
x = 1
|
||||
|
||||
def test_tags_example(self):
|
||||
pass
|
||||
test_tags_example.tags = ['kvm', 'olympus']
|
100
tests/994_test_rabbitmq.py
Normal file
100
tests/994_test_rabbitmq.py
Normal file
@ -0,0 +1,100 @@
|
||||
# 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 to check RabbitMQ """
|
||||
import pika
|
||||
import tests
|
||||
|
||||
from pprint import pprint
|
||||
#RABBITMQ_HOST = get_config("rabbitmq/host")
|
||||
#RABBITMQ_USERNAME = get_config("rabbitmq/user")
|
||||
#RABBITMQ_PASSWORD = get_config("rabbitmq/password")
|
||||
|
||||
|
||||
class TestRabbitMQ(tests.FunctionalTest):
|
||||
def test_000_ghetto(self):
|
||||
"""
|
||||
This sets the host, user, and pass self variables so they
|
||||
are accessible by all other methods
|
||||
"""
|
||||
self.rabbitmq['host'] = self.config['rabbitmq']['host']
|
||||
self.rabbitmq['user'] = self.config['rabbitmq']['user']
|
||||
self.rabbitmq['pass'] = self.config['rabbitmq']['password']
|
||||
test_000_ghetto.tags = ['rabbitmq']
|
||||
|
||||
def _cnx(self):
|
||||
# TODO: Figuring out what's going with creds
|
||||
# creds = pika.credentials.PlainCredentials(
|
||||
# self.rabbitmq['user'], self.rabbitmq['pass']
|
||||
connection = pika.BlockingConnection(pika.ConnectionParameters(
|
||||
host=self.rabbitmq['host']))
|
||||
channel = connection.channel()
|
||||
return (channel, connection)
|
||||
|
||||
def test_001_connect(self):
|
||||
channel, connection = self._cnx()
|
||||
self.assert_(channel)
|
||||
connection.close()
|
||||
test_001_connect.tags = ['rabbitmq']
|
||||
|
||||
def test_002_send_receive_msg(self):
|
||||
unitmsg = 'Hello from unittest'
|
||||
channel, connection = self._cnx()
|
||||
channel.queue_declare(queue='u1')
|
||||
channel.basic_publish(exchange='',
|
||||
routing_key='u1',
|
||||
body=unitmsg)
|
||||
connection.close()
|
||||
|
||||
channel, connection = self._cnx()
|
||||
|
||||
def callback(ch, method, properties, body):
|
||||
self.assertEquals(body, unitmsg)
|
||||
ch.stop_consuming()
|
||||
|
||||
channel.basic_consume(callback,
|
||||
queue='u1',
|
||||
no_ack=True)
|
||||
channel.start_consuming()
|
||||
test_002_send_receive_msg.tags = ['rabbitmq']
|
||||
|
||||
def test_003_send_receive_msg_with_persistense(self):
|
||||
unitmsg = 'Hello from unittest with Persistense'
|
||||
channel, connection = self._cnx()
|
||||
channel.queue_declare(queue='u2', durable=True)
|
||||
prop = pika.BasicProperties(delivery_mode=2)
|
||||
channel.basic_publish(exchange='',
|
||||
routing_key='u2',
|
||||
body=unitmsg,
|
||||
properties=prop,
|
||||
)
|
||||
connection.close()
|
||||
|
||||
channel, connection = self._cnx()
|
||||
channel.queue_declare(queue='u2', durable=True)
|
||||
|
||||
def callback(ch, method, properties, body):
|
||||
self.assertEquals(body, unitmsg)
|
||||
ch.basic_ack(delivery_tag=method.delivery_tag)
|
||||
ch.stop_consuming()
|
||||
|
||||
channel.basic_qos(prefetch_count=1)
|
||||
channel.basic_consume(callback,
|
||||
queue='u2')
|
||||
|
||||
channel.start_consuming()
|
||||
test_003_send_receive_msg_with_persistense.tags = ['rabbitmq']
|
195
tests/995_test_swift.py
Normal file
195
tests/995_test_swift.py
Normal file
@ -0,0 +1,195 @@
|
||||
# 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 for OpenStack Swift """
|
||||
|
||||
import hashlib
|
||||
import httplib2
|
||||
import json
|
||||
import os
|
||||
import tempfile
|
||||
import time
|
||||
import unittest
|
||||
import urllib
|
||||
|
||||
from pprint import pprint
|
||||
|
||||
import tests
|
||||
|
||||
SMALL_OBJ = "include/swift_objects/swift_small"
|
||||
MED_OBJ = "include/swift_objects/swift_medium"
|
||||
LRG_OBJ = "include/swift_objects/swift_large"
|
||||
|
||||
|
||||
class TestSwift(tests.FunctionalTest):
|
||||
def test_000_auth(self):
|
||||
if self.swift['auth_ssl'] == "False":
|
||||
prot = "http://"
|
||||
else:
|
||||
prot = "https://"
|
||||
|
||||
path = "%s%s:%s%s%s" % (prot, self.swift['auth_host'],
|
||||
self.swift['auth_port'],
|
||||
self.swift['auth_prefix'],
|
||||
self.swift['ver'])
|
||||
|
||||
# Uncomment for debugging
|
||||
# pprint(path)
|
||||
|
||||
http = httplib2.Http(disable_ssl_certificate_validation=True)
|
||||
self.swift['auth_user'] = '%s:%s' % (self.swift['account'],
|
||||
self.swift['username'])
|
||||
headers = {'X-Auth-User': '%s' % (self.swift['auth_user']),
|
||||
'X-Auth-Key': '%s' % (self.swift['password'])}
|
||||
response, content = http.request(path, 'GET', headers=headers)
|
||||
self.assertEqual(200, response.status)
|
||||
self.assertIsNotNone(response['x-auth-token'])
|
||||
self.assertIsNotNone(response['x-storage-token'])
|
||||
self.assertIsNotNone(response['x-storage-url'])
|
||||
|
||||
for k, v in response.items():
|
||||
if (k == 'x-auth-token'):
|
||||
self.swift['x-auth-token'] = v
|
||||
if (k == 'x-storage-token'):
|
||||
self.swift['x-storage-token'] = v
|
||||
|
||||
# Since we don't have DNS this is a bit of a hack, but works
|
||||
url = response['x-storage-url'].split('/')
|
||||
self.swift['storage_url'] = "%s//%s:%s/%s/%s" % (url[0],
|
||||
self.swift['auth_host'],
|
||||
self.swift['auth_port'],
|
||||
url[3],
|
||||
url[4])
|
||||
test_000_auth.tags = ['swift']
|
||||
|
||||
def test_001_create_container(self):
|
||||
path = "%s/%s/" % (self.swift['storage_url'], "test_container")
|
||||
http = httplib2.Http(disable_ssl_certificate_validation=True)
|
||||
headers = { 'X-Storage-Token': '%s' % (self.swift['x-storage-token'])}
|
||||
response, content = http.request(path, 'PUT', headers=headers)
|
||||
self.assertEqual(201, response.status)
|
||||
test_001_create_container.tags = ['swift']
|
||||
|
||||
def test_002_list_containers(self):
|
||||
http = httplib2.Http(disable_ssl_certificate_validation=True)
|
||||
headers = {'X-Auth-Token': '%s' % (self.swift['x-auth-token'])}
|
||||
response, content = http.request(self.swift['storage_url'], 'GET',
|
||||
headers=headers)
|
||||
self.assertEqual(200, response.status)
|
||||
self.assertLessEqual('1', response['x-account-container-count'])
|
||||
test_002_list_containers.tags = ['swift']
|
||||
|
||||
def test_010_create_small_object(self):
|
||||
md5 = self._md5sum_file(SMALL_OBJ)
|
||||
path = "%s/%s/%s" % (self.swift['storage_url'],
|
||||
"test_container",
|
||||
"swift_small")
|
||||
http = httplib2.Http(disable_ssl_certificate_validation=True)
|
||||
headers = {'X-Auth-User': '%s:%s' % (self.swift['account'],
|
||||
self.swift['username']),
|
||||
'X-Storage-Token': '%s' % (self.swift['x-storage-token']),
|
||||
'ETag': '%s' % (md5),
|
||||
'Content-Length': '%d' % os.path.getsize(SMALL_OBJ),
|
||||
'Content-Type': 'application/octet-stream'}
|
||||
upload = open(SMALL_OBJ, "rb")
|
||||
response, content = http.request(path, 'PUT',
|
||||
headers=headers,
|
||||
body=upload)
|
||||
self.assertEqual(201, response.status)
|
||||
self.assertIn('201', content)
|
||||
test_010_create_small_object.tags = ['swift']
|
||||
|
||||
def test_011_create_medium_object(self):
|
||||
md5 = self._md5sum_file(MED_OBJ)
|
||||
path = "%s/%s/%s" % (self.swift['storage_url'],
|
||||
"test_container",
|
||||
"swift_medium")
|
||||
http = httplib2.Http(disable_ssl_certificate_validation=True)
|
||||
headers = {'X-Auth-User': '%s:%s' % (self.swift['account'],
|
||||
self.swift['username']),
|
||||
'X-Storage-Token': '%s' % (self.swift['x-storage-token']),
|
||||
'ETag': '%s' % (md5),
|
||||
'Content-Length': '%d' % (os.path.getsize(MED_OBJ)),
|
||||
'Content-Type': 'application/octet-stream',
|
||||
'Content-Encoding': 'gzip'}
|
||||
upload = ""
|
||||
for chunk in self._read_in_chunks(MED_OBJ):
|
||||
upload += chunk
|
||||
response, content = http.request(path, 'PUT',
|
||||
headers=headers,
|
||||
body=upload)
|
||||
self.assertEqual(201, response.status)
|
||||
test_011_create_medium_object.tags = ['swift']
|
||||
|
||||
def test_013_get_small_object(self):
|
||||
path = "%s/%s/%s" % (self.swift['storage_url'],
|
||||
"test_container",
|
||||
"swift_small")
|
||||
http = httplib2.Http(disable_ssl_certificate_validation=True)
|
||||
headers = {'X-Auth-User': '%s:%s' % (self.swift['account'],
|
||||
self.swift['username']),
|
||||
'X-Storage-Token': '%s' % (self.swift['x-storage-token'])}
|
||||
response, content = http.request(path, 'GET',
|
||||
headers=headers)
|
||||
self.assertEqual(200, response.status)
|
||||
self.assertEqual(self._md5sum_file(SMALL_OBJ), response['etag'])
|
||||
test_013_get_small_object.tags = ['swift']
|
||||
|
||||
def test_017_delete_small_object(self):
|
||||
path = "%s/%s/%s" % (self.swift['storage_url'], "test_container",
|
||||
"swift_small")
|
||||
http = httplib2.Http(disable_ssl_certificate_validation=True)
|
||||
headers = {'X-Auth-User': '%s:%s' % (self.swift['account'],
|
||||
self.swift['username']),
|
||||
'X-Storage-Token': '%s' % (
|
||||
self.swift['x-storage-token'])}
|
||||
response, content = http.request(path, 'DELETE', headers=headers)
|
||||
self.assertEqual(204, response.status)
|
||||
test_017_delete_small_object.tags = ['swift']
|
||||
|
||||
def test_018_delete_medium_object(self):
|
||||
path = "%s/%s/%s" % (self.swift['storage_url'], "test_container",
|
||||
"swift_medium")
|
||||
http = httplib2.Http(disable_ssl_certificate_validation=True)
|
||||
headers = {'X-Auth-User': '%s:%s' % (self.swift['account'],
|
||||
self.swift['username']),
|
||||
'X-Storage-Token': '%s' % (
|
||||
self.swift['x-storage-token'])}
|
||||
response, content = http.request(path, 'DELETE', headers=headers)
|
||||
self.assertEqual(204, response.status)
|
||||
test_018_delete_medium_object.tags = ['swift']
|
||||
|
||||
def test_030_check_container_metadata(self):
|
||||
path = "%s/%s" % (self.swift['storage_url'], "test_container")
|
||||
http = httplib2.Http(disable_ssl_certificate_validation=True)
|
||||
headers = {'X-Auth-User': '%s:%s' % (self.swift['account'],
|
||||
self.swift['username']),
|
||||
'X-Storage-Token': '%s' % (self.swift['x-storage-token'])}
|
||||
response, content = http.request(path, 'HEAD', headers=headers)
|
||||
self.assertEqual(204, response.status)
|
||||
# pprint(response)
|
||||
test_030_check_container_metadata.tags = ['swift']
|
||||
|
||||
def test_050_delete_container(self):
|
||||
path = "%s/%s" % (self.swift['storage_url'], "test_container")
|
||||
http = httplib2.Http(disable_ssl_certificate_validation=True)
|
||||
headers = {'X-Auth-User': '%s:%s' % (self.swift['account'],
|
||||
self.swift['username']),
|
||||
'X-Storage-Token': '%s' % (self.swift['x-storage-token'])}
|
||||
response, content = http.request(path, 'DELETE', headers=headers)
|
||||
self.assertEqual(204, response.status)
|
||||
test_050_delete_container.tags = ['swift']
|
193
tests/996_test_glance.py
Normal file
193
tests/996_test_glance.py
Normal file
@ -0,0 +1,193 @@
|
||||
# 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
|
||||
|
||||
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 = "sample_vm/vmlinuz-2.6.32-23-server"
|
||||
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
|
||||
"""
|
||||
initrd = "sample_vm/initrd.img-2.6.32-23-server"
|
||||
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 = "sample_vm/ubuntu-lucid.img"
|
||||
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'],
|
||||
'x-image-meta-property-Ramdisk_id': '%s' % \
|
||||
self.glance['ramdisk_id'],
|
||||
'Content-Length': '%d' % os.path.getsize(image),
|
||||
'Content-Type': 'application/octet-stream'}
|
||||
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'],
|
||||
'X-Image-Meta-Property-Ramdisk_id': '%s' % \
|
||||
self.glance['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']))
|
||||
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 = "sample_vm/ubuntu-lucid.img"
|
||||
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']))
|
||||
self.assertEqual(response['x-image-meta-property-ramdisk_id'],
|
||||
str(self.glance['ramdisk_id']))
|
||||
test_006_list_image_metadata.tags = ['glance']
|
387
tests/998_test_nova.py
Normal file
387
tests/998_test_nova.py
Normal file
@ -0,0 +1,387 @@
|
||||
# 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']
|
97
tests/999_test_cleanup.py
Normal file
97
tests/999_test_cleanup.py
Normal file
@ -0,0 +1,97 @@
|
||||
# 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 that utilizes cURL against the API server"""
|
||||
|
||||
import json
|
||||
import os
|
||||
import tempfile
|
||||
import unittest
|
||||
import httplib2
|
||||
import urllib
|
||||
import hashlib
|
||||
|
||||
from pprint import pprint
|
||||
|
||||
import tests
|
||||
|
||||
|
||||
class TestCleanUp(tests.FunctionalTest):
|
||||
def test_995_delete_server(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, 'DELETE', headers=headers)
|
||||
self.assertEqual(204, response.status)
|
||||
test_995_delete_server.tags = ['nova']
|
||||
|
||||
def test_996_delete_multi_server(self):
|
||||
print "Deleting %s instances." % (len(self.nova['multi_server']))
|
||||
for k, v in self.nova['multi_server'].iteritems():
|
||||
path = "http://%s:%s/%s/servers/%s" % (self.nova['host'],
|
||||
self.nova['port'],
|
||||
self.nova['ver'],
|
||||
v)
|
||||
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, 'DELETE', headers=headers)
|
||||
self.assertEqual(204, response.status)
|
||||
test_996_delete_multi_server.tags = ['nova']
|
||||
|
||||
def test_997_delete_kernel_from_glance(self):
|
||||
if 'apiver' in self.glance:
|
||||
path = "http://%s:%s/%s/images/%s" % (self.glance['host'],
|
||||
self.glance['port'], self.glance['apiver'],
|
||||
self.glance['kernel_id'])
|
||||
else:
|
||||
path = "http://%s:%s/images/%s" % (self.glance['host'],
|
||||
self.glance['port'], self.glance['kernel_id'])
|
||||
http = httplib2.Http()
|
||||
response, content = http.request(path, 'DELETE')
|
||||
self.assertEqual(200, response.status)
|
||||
test_997_delete_kernel_from_glance.tags = ['glance', 'nova']
|
||||
|
||||
def test_998_delete_initrd_from_glance(self):
|
||||
if 'apiver' in self.glance:
|
||||
path = "http://%s:%s/%s/images/%s" % (self.glance['host'],
|
||||
self.glance['port'], self.glance['apiver'],
|
||||
self.glance['ramdisk_id'])
|
||||
else:
|
||||
path = "http://%s:%s/images/%s" % (self.glance['host'],
|
||||
self.glance['port'], self.glance['ramdisk_id'])
|
||||
http = httplib2.Http()
|
||||
response, content = http.request(path, 'DELETE')
|
||||
self.assertEqual(200, response.status)
|
||||
test_998_delete_initrd_from_glance.tags = ['glance', 'nova']
|
||||
|
||||
def test_999_delete_image_from_glance(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'])
|
||||
http = httplib2.Http()
|
||||
response, content = http.request(path, 'DELETE')
|
||||
self.assertEqual(200, response.status)
|
||||
test_999_delete_image_from_glance.tags = ['glance', 'nova']
|
159
tests/__init__.py
Normal file
159
tests/__init__.py
Normal file
@ -0,0 +1,159 @@
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
# Copyright 2010-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.
|
||||
|
||||
import ConfigParser
|
||||
from hashlib import md5
|
||||
import nose.plugins.skip
|
||||
import os
|
||||
import unittest2
|
||||
from xmlrpclib import Server
|
||||
|
||||
NOVA_DATA = {}
|
||||
GLANCE_DATA = {}
|
||||
SWIFT_DATA = {}
|
||||
RABBITMQ_DATA = {}
|
||||
CONFIG_DATA = {}
|
||||
KEYSTONE_DATA = {}
|
||||
|
||||
class skip_test(object):
|
||||
"""Decorator that skips a test."""
|
||||
def __init__(self, msg):
|
||||
self.message = msg
|
||||
|
||||
def __call__(self, func):
|
||||
def _skipper(*args, **kw):
|
||||
"""Wrapped skipper function."""
|
||||
raise nose.SkipTest(self.message)
|
||||
_skipper.__name__ = func.__name__
|
||||
_skipper.__doc__ = func.__doc__
|
||||
return _skipper
|
||||
|
||||
|
||||
class skip_if(object):
|
||||
"""Decorator that skips a test."""
|
||||
def __init__(self, condition, msg):
|
||||
self.condition = condition
|
||||
self.message = msg
|
||||
|
||||
def __call__(self, func):
|
||||
def _skipper(*args, **kw):
|
||||
"""Wrapped skipper function."""
|
||||
if self.condition:
|
||||
raise nose.SkipTest(self.message)
|
||||
func(*args, **kw)
|
||||
_skipper.__name__ = func.__name__
|
||||
_skipper.__doc__ = func.__doc__
|
||||
return _skipper
|
||||
|
||||
|
||||
class skip_unless(object):
|
||||
"""Decorator that skips a test."""
|
||||
def __init__(self, condition, msg):
|
||||
self.condition = condition
|
||||
self.message = msg
|
||||
|
||||
def __call__(self, func):
|
||||
def _skipper(*args, **kw):
|
||||
"""Wrapped skipper function."""
|
||||
if not self.condition:
|
||||
raise nose.SkipTest(self.message)
|
||||
func(*args, **kw)
|
||||
_skipper.__name__ = func.__name__
|
||||
_skipper.__doc__ = func.__doc__
|
||||
return _skipper
|
||||
|
||||
|
||||
class FunctionalTest(unittest2.TestCase):
|
||||
def setUp(self):
|
||||
global GLANCE_DATA, NOVA_DATA, SWIFT_DATA, RABBITMQ_DATA, KEYSTONE_DATA, CONFIG_DATA
|
||||
# Define config dict
|
||||
self.config = CONFIG_DATA
|
||||
# Define service specific dicts
|
||||
self.glance = GLANCE_DATA
|
||||
self.nova = NOVA_DATA
|
||||
self.swift = SWIFT_DATA
|
||||
self.rabbitmq = RABBITMQ_DATA
|
||||
self.keystone = KEYSTONE_DATA
|
||||
|
||||
self._parse_defaults_file()
|
||||
|
||||
# Swift Setup
|
||||
if 'swift' in self.config:
|
||||
self.swift['auth_host'] = self.config['swift']['auth_host']
|
||||
self.swift['auth_port'] = self.config['swift']['auth_port']
|
||||
self.swift['auth_prefix'] = self.config['swift']['auth_prefix']
|
||||
self.swift['auth_ssl'] = self.config['swift']['auth_ssl']
|
||||
self.swift['account'] = self.config['swift']['account']
|
||||
self.swift['username'] = self.config['swift']['username']
|
||||
self.swift['password'] = self.config['swift']['password']
|
||||
self.swift['ver'] = 'v1.0' # need to find a better way to get this.
|
||||
|
||||
# Glance Setup
|
||||
self.glance['host'] = self.config['glance']['host']
|
||||
self.glance['port'] = self.config['glance']['port']
|
||||
if 'apiver' in self.config['glance']:
|
||||
self.glance['apiver'] = self.config['glance']['apiver']
|
||||
|
||||
if 'nova' in self.config:
|
||||
self.nova['host'] = self.config['nova']['host']
|
||||
self.nova['port'] = self.config['nova']['port']
|
||||
self.nova['ver'] = self.config['nova']['apiver']
|
||||
self.nova['user'] = self.config['nova']['user']
|
||||
self.nova['key'] = self.config['nova']['key']
|
||||
|
||||
if 'keystone' in self.config:
|
||||
self.keystone['host'] = self.config['keystone']['host']
|
||||
self.keystone['port'] = self.config['keystone']['port']
|
||||
self.keystone['apiver'] = self.config['keystone']['apiver']
|
||||
self.keystone['user'] = self.config['keystone']['user']
|
||||
self.keystone['pass'] = self.config['keystone']['password']
|
||||
|
||||
def _md5sum_file(self, path):
|
||||
md5sum = md5()
|
||||
with open(path, 'rb') as file:
|
||||
for chunk in iter(lambda: file.read(8192), ''):
|
||||
md5sum.update(chunk)
|
||||
return md5sum.hexdigest()
|
||||
|
||||
def _read_in_chunks(self, infile, chunk_size=1024 * 64):
|
||||
file_data = open(infile, "rb")
|
||||
while True:
|
||||
# chunk = file_data.read(chunk_size).encode('base64')
|
||||
chunk = file_data.read(chunk_size)
|
||||
if chunk:
|
||||
yield chunk
|
||||
else:
|
||||
return
|
||||
file_data.close()
|
||||
|
||||
def _parse_defaults_file(self):
|
||||
cfg = os.path.abspath(os.path.join(os.path.dirname(__file__),
|
||||
"..", "etc", "config.ini"))
|
||||
if os.path.exists(cfg):
|
||||
self._build_config(cfg)
|
||||
else:
|
||||
raise Exception("Cannot read %s" % cfg)
|
||||
|
||||
def _build_config(self, config_file):
|
||||
parser = ConfigParser.ConfigParser()
|
||||
parser.read(config_file)
|
||||
|
||||
for section in parser.sections():
|
||||
self.config[section] = {}
|
||||
for value in parser.options(section):
|
||||
self.config[section][value] = parser.get(section, value)
|
||||
# print "%s = %s" % (value, parser.get(section, value))
|
135
tools/install_venv.py
Normal file
135
tools/install_venv.py
Normal file
@ -0,0 +1,135 @@
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
"""
|
||||
Installation script for Kong's testing virtualenv
|
||||
"""
|
||||
|
||||
import os
|
||||
import stat
|
||||
import string
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
ROOT = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
|
||||
VENV = os.path.join(ROOT, '.kong-venv')
|
||||
PIP_REQUIRES = os.path.join(ROOT, 'tools', 'pip-requires')
|
||||
|
||||
|
||||
def die(message, *args):
|
||||
print >> sys.stderr, message % args
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def whereis(executable):
|
||||
"""
|
||||
Detect whereis a binary and make sure it's executable we can execute.
|
||||
"""
|
||||
for d in string.split(os.environ['PATH'], \
|
||||
os.pathsep):
|
||||
f = os.path.join(d, executable)
|
||||
if os.path.isfile(f):
|
||||
try:
|
||||
st = os.stat(f)
|
||||
except OSError:
|
||||
continue
|
||||
if stat.S_IMODE(st[stat.ST_MODE]) & 0111:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def run_command(cmd, redirect_output=True, check_exit_code=True):
|
||||
"""
|
||||
Runs a command in an out-of-process shell, returning the
|
||||
output of that command. Working directory is ROOT.
|
||||
"""
|
||||
if redirect_output:
|
||||
stdout = subprocess.PIPE
|
||||
else:
|
||||
stdout = None
|
||||
|
||||
proc = subprocess.Popen(cmd, cwd=ROOT, stdout=stdout)
|
||||
output = proc.communicate()[0]
|
||||
if check_exit_code and proc.returncode != 0:
|
||||
die('Command "%s" failed.\n%s', ' '.join(cmd), output)
|
||||
return output
|
||||
|
||||
|
||||
HAS_EASY_INSTALL = bool(whereis("easy_install"))
|
||||
HAS_VIRTUALENV = bool(whereis("virtualenv"))
|
||||
|
||||
|
||||
def check_dependencies():
|
||||
"""Make sure virtualenv is in the path."""
|
||||
|
||||
if not HAS_VIRTUALENV:
|
||||
print 'not found.'
|
||||
# Try installing it via easy_install...
|
||||
if HAS_EASY_INSTALL:
|
||||
print 'Installing virtualenv via easy_install...',
|
||||
if not run_command(['easy_install', 'virtualenv']):
|
||||
die('ERROR: virtualenv not found.\n\n'
|
||||
'Glance development requires virtualenv, please install'
|
||||
' it using your favorite package management tool')
|
||||
print 'done.'
|
||||
print 'done.'
|
||||
|
||||
|
||||
def create_virtualenv(venv=VENV):
|
||||
"""Creates the virtual environment and installs PIP only into the
|
||||
virtual environment
|
||||
"""
|
||||
print 'Creating venv...',
|
||||
run_command(['virtualenv', '-q', '--no-site-packages', VENV])
|
||||
print 'done.'
|
||||
print 'Installing pip in virtualenv...',
|
||||
if not run_command(['tools/with_venv.sh', 'easy_install', 'pip']).strip():
|
||||
die("Failed to install pip.")
|
||||
print 'done.'
|
||||
|
||||
|
||||
def install_dependencies(venv=VENV):
|
||||
print 'Installing dependencies with pip (this can take a while)...'
|
||||
|
||||
# Install greenlet by hand - just listing it in the requires file does not
|
||||
# get it in stalled in the right order
|
||||
venv_tool = 'tools/with_venv.sh'
|
||||
run_command([venv_tool, 'pip', 'install', '-E', venv, '-r', PIP_REQUIRES],
|
||||
redirect_output=False)
|
||||
|
||||
# Tell the virtual env how to "import glance"
|
||||
pthfile = os.path.join(venv, "lib", "python2.6", "site-packages",
|
||||
"glance.pth")
|
||||
f = open(pthfile, 'w')
|
||||
f.write("%s\n" % ROOT)
|
||||
|
||||
|
||||
def print_help():
|
||||
help = """
|
||||
Kong testing environment setup is complete.
|
||||
|
||||
Kong testing uses virtualenv to track and manage Python dependencies
|
||||
while in development and testing.
|
||||
|
||||
To activate the Kong virtualenv for the extent of your current shell
|
||||
session you can run:
|
||||
|
||||
$ source .kong-venv/bin/activate
|
||||
|
||||
Or, if you prefer, you can run commands in the virtualenv on a case by case
|
||||
basis by running:
|
||||
|
||||
$ tools/with_venv.sh <your command>
|
||||
|
||||
Also, make test will automatically use the virtualenv.
|
||||
"""
|
||||
print help
|
||||
|
||||
|
||||
def main(argv):
|
||||
check_dependencies()
|
||||
create_virtualenv()
|
||||
install_dependencies()
|
||||
print_help()
|
||||
|
||||
if __name__ == '__main__':
|
||||
main(sys.argv)
|
9
tools/pip-requires
Normal file
9
tools/pip-requires
Normal file
@ -0,0 +1,9 @@
|
||||
pep8>=0.5.0
|
||||
pylint==0.19
|
||||
anyjson
|
||||
nose
|
||||
argparse
|
||||
httplib2>=0.7.0
|
||||
pika
|
||||
dnspython
|
||||
ipython
|
4
tools/with_venv.sh
Executable file
4
tools/with_venv.sh
Executable file
@ -0,0 +1,4 @@
|
||||
#!/bin/bash
|
||||
TOOLS=`dirname $0`
|
||||
VENV=$TOOLS/../.kong-venv
|
||||
source $VENV/bin/activate && $@
|
Loading…
Reference in New Issue
Block a user