Rebased to Nova revision 749.

This commit is contained in:
sateesh
2011-02-27 08:07:24 +05:30
52 changed files with 25017 additions and 465 deletions

View File

@@ -13,3 +13,4 @@ CA/serial*
CA/newcerts/*.pem CA/newcerts/*.pem
CA/private/cakey.pem CA/private/cakey.pem
nova/vcsversion.py nova/vcsversion.py
*.DS_Store

View File

@@ -1,36 +1,43 @@
# Format is: # Format is:
# <preferred e-mail> <other e-mail> # <preferred e-mail> <other e-mail 1>
<code@term.ie> <github@anarkystic.com> # <preferred e-mail> <other e-mail 2>
<code@term.ie> <termie@preciousroy.local>
<Armando.Migliaccio@eu.citrix.com> <armando.migliaccio@citrix.com>
<matt.dietz@rackspace.com> <matthewdietz@Matthew-Dietzs-MacBook-Pro.local>
<matt.dietz@rackspace.com> <mdietz@openstack>
<cbehrens@codestud.com> <chris.behrens@rackspace.com>
<devin.carlen@gmail.com> <devcamcar@illian.local>
<ewan.mellor@citrix.com> <emellor@silver>
<jaypipes@gmail.com> <jpipes@serialcoder>
<anotherjesse@gmail.com> <jesse@dancelamb> <anotherjesse@gmail.com> <jesse@dancelamb>
<anotherjesse@gmail.com> <jesse@gigantor.local> <anotherjesse@gmail.com> <jesse@gigantor.local>
<anotherjesse@gmail.com> <jesse@ubuntu> <anotherjesse@gmail.com> <jesse@ubuntu>
<jmckenty@gmail.com> <jmckenty@yyj-dhcp171.corp.flock.com> <ant@openstack.org> <amesserl@rackspace.com>
<Armando.Migliaccio@eu.citrix.com> <armando.migliaccio@citrix.com>
<brian.lamar@rackspace.com> <brian.lamar@gmail.com>
<bschott@isi.edu> <bfschott@gmail.com>
<cbehrens@codestud.com> <chris.behrens@rackspace.com>
<chiradeep@cloud.com> <chiradeep@chiradeep-lt2>
<code@term.ie> <github@anarkystic.com>
<code@term.ie> <termie@preciousroy.local>
<corywright@gmail.com> <cory.wright@rackspace.com>
<devin.carlen@gmail.com> <devcamcar@illian.local>
<ewan.mellor@citrix.com> <emellor@silver>
<jaypipes@gmail.com> <jpipes@serialcoder>
<jmckenty@gmail.com> <jmckenty@joshua-mckentys-macbook-pro.local> <jmckenty@gmail.com> <jmckenty@joshua-mckentys-macbook-pro.local>
<jmckenty@gmail.com> <jmckenty@yyj-dhcp171.corp.flock.com>
<jmckenty@gmail.com> <joshua.mckenty@nasa.gov> <jmckenty@gmail.com> <joshua.mckenty@nasa.gov>
<justin@fathomdb.com> <justinsb@justinsb-desktop> <justin@fathomdb.com> <justinsb@justinsb-desktop>
<masumotok@nttdata.co.jp> <root@openstack2-api> <justin@fathomdb.com> <superstack@superstack.org>
<masumotok@nttdata.co.jp> Masumoto<masumotok@nttdata.co.jp> <masumotok@nttdata.co.jp> Masumoto<masumotok@nttdata.co.jp>
<masumotok@nttdata.co.jp> <root@openstack2-api>
<matt.dietz@rackspace.com> <matthewdietz@Matthew-Dietzs-MacBook-Pro.local>
<matt.dietz@rackspace.com> <mdietz@openstack>
<mordred@inaugust.com> <mordred@hudson> <mordred@inaugust.com> <mordred@hudson>
<paul@openstack.org> <pvoccio@castor.local>
<paul@openstack.org> <paul.voccio@rackspace.com> <paul@openstack.org> <paul.voccio@rackspace.com>
<paul@openstack.org> <pvoccio@castor.local>
<rconradharris@gmail.com> <rick.harris@rackspace.com>
<rlane@wikimedia.org> <laner@controller>
<sleepsonthefloor@gmail.com> <root@tonbuntu>
<soren.hansen@rackspace.com> <soren@linux2go.dk> <soren.hansen@rackspace.com> <soren@linux2go.dk>
<todd@ansolabs.com> <todd@lapex> <todd@ansolabs.com> <todd@lapex>
<todd@ansolabs.com> <todd@rubidine.com> <todd@ansolabs.com> <todd@rubidine.com>
<vishvananda@gmail.com> <vishvananda@yahoo.com> <tushar.vitthal.patil@gmail.com> <tpatil@vertex.co.in>
<ueno.nachi@lab.ntt.co.jp> <nati.ueno@gmail.com>
<ueno.nachi@lab.ntt.co.jp> <nova@u4>
<ueno.nachi@lab.ntt.co.jp> <openstack@lab.ntt.co.jp>
<vishvananda@gmail.com> <root@mirror.nasanebula.net> <vishvananda@gmail.com> <root@mirror.nasanebula.net>
<vishvananda@gmail.com> <root@ubuntu> <vishvananda@gmail.com> <root@ubuntu>
<sleepsonthefloor@gmail.com> <root@tonbuntu> <vishvananda@gmail.com> <vishvananda@yahoo.com>
<rlane@wikimedia.org> <laner@controller>
<rconradharris@gmail.com> <rick.harris@rackspace.com>
<corywright@gmail.com> <cory.wright@rackspace.com>
<ant@openstack.org> <amesserl@rackspace.com>
<chiradeep@cloud.com> <chiradeep@chiradeep-lt2>
<justin@fathomdb.com> <superstack@superstack.org>

12
Authors
View File

@@ -4,14 +4,16 @@ Anthony Young <sleepsonthefloor@gmail.com>
Antony Messerli <ant@openstack.org> Antony Messerli <ant@openstack.org>
Armando Migliaccio <Armando.Migliaccio@eu.citrix.com> Armando Migliaccio <Armando.Migliaccio@eu.citrix.com>
Bilal Akhtar <bilalakhtar@ubuntu.com> Bilal Akhtar <bilalakhtar@ubuntu.com>
Brian Schott <bschott@isi.edu> <bfschott@gmail.com> Brian Lamar <brian.lamar@rackspace.com>
Brian Schott <bschott@isi.edu>
Brian Waldon <brian.waldon@rackspace.com>
Chiradeep Vittal <chiradeep@cloud.com> Chiradeep Vittal <chiradeep@cloud.com>
Chmouel Boudjnah <chmouel@chmouel.com> Chmouel Boudjnah <chmouel@chmouel.com>
Chris Behrens <cbehrens@codestud.com> Chris Behrens <cbehrens@codestud.com>
Christian Berendt <berendt@b1-systems.de> Christian Berendt <berendt@b1-systems.de>
Cory Wright <corywright@gmail.com> Cory Wright <corywright@gmail.com>
David Pravec <David.Pravec@danix.org>
Dan Prince <dan.prince@rackspace.com> Dan Prince <dan.prince@rackspace.com>
David Pravec <David.Pravec@danix.org>
Dean Troyer <dtroyer@gmail.com> Dean Troyer <dtroyer@gmail.com>
Devin Carlen <devin.carlen@gmail.com> Devin Carlen <devin.carlen@gmail.com>
Ed Leafe <ed@leafe.com> Ed Leafe <ed@leafe.com>
@@ -34,6 +36,7 @@ Joshua McKenty <jmckenty@gmail.com>
Justin Santa Barbara <justin@fathomdb.com> Justin Santa Barbara <justin@fathomdb.com>
Kei Masumoto <masumotok@nttdata.co.jp> Kei Masumoto <masumotok@nttdata.co.jp>
Ken Pepple <ken.pepple@gmail.com> Ken Pepple <ken.pepple@gmail.com>
Kevin L. Mitchell <kevin.mitchell@rackspace.com>
Koji Iida <iida.koji@lab.ntt.co.jp> Koji Iida <iida.koji@lab.ntt.co.jp>
Lorin Hochstein <lorin@isi.edu> Lorin Hochstein <lorin@isi.edu>
Matt Dietz <matt.dietz@rackspace.com> Matt Dietz <matt.dietz@rackspace.com>
@@ -42,7 +45,8 @@ Monsyne Dragon <mdragon@rackspace.com>
Monty Taylor <mordred@inaugust.com> Monty Taylor <mordred@inaugust.com>
MORITA Kazutaka <morita.kazutaka@gmail.com> MORITA Kazutaka <morita.kazutaka@gmail.com>
Muneyuki Noguchi <noguchimn@nttdata.co.jp> Muneyuki Noguchi <noguchimn@nttdata.co.jp>
Nachi Ueno <ueno.nachi@lab.ntt.co.jp> <openstack@lab.ntt.co.jp> <nati.ueno@gmail.com> <nova@u4> Nachi Ueno <ueno.nachi@lab.ntt.co.jp>
Naveed Massjouni <naveed.massjouni@rackspace.com>
Paul Voccio <paul@openstack.org> Paul Voccio <paul@openstack.org>
Ricardo Carrillo Cruz <emaildericky@gmail.com> Ricardo Carrillo Cruz <emaildericky@gmail.com>
Rick Clark <rick@openstack.org> Rick Clark <rick@openstack.org>
@@ -57,7 +61,7 @@ Soren Hansen <soren.hansen@rackspace.com>
Thierry Carrez <thierry@openstack.org> Thierry Carrez <thierry@openstack.org>
Todd Willey <todd@ansolabs.com> Todd Willey <todd@ansolabs.com>
Trey Morris <trey.morris@rackspace.com> Trey Morris <trey.morris@rackspace.com>
Tushar Patil <tushar.vitthal.patil@gmail.com> <tpatil@vertex.co.in> Tushar Patil <tushar.vitthal.patil@gmail.com>
Vasiliy Shlykov <vash@vasiliyshlykov.org> Vasiliy Shlykov <vash@vasiliyshlykov.org>
Vishvananda Ishaya <vishvananda@gmail.com> Vishvananda Ishaya <vishvananda@gmail.com>
Youcef Laribi <Youcef.Laribi@eu.citrix.com> Youcef Laribi <Youcef.Laribi@eu.citrix.com>

View File

@@ -38,3 +38,4 @@ include nova/tests/db/nova.austin.sqlite
include plugins/xenapi/README include plugins/xenapi/README
include plugins/xenapi/etc/xapi.d/plugins/objectstore include plugins/xenapi/etc/xapi.d/plugins/objectstore
include plugins/xenapi/etc/xapi.d/plugins/pluginlib_nova.py include plugins/xenapi/etc/xapi.d/plugins/pluginlib_nova.py
global-exclude *.pyc

View File

@@ -25,7 +25,6 @@ from eventlet.green import urllib2
import exceptions import exceptions
import gettext import gettext
import logging
import os import os
import sys import sys
import time import time
@@ -48,9 +47,11 @@ from nova import utils
from nova import wsgi from nova import wsgi
FLAGS = flags.FLAGS FLAGS = flags.FLAGS
flags.DEFINE_integer('ajax_console_idle_timeout', 300, flags.DEFINE_integer('ajax_console_idle_timeout', 300,
'Seconds before idle connection destroyed') 'Seconds before idle connection destroyed')
flags.DEFINE_flag(flags.HelpFlag())
flags.DEFINE_flag(flags.HelpshortFlag())
flags.DEFINE_flag(flags.HelpXMLFlag())
LOG = logging.getLogger('nova.ajax_console_proxy') LOG = logging.getLogger('nova.ajax_console_proxy')
LOG.setLevel(logging.DEBUG) LOG.setLevel(logging.DEBUG)
@@ -62,10 +63,16 @@ class AjaxConsoleProxy(object):
def __call__(self, env, start_response): def __call__(self, env, start_response):
try: try:
req_url = '%s://%s%s?%s' % (env['wsgi.url_scheme'], if 'QUERY_STRING' in env:
env['HTTP_HOST'], req_url = '%s://%s%s?%s' % (env['wsgi.url_scheme'],
env['PATH_INFO'], env['HTTP_HOST'],
env['QUERY_STRING']) env['PATH_INFO'],
env['QUERY_STRING'])
else:
req_url = '%s://%s%s' % (env['wsgi.url_scheme'],
env['HTTP_HOST'],
env['PATH_INFO'])
if 'HTTP_REFERER' in env: if 'HTTP_REFERER' in env:
auth_url = env['HTTP_REFERER'] auth_url = env['HTTP_REFERER']
else: else:
@@ -130,6 +137,7 @@ class AjaxConsoleProxy(object):
if __name__ == '__main__': if __name__ == '__main__':
utils.default_flagfile() utils.default_flagfile()
FLAGS(sys.argv) FLAGS(sys.argv)
logging.setup()
server = wsgi.Server() server = wsgi.Server()
acp = AjaxConsoleProxy() acp = AjaxConsoleProxy()
acp.register_listeners() acp.register_listeners()

View File

@@ -36,14 +36,22 @@ gettext.install('nova', unicode=1)
from nova import flags from nova import flags
from nova import log as logging from nova import log as logging
from nova import utils
from nova import version from nova import version
from nova import wsgi from nova import wsgi
logging.basicConfig()
LOG = logging.getLogger('nova.api') LOG = logging.getLogger('nova.api')
LOG.setLevel(logging.DEBUG)
FLAGS = flags.FLAGS FLAGS = flags.FLAGS
flags.DEFINE_string('ec2_listen', "0.0.0.0",
'IP address for EC2 API to listen')
flags.DEFINE_integer('ec2_listen_port', 8773, 'port for ec2 api to listen')
flags.DEFINE_string('osapi_listen', "0.0.0.0",
'IP address for OpenStack API to listen')
flags.DEFINE_integer('osapi_listen_port', 8774, 'port for os api to listen')
flags.DEFINE_flag(flags.HelpFlag())
flags.DEFINE_flag(flags.HelpshortFlag())
flags.DEFINE_flag(flags.HelpXMLFlag())
API_ENDPOINTS = ['ec2', 'osapi'] API_ENDPOINTS = ['ec2', 'osapi']
@@ -57,21 +65,15 @@ def run_app(paste_config_file):
LOG.debug(_("No paste configuration for app: %s"), api) LOG.debug(_("No paste configuration for app: %s"), api)
continue continue
LOG.debug(_("App Config: %(api)s\n%(config)r") % locals()) LOG.debug(_("App Config: %(api)s\n%(config)r") % locals())
wsgi.paste_config_to_flags(config, {
"verbose": FLAGS.verbose,
"%s_host" % api: config.get('host', '0.0.0.0'),
"%s_port" % api: getattr(FLAGS, "%s_port" % api)})
LOG.info(_("Running %s API"), api) LOG.info(_("Running %s API"), api)
app = wsgi.load_paste_app(paste_config_file, api) app = wsgi.load_paste_app(paste_config_file, api)
apps.append((app, getattr(FLAGS, "%s_port" % api), apps.append((app, getattr(FLAGS, "%s_listen_port" % api),
getattr(FLAGS, "%s_host" % api))) getattr(FLAGS, "%s_listen" % api)))
if len(apps) == 0: if len(apps) == 0:
LOG.error(_("No known API applications configured in %s."), LOG.error(_("No known API applications configured in %s."),
paste_config_file) paste_config_file)
return return
# NOTE(todd): redo logging config, verbose could be set in paste config
logging.basicConfig()
server = wsgi.Server() server = wsgi.Server()
for app in apps: for app in apps:
server.start(*app) server.start(*app)
@@ -79,9 +81,15 @@ def run_app(paste_config_file):
if __name__ == '__main__': if __name__ == '__main__':
utils.default_flagfile()
FLAGS(sys.argv) FLAGS(sys.argv)
logging.setup()
LOG.audit(_("Starting nova-api node (version %s)"), LOG.audit(_("Starting nova-api node (version %s)"),
version.version_string_with_vcs()) version.version_string_with_vcs())
LOG.debug(_("Full set of FLAGS:"))
for flag in FLAGS:
flag_get = FLAGS.get(flag, None)
LOG.debug("%(flag)s : %(flag_get)s" % locals())
conf = wsgi.paste_config_file('nova-api.conf') conf = wsgi.paste_config_file('nova-api.conf')
if conf: if conf:
run_app(conf) run_app(conf)

View File

@@ -1,80 +0,0 @@
#!/usr/bin/env python
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2010 United States Government as represented by the
# Administrator of the National Aeronautics and Space Administration.
# 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.
"""Combined starter script for Nova services."""
import eventlet
eventlet.monkey_patch()
import gettext
import os
import sys
# If ../nova/__init__.py exists, add ../ to Python search path, so that
# it will override what happens to be installed in /usr/(local/)lib/python...
possible_topdir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]),
os.pardir,
os.pardir))
if os.path.exists(os.path.join(possible_topdir, 'nova', '__init__.py')):
sys.path.insert(0, possible_topdir)
gettext.install('nova', unicode=1)
from nova import flags
from nova import log as logging
from nova import service
from nova import utils
from nova import wsgi
FLAGS = flags.FLAGS
if __name__ == '__main__':
utils.default_flagfile()
FLAGS(sys.argv)
logging.basicConfig()
compute = service.Service.create(binary='nova-compute')
network = service.Service.create(binary='nova-network')
volume = service.Service.create(binary='nova-volume')
scheduler = service.Service.create(binary='nova-scheduler')
#objectstore = service.Service.create(binary='nova-objectstore')
service.serve(compute, network, volume, scheduler)
apps = []
paste_config_file = wsgi.paste_config_file('nova-api.conf')
for api in ['osapi', 'ec2']:
config = wsgi.load_paste_configuration(paste_config_file, api)
if config is None:
continue
wsgi.paste_config_to_flags(config, {
"verbose": FLAGS.verbose,
"%s_host" % api: config.get('host', '0.0.0.0'),
"%s_port" % api: getattr(FLAGS, "%s_port" % api)})
app = wsgi.load_paste_app(paste_config_file, api)
apps.append((app, getattr(FLAGS, "%s_port" % api),
getattr(FLAGS, "%s_host" % api)))
if len(apps) > 0:
logging.basicConfig()
server = wsgi.Server()
for app in apps:
server.start(*app)
server.wait()

View File

@@ -36,10 +36,14 @@ if os.path.exists(os.path.join(possible_topdir, 'nova', '__init__.py')):
gettext.install('nova', unicode=1) gettext.install('nova', unicode=1)
from nova import flags
from nova import log as logging
from nova import service from nova import service
from nova import utils from nova import utils
if __name__ == '__main__': if __name__ == '__main__':
utils.default_flagfile() utils.default_flagfile()
flags.FLAGS(sys.argv)
logging.setup()
service.serve() service.serve()
service.wait() service.wait()

View File

@@ -35,10 +35,14 @@ if os.path.exists(os.path.join(possible_topdir, 'nova', '__init__.py')):
gettext.install('nova', unicode=1) gettext.install('nova', unicode=1)
from nova import flags
from nova import log as logging
from nova import service from nova import service
from nova import utils from nova import utils
if __name__ == '__main__': if __name__ == '__main__':
utils.default_flagfile() utils.default_flagfile()
flags.FLAGS(sys.argv)
logging.setup()
service.serve() service.serve()
service.wait() service.wait()

View File

@@ -102,19 +102,10 @@ def main():
flagfile = os.environ.get('FLAGFILE', FLAGS.dhcpbridge_flagfile) flagfile = os.environ.get('FLAGFILE', FLAGS.dhcpbridge_flagfile)
utils.default_flagfile(flagfile) utils.default_flagfile(flagfile)
argv = FLAGS(sys.argv) argv = FLAGS(sys.argv)
logging.basicConfig() logging.setup()
interface = os.environ.get('DNSMASQ_INTERFACE', 'br0') interface = os.environ.get('DNSMASQ_INTERFACE', 'br0')
if int(os.environ.get('TESTING', '0')): if int(os.environ.get('TESTING', '0')):
FLAGS.fake_rabbit = True from nova.tests import fake_flags
FLAGS.network_size = 16
FLAGS.connection_type = 'fake'
FLAGS.fake_network = True
FLAGS.auth_driver = 'nova.auth.dbdriver.DbDriver'
FLAGS.num_networks = 5
path = os.path.abspath(os.path.join(os.path.dirname(__file__),
'..',
'nova.sqlite'))
FLAGS.sql_connection = 'sqlite:///%s' % path
action = argv[1] action = argv[1]
if action in ['add', 'del', 'old']: if action in ['add', 'del', 'old']:
mac = argv[2] mac = argv[2]

View File

@@ -35,6 +35,7 @@ if os.path.exists(os.path.join(possible_topdir, 'nova', '__init__.py')):
gettext.install('nova', unicode=1) gettext.install('nova', unicode=1)
from nova import flags from nova import flags
from nova import log as logging
from nova import utils from nova import utils
from nova import wsgi from nova import wsgi
from nova.api import direct from nova.api import direct
@@ -44,10 +45,15 @@ from nova.compute import api as compute_api
FLAGS = flags.FLAGS FLAGS = flags.FLAGS
flags.DEFINE_integer('direct_port', 8001, 'Direct API port') flags.DEFINE_integer('direct_port', 8001, 'Direct API port')
flags.DEFINE_string('direct_host', '0.0.0.0', 'Direct API host') flags.DEFINE_string('direct_host', '0.0.0.0', 'Direct API host')
flags.DEFINE_flag(flags.HelpFlag())
flags.DEFINE_flag(flags.HelpshortFlag())
flags.DEFINE_flag(flags.HelpXMLFlag())
if __name__ == '__main__': if __name__ == '__main__':
utils.default_flagfile() utils.default_flagfile()
FLAGS(sys.argv) FLAGS(sys.argv)
logging.setup()
direct.register_service('compute', compute_api.API()) direct.register_service('compute', compute_api.API())
direct.register_service('reflect', direct.Reflection()) direct.register_service('reflect', direct.Reflection())

View File

@@ -41,6 +41,7 @@ if os.path.exists(os.path.join(possible_topdir, 'nova', '__init__.py')):
gettext.install('nova', unicode=1) gettext.install('nova', unicode=1)
from nova import flags from nova import flags
from nova import log as logging
from nova import utils from nova import utils
from nova.objectstore import image from nova.objectstore import image
@@ -92,6 +93,7 @@ def main():
"""Main entry point.""" """Main entry point."""
utils.default_flagfile() utils.default_flagfile()
argv = FLAGS(sys.argv) argv = FLAGS(sys.argv)
logging.setup()
images = get_images() images = get_images()
if len(argv) == 2: if len(argv) == 2:

View File

@@ -41,9 +41,6 @@ from nova import utils
from nova import twistd from nova import twistd
from nova.compute import monitor from nova.compute import monitor
# TODO(todd): shouldn't this be done with flags? And what about verbose?
logging.getLogger('boto').setLevel(logging.WARN)
LOG = logging.getLogger('nova.instancemonitor') LOG = logging.getLogger('nova.instancemonitor')

View File

@@ -86,8 +86,6 @@ from nova.auth import manager
from nova.cloudpipe import pipelib from nova.cloudpipe import pipelib
from nova.db import migration from nova.db import migration
logging.basicConfig()
FLAGS = flags.FLAGS FLAGS = flags.FLAGS
flags.DECLARE('fixed_range', 'nova.network.manager') flags.DECLARE('fixed_range', 'nova.network.manager')
flags.DECLARE('num_networks', 'nova.network.manager') flags.DECLARE('num_networks', 'nova.network.manager')
@@ -95,6 +93,9 @@ flags.DECLARE('network_size', 'nova.network.manager')
flags.DECLARE('vlan_start', 'nova.network.manager') flags.DECLARE('vlan_start', 'nova.network.manager')
flags.DECLARE('vpn_start', 'nova.network.manager') flags.DECLARE('vpn_start', 'nova.network.manager')
flags.DECLARE('fixed_range_v6', 'nova.network.manager') flags.DECLARE('fixed_range_v6', 'nova.network.manager')
flags.DEFINE_flag(flags.HelpFlag())
flags.DEFINE_flag(flags.HelpshortFlag())
flags.DEFINE_flag(flags.HelpXMLFlag())
def param2id(object_id): def param2id(object_id):
@@ -433,6 +434,37 @@ class ProjectCommands(object):
"nova-api server on this host.") "nova-api server on this host.")
class FixedIpCommands(object):
"""Class for managing fixed ip."""
def list(self, host=None):
"""Lists all fixed ips (optionally by host) arguments: [host]"""
ctxt = context.get_admin_context()
if host == None:
fixed_ips = db.fixed_ip_get_all(ctxt)
else:
fixed_ips = db.fixed_ip_get_all_by_host(ctxt, host)
print "%-18s\t%-15s\t%-17s\t%-15s\t%s" % (_('network'),
_('IP address'),
_('MAC address'),
_('hostname'),
_('host'))
for fixed_ip in fixed_ips:
hostname = None
host = None
mac_address = None
if fixed_ip['instance']:
instance = fixed_ip['instance']
hostname = instance['hostname']
host = instance['host']
mac_address = instance['mac_address']
print "%-18s\t%-15s\t%-17s\t%-15s\t%s" % (
fixed_ip['network']['cidr'],
fixed_ip['address'],
mac_address, hostname, host)
class FloatingIpCommands(object): class FloatingIpCommands(object):
"""Class for managing floating ip.""" """Class for managing floating ip."""
@@ -472,8 +504,8 @@ class NetworkCommands(object):
"""Class for managing networks.""" """Class for managing networks."""
def create(self, fixed_range=None, num_networks=None, def create(self, fixed_range=None, num_networks=None,
network_size=None, vlan_start=None, vpn_start=None, network_size=None, vlan_start=None,
fixed_range_v6=None): vpn_start=None, fixed_range_v6=None, label='public'):
"""Creates fixed ips for host by range """Creates fixed ips for host by range
arguments: [fixed_range=FLAG], [num_networks=FLAG], arguments: [fixed_range=FLAG], [num_networks=FLAG],
[network_size=FLAG], [vlan_start=FLAG], [network_size=FLAG], [vlan_start=FLAG],
@@ -495,9 +527,22 @@ class NetworkCommands(object):
cidr=fixed_range, cidr=fixed_range,
num_networks=int(num_networks), num_networks=int(num_networks),
network_size=int(network_size), network_size=int(network_size),
cidr_v6=fixed_range_v6,
vlan_start=int(vlan_start), vlan_start=int(vlan_start),
vpn_start=int(vpn_start)) vpn_start=int(vpn_start),
cidr_v6=fixed_range_v6,
label=label)
def list(self):
"""List all created networks"""
print "%-18s\t%-15s\t%-15s\t%-15s" % (_('network'),
_('netmask'),
_('start address'),
'DNS')
for network in db.network_get_all(context.get_admin_context()):
print "%-18s\t%-15s\t%-15s\t%-15s" % (network.cidr,
network.netmask,
network.dhcp_start,
network.dns)
class ServiceCommands(object): class ServiceCommands(object):
@@ -508,7 +553,7 @@ class ServiceCommands(object):
args: [host] [service]""" args: [host] [service]"""
ctxt = context.get_admin_context() ctxt = context.get_admin_context()
now = datetime.datetime.utcnow() now = datetime.datetime.utcnow()
services = db.service_get_all(ctxt) services = db.service_get_all(ctxt) + db.service_get_all(ctxt, True)
if host: if host:
services = [s for s in services if s['host'] == host] services = [s for s in services if s['host'] == host]
if service: if service:
@@ -622,6 +667,7 @@ CATEGORIES = [
('role', RoleCommands), ('role', RoleCommands),
('shell', ShellCommands), ('shell', ShellCommands),
('vpn', VpnCommands), ('vpn', VpnCommands),
('fixed', FixedIpCommands),
('floating', FloatingIpCommands), ('floating', FloatingIpCommands),
('network', NetworkCommands), ('network', NetworkCommands),
('service', ServiceCommands), ('service', ServiceCommands),
@@ -665,6 +711,7 @@ def main():
"""Parse options and call the appropriate class/method.""" """Parse options and call the appropriate class/method."""
utils.default_flagfile() utils.default_flagfile()
argv = FLAGS(sys.argv) argv = FLAGS(sys.argv)
logging.setup()
script_name = argv.pop(0) script_name = argv.pop(0)
if len(argv) < 1: if len(argv) < 1:

View File

@@ -36,10 +36,14 @@ if os.path.exists(os.path.join(possible_topdir, 'nova', '__init__.py')):
gettext.install('nova', unicode=1) gettext.install('nova', unicode=1)
from nova import flags
from nova import log as logging
from nova import service from nova import service
from nova import utils from nova import utils
if __name__ == '__main__': if __name__ == '__main__':
utils.default_flagfile() utils.default_flagfile()
flags.FLAGS(sys.argv)
logging.setup()
service.serve() service.serve()
service.wait() service.wait()

View File

@@ -36,10 +36,14 @@ if os.path.exists(os.path.join(possible_topdir, 'nova', '__init__.py')):
gettext.install('nova', unicode=1) gettext.install('nova', unicode=1)
from nova import flags
from nova import log as logging
from nova import service from nova import service
from nova import utils from nova import utils
if __name__ == '__main__': if __name__ == '__main__':
utils.default_flagfile() utils.default_flagfile()
flags.FLAGS(sys.argv)
logging.setup()
service.serve() service.serve()
service.wait() service.wait()

View File

@@ -36,10 +36,14 @@ if os.path.exists(os.path.join(possible_topdir, 'nova', '__init__.py')):
gettext.install('nova', unicode=1) gettext.install('nova', unicode=1)
from nova import flags
from nova import log as logging
from nova import service from nova import service
from nova import utils from nova import utils
if __name__ == '__main__': if __name__ == '__main__':
utils.default_flagfile() utils.default_flagfile()
flags.FLAGS(sys.argv)
logging.setup()
service.serve() service.serve()
service.wait() service.wait()

View File

@@ -23,6 +23,8 @@ import base64
import boto import boto
import boto.exception import boto.exception
import httplib import httplib
import re
import string
from boto.ec2.regioninfo import RegionInfo from boto.ec2.regioninfo import RegionInfo
@@ -165,19 +167,20 @@ class HostInfo(object):
**Fields Include** **Fields Include**
* Disk stats * Hostname
* Running Instances * Compute service status
* Memory stats * Volume service status
* CPU stats * Instance count
* Network address info * Volume count
* Firewall info
* Bridge and devices
""" """
def __init__(self, connection=None): def __init__(self, connection=None):
self.connection = connection self.connection = connection
self.hostname = None self.hostname = None
self.compute = None
self.volume = None
self.instance_count = 0
self.volume_count = 0
def __repr__(self): def __repr__(self):
return 'Host:%s' % self.hostname return 'Host:%s' % self.hostname
@@ -188,7 +191,39 @@ class HostInfo(object):
# this is needed by the sax parser, so ignore the ugly name # this is needed by the sax parser, so ignore the ugly name
def endElement(self, name, value, connection): def endElement(self, name, value, connection):
setattr(self, name, value) fixed_name = string.lower(re.sub(r'([A-Z])', r'_\1', name))
setattr(self, fixed_name, value)
class Vpn(object):
"""
Information about a Vpn, as parsed through SAX
**Fields Include**
* instance_id
* project_id
* public_ip
* public_port
* created_at
* internal_ip
* state
"""
def __init__(self, connection=None):
self.connection = connection
self.instance_id = None
self.project_id = None
def __repr__(self):
return 'Vpn:%s:%s' % (self.project_id, self.instance_id)
def startElement(self, name, attrs, connection):
return None
def endElement(self, name, value, connection):
fixed_name = string.lower(re.sub(r'([A-Z])', r'_\1', name))
setattr(self, fixed_name, value)
class InstanceType(object): class InstanceType(object):
@@ -422,6 +457,16 @@ class NovaAdminClient(object):
zip = self.apiconn.get_object('GenerateX509ForUser', params, UserInfo) zip = self.apiconn.get_object('GenerateX509ForUser', params, UserInfo)
return zip.file return zip.file
def start_vpn(self, project):
"""
Starts the vpn for a user
"""
return self.apiconn.get_object('StartVpn', {'Project': project}, Vpn)
def get_vpns(self):
"""Return a list of vpn with project name"""
return self.apiconn.get_list('DescribeVpns', {}, [('item', Vpn)])
def get_hosts(self): def get_hosts(self):
return self.apiconn.get_list('DescribeHosts', {}, [('item', HostInfo)]) return self.apiconn.get_list('DescribeHosts', {}, [('item', HostInfo)])

View File

@@ -10,7 +10,6 @@ export NOVA_CERT=${NOVA_KEY_DIR}/%(nova)s
export EUCALYPTUS_CERT=${NOVA_CERT} # euca-bundle-image seems to require this set export EUCALYPTUS_CERT=${NOVA_CERT} # euca-bundle-image seems to require this set
alias ec2-bundle-image="ec2-bundle-image --cert ${EC2_CERT} --privatekey ${EC2_PRIVATE_KEY} --user 42 --ec2cert ${NOVA_CERT}" alias ec2-bundle-image="ec2-bundle-image --cert ${EC2_CERT} --privatekey ${EC2_PRIVATE_KEY} --user 42 --ec2cert ${NOVA_CERT}"
alias ec2-upload-bundle="ec2-upload-bundle -a ${EC2_ACCESS_KEY} -s ${EC2_SECRET_KEY} --url ${S3_URL} --ec2cert ${NOVA_CERT}" alias ec2-upload-bundle="ec2-upload-bundle -a ${EC2_ACCESS_KEY} -s ${EC2_SECRET_KEY} --url ${S3_URL} --ec2cert ${NOVA_CERT}"
export CLOUD_SERVERS_API_KEY="%(access)s" export NOVA_API_KEY="%(access)s"
export CLOUD_SERVERS_USERNAME="%(user)s" export NOVA_USERNAME="%(user)s"
export CLOUD_SERVERS_URL="%(os)s" export NOVA_URL="%(os)s"

View File

@@ -160,9 +160,45 @@ class StrWrapper(object):
raise KeyError(name) raise KeyError(name)
FLAGS = FlagValues() # Copied from gflags with small mods to get the naming correct.
gflags.FLAGS = FLAGS # Originally gflags checks for the first module that is not gflags that is
gflags.DEFINE_flag(gflags.HelpFlag(), FLAGS) # in the call chain, we want to check for the first module that is not gflags
# and not this module.
def _GetCallingModule():
"""Returns the name of the module that's calling into this module.
We generally use this function to get the name of the module calling a
DEFINE_foo... function.
"""
# Walk down the stack to find the first globals dict that's not ours.
for depth in range(1, sys.getrecursionlimit()):
if not sys._getframe(depth).f_globals is globals():
module_name = __GetModuleName(sys._getframe(depth).f_globals)
if module_name == 'gflags':
continue
if module_name is not None:
return module_name
raise AssertionError("No module was found")
# Copied from gflags because it is a private function
def __GetModuleName(globals_dict):
"""Given a globals dict, returns the name of the module that defines it.
Args:
globals_dict: A dictionary that should correspond to an environment
providing the values of the globals.
Returns:
A string (the name of the module) or None (if the module could not
be identified.
"""
for name, module in sys.modules.iteritems():
if getattr(module, '__dict__', None) is globals_dict:
if name == '__main__':
return sys.argv[0]
return name
return None
def _wrapper(func): def _wrapper(func):
@@ -173,6 +209,11 @@ def _wrapper(func):
return _wrapped return _wrapped
FLAGS = FlagValues()
gflags.FLAGS = FLAGS
gflags._GetCallingModule = _GetCallingModule
DEFINE = _wrapper(gflags.DEFINE) DEFINE = _wrapper(gflags.DEFINE)
DEFINE_string = _wrapper(gflags.DEFINE_string) DEFINE_string = _wrapper(gflags.DEFINE_string)
DEFINE_integer = _wrapper(gflags.DEFINE_integer) DEFINE_integer = _wrapper(gflags.DEFINE_integer)
@@ -185,8 +226,6 @@ DEFINE_spaceseplist = _wrapper(gflags.DEFINE_spaceseplist)
DEFINE_multistring = _wrapper(gflags.DEFINE_multistring) DEFINE_multistring = _wrapper(gflags.DEFINE_multistring)
DEFINE_multi_int = _wrapper(gflags.DEFINE_multi_int) DEFINE_multi_int = _wrapper(gflags.DEFINE_multi_int)
DEFINE_flag = _wrapper(gflags.DEFINE_flag) DEFINE_flag = _wrapper(gflags.DEFINE_flag)
HelpFlag = gflags.HelpFlag HelpFlag = gflags.HelpFlag
HelpshortFlag = gflags.HelpshortFlag HelpshortFlag = gflags.HelpshortFlag
HelpXMLFlag = gflags.HelpXMLFlag HelpXMLFlag = gflags.HelpXMLFlag
@@ -285,8 +324,9 @@ DEFINE_string('state_path', os.path.join(os.path.dirname(__file__), '../'),
DEFINE_string('logdir', None, 'output to a per-service log file in named ' DEFINE_string('logdir', None, 'output to a per-service log file in named '
'directory') 'directory')
DEFINE_string('sqlite_db', 'nova.sqlite', 'file name for sqlite')
DEFINE_string('sql_connection', DEFINE_string('sql_connection',
'sqlite:///$state_path/nova.sqlite', 'sqlite:///$state_path/$sqlite_db',
'connection string for sql database') 'connection string for sql database')
DEFINE_integer('sql_idle_timeout', DEFINE_integer('sql_idle_timeout',
3600, 3600,

View File

@@ -54,7 +54,7 @@ flags.DEFINE_string('logging_default_format_string',
'format string to use for log messages without context') 'format string to use for log messages without context')
flags.DEFINE_string('logging_debug_format_suffix', flags.DEFINE_string('logging_debug_format_suffix',
'from %(processName)s (pid=%(process)d) %(funcName)s' 'from (pid=%(process)d) %(funcName)s'
' %(pathname)s:%(lineno)d', ' %(pathname)s:%(lineno)d',
'data to append to log format when level is DEBUG') 'data to append to log format when level is DEBUG')
@@ -65,6 +65,7 @@ flags.DEFINE_string('logging_exception_prefix',
flags.DEFINE_list('default_log_levels', flags.DEFINE_list('default_log_levels',
['amqplib=WARN', ['amqplib=WARN',
'sqlalchemy=WARN', 'sqlalchemy=WARN',
'boto=WARN',
'eventlet.wsgi.server=WARN'], 'eventlet.wsgi.server=WARN'],
'list of logger=LEVEL pairs') 'list of logger=LEVEL pairs')
@@ -94,7 +95,7 @@ critical = logging.critical
log = logging.log log = logging.log
# handlers # handlers
StreamHandler = logging.StreamHandler StreamHandler = logging.StreamHandler
RotatingFileHandler = logging.handlers.RotatingFileHandler WatchedFileHandler = logging.handlers.WatchedFileHandler
# logging.SysLogHandler is nicer than logging.logging.handler.SysLogHandler. # logging.SysLogHandler is nicer than logging.logging.handler.SysLogHandler.
SysLogHandler = logging.handlers.SysLogHandler SysLogHandler = logging.handlers.SysLogHandler
@@ -117,7 +118,7 @@ def _get_binary_name():
return os.path.basename(inspect.stack()[-1][1]) return os.path.basename(inspect.stack()[-1][1])
def get_log_file_path(binary=None): def _get_log_file_path(binary=None):
if FLAGS.logfile: if FLAGS.logfile:
return FLAGS.logfile return FLAGS.logfile
if FLAGS.logdir: if FLAGS.logdir:
@@ -125,25 +126,6 @@ def get_log_file_path(binary=None):
return '%s.log' % (os.path.join(FLAGS.logdir, binary),) return '%s.log' % (os.path.join(FLAGS.logdir, binary),)
def basicConfig():
logging.basicConfig()
for handler in logging.root.handlers:
handler.setFormatter(_formatter)
if FLAGS.verbose:
logging.root.setLevel(logging.DEBUG)
else:
logging.root.setLevel(logging.INFO)
if FLAGS.use_syslog:
syslog = SysLogHandler(address='/dev/log')
syslog.setFormatter(_formatter)
logging.root.addHandler(syslog)
logpath = get_log_file_path()
if logpath:
logfile = RotatingFileHandler(logpath)
logfile.setFormatter(_formatter)
logging.root.addHandler(logfile)
class NovaLogger(logging.Logger): class NovaLogger(logging.Logger):
""" """
NovaLogger manages request context and formatting. NovaLogger manages request context and formatting.
@@ -151,23 +133,19 @@ class NovaLogger(logging.Logger):
This becomes the class that is instanciated by logging.getLogger. This becomes the class that is instanciated by logging.getLogger.
""" """
def __init__(self, name, level=NOTSET): def __init__(self, name, level=NOTSET):
level_name = self._get_level_from_flags(name, FLAGS)
level = globals()[level_name]
logging.Logger.__init__(self, name, level) logging.Logger.__init__(self, name, level)
self.setup_from_flags()
def _get_level_from_flags(self, name, FLAGS): def setup_from_flags(self):
# if exactly "nova", or a child logger, honor the verbose flag """Setup logger from flags"""
if (name == "nova" or name.startswith("nova.")) and FLAGS.verbose: level = NOTSET
return 'DEBUG'
for pair in FLAGS.default_log_levels: for pair in FLAGS.default_log_levels:
logger, _sep, level = pair.partition('=') logger, _sep, level_name = pair.partition('=')
# NOTE(todd): if we set a.b, we want a.b.c to have the same level # NOTE(todd): if we set a.b, we want a.b.c to have the same level
# (but not a.bc, so we check the dot) # (but not a.bc, so we check the dot)
if name == logger: if self.name == logger or self.name.startswith("%s." % logger):
return level level = globals()[level_name]
if name.startswith(logger) and name[len(logger)] == '.': self.setLevel(level)
return level
return 'INFO'
def _log(self, level, msg, args, exc_info=None, extra=None, context=None): def _log(self, level, msg, args, exc_info=None, extra=None, context=None):
"""Extract context from any log call""" """Extract context from any log call"""
@@ -176,12 +154,12 @@ class NovaLogger(logging.Logger):
if context: if context:
extra.update(_dictify_context(context)) extra.update(_dictify_context(context))
extra.update({"nova_version": version.version_string_with_vcs()}) extra.update({"nova_version": version.version_string_with_vcs()})
logging.Logger._log(self, level, msg, args, exc_info, extra) return logging.Logger._log(self, level, msg, args, exc_info, extra)
def addHandler(self, handler): def addHandler(self, handler):
"""Each handler gets our custom formatter""" """Each handler gets our custom formatter"""
handler.setFormatter(_formatter) handler.setFormatter(_formatter)
logging.Logger.addHandler(self, handler) return logging.Logger.addHandler(self, handler)
def audit(self, msg, *args, **kwargs): def audit(self, msg, *args, **kwargs):
"""Shortcut for our AUDIT level""" """Shortcut for our AUDIT level"""
@@ -208,23 +186,6 @@ class NovaLogger(logging.Logger):
self.error(message, **kwargs) self.error(message, **kwargs)
def handle_exception(type, value, tb):
logging.root.critical(str(value), exc_info=(type, value, tb))
sys.excepthook = handle_exception
logging.setLoggerClass(NovaLogger)
class NovaRootLogger(NovaLogger):
pass
if not isinstance(logging.root, NovaRootLogger):
logging.root = NovaRootLogger("nova.root", WARNING)
NovaLogger.root = logging.root
NovaLogger.manager.root = logging.root
class NovaFormatter(logging.Formatter): class NovaFormatter(logging.Formatter):
""" """
A nova.context.RequestContext aware formatter configured through flags. A nova.context.RequestContext aware formatter configured through flags.
@@ -271,8 +232,73 @@ class NovaFormatter(logging.Formatter):
_formatter = NovaFormatter() _formatter = NovaFormatter()
class NovaRootLogger(NovaLogger):
def __init__(self, name, level=NOTSET):
self.logpath = None
self.filelog = None
self.streamlog = StreamHandler()
self.syslog = None
NovaLogger.__init__(self, name, level)
def setup_from_flags(self):
"""Setup logger from flags"""
global _filelog
if FLAGS.use_syslog:
self.syslog = SysLogHandler(address='/dev/log')
self.addHandler(self.syslog)
elif self.syslog:
self.removeHandler(self.syslog)
logpath = _get_log_file_path()
if logpath:
self.removeHandler(self.streamlog)
if logpath != self.logpath:
self.removeHandler(self.filelog)
self.filelog = WatchedFileHandler(logpath)
self.addHandler(self.filelog)
self.logpath = logpath
else:
self.removeHandler(self.filelog)
self.addHandler(self.streamlog)
if FLAGS.verbose:
self.setLevel(DEBUG)
else:
self.setLevel(INFO)
def handle_exception(type, value, tb):
logging.root.critical(str(value), exc_info=(type, value, tb))
def reset():
"""Resets logging handlers. Should be called if FLAGS changes."""
for logger in NovaLogger.manager.loggerDict.itervalues():
if isinstance(logger, NovaLogger):
logger.setup_from_flags()
def setup():
"""Setup nova logging."""
if not isinstance(logging.root, NovaRootLogger):
logging._acquireLock()
for handler in logging.root.handlers:
logging.root.removeHandler(handler)
logging.root = NovaRootLogger("nova")
NovaLogger.root = logging.root
NovaLogger.manager.root = logging.root
for logger in NovaLogger.manager.loggerDict.itervalues():
logger.root = logging.root
if isinstance(logger, logging.Logger):
NovaLogger.manager._fixupParents(logger)
NovaLogger.manager.loggerDict["nova"] = logging.root
logging._releaseLock()
sys.excepthook = handle_exception
reset()
root = logging.root
logging.setLoggerClass(NovaLogger)
def audit(msg, *args, **kwargs): def audit(msg, *args, **kwargs):
"""Shortcut for logging to root log with sevrity 'AUDIT'.""" """Shortcut for logging to root log with sevrity 'AUDIT'."""
if len(logging.root.handlers) == 0:
basicConfig()
logging.root.log(AUDIT, msg, *args, **kwargs) logging.root.log(AUDIT, msg, *args, **kwargs)

View File

@@ -91,18 +91,19 @@ class Consumer(messaging.Consumer):
super(Consumer, self).__init__(*args, **kwargs) super(Consumer, self).__init__(*args, **kwargs)
self.failed_connection = False self.failed_connection = False
break break
except: # Catching all because carrot sucks except Exception as e: # Catching all because carrot sucks
fl_host = FLAGS.rabbit_host fl_host = FLAGS.rabbit_host
fl_port = FLAGS.rabbit_port fl_port = FLAGS.rabbit_port
fl_intv = FLAGS.rabbit_retry_interval fl_intv = FLAGS.rabbit_retry_interval
LOG.exception(_("AMQP server on %(fl_host)s:%(fl_port)d is" LOG.error(_("AMQP server on %(fl_host)s:%(fl_port)d is"
" unreachable. Trying again in %(fl_intv)d seconds.") " unreachable: %(e)s. Trying again in %(fl_intv)d"
" seconds.")
% locals()) % locals())
self.failed_connection = True self.failed_connection = True
if self.failed_connection: if self.failed_connection:
LOG.exception(_("Unable to connect to AMQP server " LOG.error(_("Unable to connect to AMQP server "
"after %d tries. Shutting down."), "after %d tries. Shutting down."),
FLAGS.rabbit_max_retries) FLAGS.rabbit_max_retries)
sys.exit(1) sys.exit(1)
def fetch(self, no_ack=None, auto_ack=None, enable_callbacks=False): def fetch(self, no_ack=None, auto_ack=None, enable_callbacks=False):

View File

@@ -29,8 +29,8 @@ FLAGS.auth_driver = 'nova.auth.dbdriver.DbDriver'
flags.DECLARE('network_size', 'nova.network.manager') flags.DECLARE('network_size', 'nova.network.manager')
flags.DECLARE('num_networks', 'nova.network.manager') flags.DECLARE('num_networks', 'nova.network.manager')
flags.DECLARE('fake_network', 'nova.network.manager') flags.DECLARE('fake_network', 'nova.network.manager')
FLAGS.network_size = 16 FLAGS.network_size = 8
FLAGS.num_networks = 5 FLAGS.num_networks = 2
FLAGS.fake_network = True FLAGS.fake_network = True
flags.DECLARE('num_shelves', 'nova.volume.driver') flags.DECLARE('num_shelves', 'nova.volume.driver')
flags.DECLARE('blades_per_shelf', 'nova.volume.driver') flags.DECLARE('blades_per_shelf', 'nova.volume.driver')
@@ -39,5 +39,5 @@ FLAGS.num_shelves = 2
FLAGS.blades_per_shelf = 4 FLAGS.blades_per_shelf = 4
FLAGS.iscsi_num_targets = 8 FLAGS.iscsi_num_targets = 8
FLAGS.verbose = True FLAGS.verbose = True
FLAGS.sql_connection = 'sqlite:///nova.sqlite' FLAGS.sqlite_db = "tests.sqlite"
FLAGS.use_ipv6 = True FLAGS.use_ipv6 = True

View File

@@ -311,4 +311,5 @@ class S3APITestCase(test.TestCase):
self.auth_manager.delete_user('admin') self.auth_manager.delete_user('admin')
self.auth_manager.delete_project('admin') self.auth_manager.delete_project('admin')
stop_listening = defer.maybeDeferred(self.listening_port.stopListening) stop_listening = defer.maybeDeferred(self.listening_port.stopListening)
super(S3APITestCase, self).tearDown()
return defer.DeferredList([stop_listening]) return defer.DeferredList([stop_listening])

View File

@@ -20,6 +20,7 @@
import boto import boto
from boto.ec2 import regioninfo from boto.ec2 import regioninfo
import datetime
import httplib import httplib
import random import random
import StringIO import StringIO
@@ -127,6 +128,28 @@ class ApiEc2TestCase(test.TestCase):
self.ec2.new_http_connection(host, is_secure).AndReturn(self.http) self.ec2.new_http_connection(host, is_secure).AndReturn(self.http)
return self.http return self.http
def test_return_valid_isoformat(self):
"""
Ensure that the ec2 api returns datetime in xs:dateTime
(which apparently isn't datetime.isoformat())
NOTE(ken-pepple): https://bugs.launchpad.net/nova/+bug/721297
"""
conv = apirequest._database_to_isoformat
# sqlite database representation with microseconds
time_to_convert = datetime.datetime.strptime(
"2011-02-21 20:14:10.634276",
"%Y-%m-%d %H:%M:%S.%f")
self.assertEqual(
conv(time_to_convert),
'2011-02-21T20:14:10Z')
# mysqlite database representation
time_to_convert = datetime.datetime.strptime(
"2011-02-21 19:56:18",
"%Y-%m-%d %H:%M:%S")
self.assertEqual(
conv(time_to_convert),
'2011-02-21T19:56:18Z')
def test_xmlns_version_matches_request_version(self): def test_xmlns_version_matches_request_version(self):
self.expect_http(api_version='2010-10-30') self.expect_http(api_version='2010-10-30')
self.mox.ReplayAll() self.mox.ReplayAll()

View File

@@ -327,15 +327,6 @@ class AuthManagerTestCase(object):
class AuthManagerLdapTestCase(AuthManagerTestCase, test.TestCase): class AuthManagerLdapTestCase(AuthManagerTestCase, test.TestCase):
auth_driver = 'nova.auth.ldapdriver.FakeLdapDriver' auth_driver = 'nova.auth.ldapdriver.FakeLdapDriver'
def __init__(self, *args, **kwargs):
AuthManagerTestCase.__init__(self)
test.TestCase.__init__(self, *args, **kwargs)
import nova.auth.fakeldap as fakeldap
if FLAGS.flush_db:
LOG.info("Flushing datastore")
r = fakeldap.Store.instance()
r.flushdb()
class AuthManagerDbTestCase(AuthManagerTestCase, test.TestCase): class AuthManagerDbTestCase(AuthManagerTestCase, test.TestCase):
auth_driver = 'nova.auth.dbdriver.DbDriver' auth_driver = 'nova.auth.dbdriver.DbDriver'

View File

@@ -65,18 +65,21 @@ class CloudTestCase(test.TestCase):
self.cloud = cloud.CloudController() self.cloud = cloud.CloudController()
# set up services # set up services
self.compute = service.Service.create(binary='nova-compute') self.compute = self.start_service('compute')
self.compute.start() self.scheduter = self.start_service('scheduler')
self.network = service.Service.create(binary='nova-network') self.network = self.start_service('network')
self.network.start()
self.manager = manager.AuthManager() self.manager = manager.AuthManager()
self.user = self.manager.create_user('admin', 'admin', 'admin', True) self.user = self.manager.create_user('admin', 'admin', 'admin', True)
self.project = self.manager.create_project('proj', 'admin', 'proj') self.project = self.manager.create_project('proj', 'admin', 'proj')
self.context = context.RequestContext(user=self.user, self.context = context.RequestContext(user=self.user,
project=self.project) project=self.project)
host = self.network.get_network_host(self.context.elevated())
def tearDown(self): def tearDown(self):
network_ref = db.project_get_network(self.context,
self.project.id)
db.network_disassociate(self.context, network_ref['id'])
self.manager.delete_project(self.project) self.manager.delete_project(self.project)
self.manager.delete_user(self.user) self.manager.delete_user(self.user)
self.compute.kill() self.compute.kill()
@@ -102,7 +105,7 @@ class CloudTestCase(test.TestCase):
address = "10.10.10.10" address = "10.10.10.10"
db.floating_ip_create(self.context, db.floating_ip_create(self.context,
{'address': address, {'address': address,
'host': FLAGS.host}) 'host': self.network.host})
self.cloud.allocate_address(self.context) self.cloud.allocate_address(self.context)
self.cloud.describe_addresses(self.context) self.cloud.describe_addresses(self.context)
self.cloud.release_address(self.context, self.cloud.release_address(self.context,
@@ -115,9 +118,9 @@ class CloudTestCase(test.TestCase):
address = "10.10.10.10" address = "10.10.10.10"
db.floating_ip_create(self.context, db.floating_ip_create(self.context,
{'address': address, {'address': address,
'host': FLAGS.host}) 'host': self.network.host})
self.cloud.allocate_address(self.context) self.cloud.allocate_address(self.context)
inst = db.instance_create(self.context, {'host': FLAGS.host}) inst = db.instance_create(self.context, {'host': self.compute.host})
fixed = self.network.allocate_fixed_ip(self.context, inst['id']) fixed = self.network.allocate_fixed_ip(self.context, inst['id'])
ec2_id = cloud.id_to_ec2_id(inst['id']) ec2_id = cloud.id_to_ec2_id(inst['id'])
self.cloud.associate_address(self.context, self.cloud.associate_address(self.context,
@@ -133,6 +136,22 @@ class CloudTestCase(test.TestCase):
db.instance_destroy(self.context, inst['id']) db.instance_destroy(self.context, inst['id'])
db.floating_ip_destroy(self.context, address) db.floating_ip_destroy(self.context, address)
def test_describe_security_groups(self):
"""Makes sure describe_security_groups works and filters results."""
sec = db.security_group_create(self.context,
{'project_id': self.context.project_id,
'name': 'test'})
result = self.cloud.describe_security_groups(self.context)
# NOTE(vish): should have the default group as well
self.assertEqual(len(result['securityGroupInfo']), 2)
result = self.cloud.describe_security_groups(self.context,
group_name=[sec['name']])
self.assertEqual(len(result['securityGroupInfo']), 1)
self.assertEqual(
result['securityGroupInfo'][0]['groupName'],
sec['name'])
db.security_group_destroy(self.context, sec['id'])
def test_describe_volumes(self): def test_describe_volumes(self):
"""Makes sure describe_volumes works and filters results.""" """Makes sure describe_volumes works and filters results."""
vol1 = db.volume_create(self.context, {}) vol1 = db.volume_create(self.context, {})
@@ -203,27 +222,32 @@ class CloudTestCase(test.TestCase):
'instance_type': instance_type, 'instance_type': instance_type,
'max_count': max_count} 'max_count': max_count}
rv = self.cloud.run_instances(self.context, **kwargs) rv = self.cloud.run_instances(self.context, **kwargs)
greenthread.sleep(0.3)
instance_id = rv['instancesSet'][0]['instanceId'] instance_id = rv['instancesSet'][0]['instanceId']
output = self.cloud.get_console_output(context=self.context, output = self.cloud.get_console_output(context=self.context,
instance_id=[instance_id]) instance_id=[instance_id])
self.assertEquals(b64decode(output['output']), 'FAKE CONSOLE OUTPUT') self.assertEquals(b64decode(output['output']), 'FAKE CONSOLE OUTPUT')
# TODO(soren): We need this until we can stop polling in the rpc code # TODO(soren): We need this until we can stop polling in the rpc code
# for unit tests. # for unit tests.
greenthread.sleep(0.3) greenthread.sleep(0.3)
rv = self.cloud.terminate_instances(self.context, [instance_id]) rv = self.cloud.terminate_instances(self.context, [instance_id])
greenthread.sleep(0.3)
def test_ajax_console(self): def test_ajax_console(self):
image_id = FLAGS.default_image
kwargs = {'image_id': image_id} kwargs = {'image_id': image_id}
rv = yield self.cloud.run_instances(self.context, **kwargs) rv = self.cloud.run_instances(self.context, **kwargs)
instance_id = rv['instancesSet'][0]['instanceId'] instance_id = rv['instancesSet'][0]['instanceId']
output = yield self.cloud.get_console_output(context=self.context, greenthread.sleep(0.3)
instance_id=[instance_id]) output = self.cloud.get_ajax_console(context=self.context,
self.assertEquals(b64decode(output['output']), instance_id=[instance_id])
'http://fakeajaxconsole.com/?token=FAKETOKEN') self.assertEquals(output['url'],
'%s/?token=FAKETOKEN' % FLAGS.ajax_console_proxy_url)
# TODO(soren): We need this until we can stop polling in the rpc code # TODO(soren): We need this until we can stop polling in the rpc code
# for unit tests. # for unit tests.
greenthread.sleep(0.3) greenthread.sleep(0.3)
rv = yield self.cloud.terminate_instances(self.context, [instance_id]) rv = self.cloud.terminate_instances(self.context, [instance_id])
greenthread.sleep(0.3)
def test_key_generation(self): def test_key_generation(self):
result = self._create_key('test') result = self._create_key('test')
@@ -286,70 +310,6 @@ class CloudTestCase(test.TestCase):
LOG.debug(_("Terminating instance %s"), instance_id) LOG.debug(_("Terminating instance %s"), instance_id)
rv = self.compute.terminate_instance(instance_id) rv = self.compute.terminate_instance(instance_id)
def test_describe_instances(self):
"""Makes sure describe_instances works."""
instance1 = db.instance_create(self.context, {'host': 'host2'})
comp1 = db.service_create(self.context, {'host': 'host2',
'availability_zone': 'zone1',
'topic': "compute"})
result = self.cloud.describe_instances(self.context)
self.assertEqual(result['reservationSet'][0]
['instancesSet'][0]
['placement']['availabilityZone'], 'zone1')
db.instance_destroy(self.context, instance1['id'])
db.service_destroy(self.context, comp1['id'])
def test_instance_update_state(self):
# TODO(termie): what is this code even testing?
def instance(num):
return {
'reservation_id': 'r-1',
'instance_id': 'i-%s' % num,
'image_id': 'ami-%s' % num,
'private_dns_name': '10.0.0.%s' % num,
'dns_name': '10.0.0%s' % num,
'ami_launch_index': str(num),
'instance_type': 'fake',
'availability_zone': 'fake',
'key_name': None,
'kernel_id': 'fake',
'ramdisk_id': 'fake',
'groups': ['default'],
'product_codes': None,
'state': 0x01,
'user_data': ''}
rv = self.cloud._format_describe_instances(self.context)
logging.error(str(rv))
self.assertEqual(len(rv['reservationSet']), 0)
# simulate launch of 5 instances
# self.cloud.instances['pending'] = {}
#for i in xrange(5):
# inst = instance(i)
# self.cloud.instances['pending'][inst['instance_id']] = inst
#rv = self.cloud._format_instances(self.admin)
#self.assert_(len(rv['reservationSet']) == 1)
#self.assert_(len(rv['reservationSet'][0]['instances_set']) == 5)
# report 4 nodes each having 1 of the instances
#for i in xrange(4):
# self.cloud.update_state('instances',
# {('node-%s' % i): {('i-%s' % i):
# instance(i)}})
# one instance should be pending still
#self.assert_(len(self.cloud.instances['pending'].keys()) == 1)
# check that the reservations collapse
#rv = self.cloud._format_instances(self.admin)
#self.assert_(len(rv['reservationSet']) == 1)
#self.assert_(len(rv['reservationSet'][0]['instances_set']) == 5)
# check that we can get metadata for each instance
#for i in xrange(4):
# data = self.cloud.get_metadata(instance(i)['private_dns_name'])
# self.assert_(data['meta-data']['ami-id'] == 'ami-%s' % i)
@staticmethod @staticmethod
def _fake_set_image_description(ctxt, image_id, description): def _fake_set_image_description(ctxt, image_id, description):
from nova.objectstore import handler from nova.objectstore import handler

View File

@@ -202,6 +202,14 @@ class ComputeTestCase(test.TestCase):
self.compute.set_admin_password(self.context, instance_id) self.compute.set_admin_password(self.context, instance_id)
self.compute.terminate_instance(self.context, instance_id) self.compute.terminate_instance(self.context, instance_id)
def test_inject_file(self):
"""Ensure we can write a file to an instance"""
instance_id = self._create_instance()
self.compute.run_instance(self.context, instance_id)
self.compute.inject_file(self.context, instance_id, "/tmp/test",
"File Contents")
self.compute.terminate_instance(self.context, instance_id)
def test_snapshot(self): def test_snapshot(self):
"""Ensure instance can be snapshotted""" """Ensure instance can be snapshotted"""
instance_id = self._create_instance() instance_id = self._create_instance()

View File

@@ -21,7 +21,6 @@ Tests For Console proxy.
""" """
import datetime import datetime
import logging
from nova import context from nova import context
from nova import db from nova import db
@@ -38,7 +37,6 @@ FLAGS = flags.FLAGS
class ConsoleTestCase(test.TestCase): class ConsoleTestCase(test.TestCase):
"""Test case for console proxy""" """Test case for console proxy"""
def setUp(self): def setUp(self):
logging.getLogger().setLevel(logging.DEBUG)
super(ConsoleTestCase, self).setUp() super(ConsoleTestCase, self).setUp()
self.flags(console_driver='nova.console.fake.FakeConsoleProxy', self.flags(console_driver='nova.console.fake.FakeConsoleProxy',
stub_compute=True) stub_compute=True)

View File

@@ -19,7 +19,6 @@
"""Tests for Direct API.""" """Tests for Direct API."""
import json import json
import logging
import webob import webob
@@ -53,6 +52,7 @@ class DirectTestCase(test.TestCase):
def tearDown(self): def tearDown(self):
direct.ROUTES = {} direct.ROUTES = {}
super(DirectTestCase, self).tearDown()
def test_delegated_auth(self): def test_delegated_auth(self):
req = webob.Request.blank('/fake/context') req = webob.Request.blank('/fake/context')

View File

@@ -15,7 +15,6 @@
# under the License. # under the License.
import glob import glob
import logging
import os import os
import re import re
import sys import sys

View File

@@ -1,9 +1,12 @@
import cStringIO import cStringIO
from nova import context from nova import context
from nova import flags
from nova import log from nova import log
from nova import test from nova import test
FLAGS = flags.FLAGS
def _fake_context(): def _fake_context():
return context.RequestContext(1, 1) return context.RequestContext(1, 1)
@@ -14,15 +17,11 @@ class RootLoggerTestCase(test.TestCase):
super(RootLoggerTestCase, self).setUp() super(RootLoggerTestCase, self).setUp()
self.log = log.logging.root self.log = log.logging.root
def tearDown(self):
super(RootLoggerTestCase, self).tearDown()
log.NovaLogger.manager.loggerDict = {}
def test_is_nova_instance(self): def test_is_nova_instance(self):
self.assert_(isinstance(self.log, log.NovaLogger)) self.assert_(isinstance(self.log, log.NovaLogger))
def test_name_is_nova_root(self): def test_name_is_nova(self):
self.assertEqual("nova.root", self.log.name) self.assertEqual("nova", self.log.name)
def test_handlers_have_nova_formatter(self): def test_handlers_have_nova_formatter(self):
formatters = [] formatters = []
@@ -45,25 +44,36 @@ class RootLoggerTestCase(test.TestCase):
log.audit("foo", context=_fake_context()) log.audit("foo", context=_fake_context())
self.assert_(True) # didn't raise exception self.assert_(True) # didn't raise exception
def test_will_be_verbose_if_verbose_flag_set(self):
self.flags(verbose=True)
log.reset()
self.assertEqual(log.DEBUG, self.log.level)
def test_will_not_be_verbose_if_verbose_flag_not_set(self):
self.flags(verbose=False)
log.reset()
self.assertEqual(log.INFO, self.log.level)
class LogHandlerTestCase(test.TestCase): class LogHandlerTestCase(test.TestCase):
def test_log_path_logdir(self): def test_log_path_logdir(self):
self.flags(logdir='/some/path') self.flags(logdir='/some/path', logfile=None)
self.assertEquals(log.get_log_file_path(binary='foo-bar'), self.assertEquals(log._get_log_file_path(binary='foo-bar'),
'/some/path/foo-bar.log') '/some/path/foo-bar.log')
def test_log_path_logfile(self): def test_log_path_logfile(self):
self.flags(logfile='/some/path/foo-bar.log') self.flags(logfile='/some/path/foo-bar.log')
self.assertEquals(log.get_log_file_path(binary='foo-bar'), self.assertEquals(log._get_log_file_path(binary='foo-bar'),
'/some/path/foo-bar.log') '/some/path/foo-bar.log')
def test_log_path_none(self): def test_log_path_none(self):
self.assertTrue(log.get_log_file_path(binary='foo-bar') is None) self.flags(logdir=None, logfile=None)
self.assertTrue(log._get_log_file_path(binary='foo-bar') is None)
def test_log_path_logfile_overrides_logdir(self): def test_log_path_logfile_overrides_logdir(self):
self.flags(logdir='/some/other/path', self.flags(logdir='/some/other/path',
logfile='/some/path/foo-bar.log') logfile='/some/path/foo-bar.log')
self.assertEquals(log.get_log_file_path(binary='foo-bar'), self.assertEquals(log._get_log_file_path(binary='foo-bar'),
'/some/path/foo-bar.log') '/some/path/foo-bar.log')
@@ -76,13 +86,15 @@ class NovaFormatterTestCase(test.TestCase):
logging_debug_format_suffix="--DBG") logging_debug_format_suffix="--DBG")
self.log = log.logging.root self.log = log.logging.root
self.stream = cStringIO.StringIO() self.stream = cStringIO.StringIO()
handler = log.StreamHandler(self.stream) self.handler = log.StreamHandler(self.stream)
self.log.addHandler(handler) self.log.addHandler(self.handler)
self.level = self.log.level
self.log.setLevel(log.DEBUG) self.log.setLevel(log.DEBUG)
def tearDown(self): def tearDown(self):
self.log.setLevel(self.level)
self.log.removeHandler(self.handler)
super(NovaFormatterTestCase, self).tearDown() super(NovaFormatterTestCase, self).tearDown()
log.NovaLogger.manager.loggerDict = {}
def test_uncontextualized_log(self): def test_uncontextualized_log(self):
self.log.info("foo") self.log.info("foo")
@@ -102,30 +114,15 @@ class NovaFormatterTestCase(test.TestCase):
class NovaLoggerTestCase(test.TestCase): class NovaLoggerTestCase(test.TestCase):
def setUp(self): def setUp(self):
super(NovaLoggerTestCase, self).setUp() super(NovaLoggerTestCase, self).setUp()
self.flags(default_log_levels=["nova-test=AUDIT"], verbose=False) levels = FLAGS.default_log_levels
levels.append("nova-test=AUDIT")
self.flags(default_log_levels=levels,
verbose=True)
self.log = log.getLogger('nova-test') self.log = log.getLogger('nova-test')
def tearDown(self):
super(NovaLoggerTestCase, self).tearDown()
log.NovaLogger.manager.loggerDict = {}
def test_has_level_from_flags(self): def test_has_level_from_flags(self):
self.assertEqual(log.AUDIT, self.log.level) self.assertEqual(log.AUDIT, self.log.level)
def test_child_log_has_level_of_parent_flag(self): def test_child_log_has_level_of_parent_flag(self):
l = log.getLogger('nova-test.foo') l = log.getLogger('nova-test.foo')
self.assertEqual(log.AUDIT, l.level) self.assertEqual(log.AUDIT, l.level)
class VerboseLoggerTestCase(test.TestCase):
def setUp(self):
super(VerboseLoggerTestCase, self).setUp()
self.flags(default_log_levels=["nova.test=AUDIT"], verbose=True)
self.log = log.getLogger('nova.test')
def tearDown(self):
super(VerboseLoggerTestCase, self).tearDown()
log.NovaLogger.manager.loggerDict = {}
def test_will_be_verbose_if_named_nova_and_verbose_flag_set(self):
self.assertEqual(log.DEBUG, self.log.level)

View File

@@ -46,6 +46,8 @@ class ProjectTestCase(test.TestCase):
missing = set() missing = set()
for contributor in contributors: for contributor in contributors:
if contributor == 'nova-core':
continue
if not contributor in authors_file: if not contributor in authors_file:
missing.add(contributor) missing.add(contributor)

View File

@@ -42,15 +42,13 @@ class NetworkTestCase(test.TestCase):
# flags in the corresponding section in nova-dhcpbridge # flags in the corresponding section in nova-dhcpbridge
self.flags(connection_type='fake', self.flags(connection_type='fake',
fake_call=True, fake_call=True,
fake_network=True, fake_network=True)
network_size=16,
num_networks=5)
self.manager = manager.AuthManager() self.manager = manager.AuthManager()
self.user = self.manager.create_user('netuser', 'netuser', 'netuser') self.user = self.manager.create_user('netuser', 'netuser', 'netuser')
self.projects = [] self.projects = []
self.network = utils.import_object(FLAGS.network_manager) self.network = utils.import_object(FLAGS.network_manager)
self.context = context.RequestContext(project=None, user=self.user) self.context = context.RequestContext(project=None, user=self.user)
for i in range(5): for i in range(FLAGS.num_networks):
name = 'project%s' % i name = 'project%s' % i
project = self.manager.create_project(name, 'netuser', name) project = self.manager.create_project(name, 'netuser', name)
self.projects.append(project) self.projects.append(project)
@@ -117,6 +115,9 @@ class NetworkTestCase(test.TestCase):
utils.to_global_ipv6( utils.to_global_ipv6(
network_ref['cidr_v6'], network_ref['cidr_v6'],
instance_ref['mac_address'])) instance_ref['mac_address']))
self._deallocate_address(0, address)
db.instance_destroy(context.get_admin_context(),
instance_ref['id'])
def test_public_network_association(self): def test_public_network_association(self):
"""Makes sure that we can allocaate a public ip""" """Makes sure that we can allocaate a public ip"""
@@ -192,7 +193,7 @@ class NetworkTestCase(test.TestCase):
first = self._create_address(0) first = self._create_address(0)
lease_ip(first) lease_ip(first)
instance_ids = [] instance_ids = []
for i in range(1, 5): for i in range(1, FLAGS.num_networks):
instance_ref = self._create_instance(i, mac=utils.generate_mac()) instance_ref = self._create_instance(i, mac=utils.generate_mac())
instance_ids.append(instance_ref['id']) instance_ids.append(instance_ref['id'])
address = self._create_address(i, instance_ref['id']) address = self._create_address(i, instance_ref['id'])

View File

@@ -150,6 +150,7 @@ class SimpleDriverTestCase(test.TestCase):
def tearDown(self): def tearDown(self):
self.manager.delete_user(self.user) self.manager.delete_user(self.user)
self.manager.delete_project(self.project) self.manager.delete_project(self.project)
super(SimpleDriverTestCase, self).tearDown()
def _create_instance(self, **kwargs): def _create_instance(self, **kwargs):
"""Create a test instance""" """Create a test instance"""
@@ -176,18 +177,8 @@ class SimpleDriverTestCase(test.TestCase):
def test_doesnt_report_disabled_hosts_as_up(self): def test_doesnt_report_disabled_hosts_as_up(self):
"""Ensures driver doesn't find hosts before they are enabled""" """Ensures driver doesn't find hosts before they are enabled"""
# NOTE(vish): constructing service without create method compute1 = self.start_service('compute', host='host1')
# because we are going to use it without queue compute2 = self.start_service('compute', host='host2')
compute1 = service.Service('host1',
'nova-compute',
'compute',
FLAGS.compute_manager)
compute1.start()
compute2 = service.Service('host2',
'nova-compute',
'compute',
FLAGS.compute_manager)
compute2.start()
s1 = db.service_get_by_args(self.context, 'host1', 'nova-compute') s1 = db.service_get_by_args(self.context, 'host1', 'nova-compute')
s2 = db.service_get_by_args(self.context, 'host2', 'nova-compute') s2 = db.service_get_by_args(self.context, 'host2', 'nova-compute')
db.service_update(self.context, s1['id'], {'disabled': True}) db.service_update(self.context, s1['id'], {'disabled': True})
@@ -199,18 +190,8 @@ class SimpleDriverTestCase(test.TestCase):
def test_reports_enabled_hosts_as_up(self): def test_reports_enabled_hosts_as_up(self):
"""Ensures driver can find the hosts that are up""" """Ensures driver can find the hosts that are up"""
# NOTE(vish): constructing service without create method compute1 = self.start_service('compute', host='host1')
# because we are going to use it without queue compute2 = self.start_service('compute', host='host2')
compute1 = service.Service('host1',
'nova-compute',
'compute',
FLAGS.compute_manager)
compute1.start()
compute2 = service.Service('host2',
'nova-compute',
'compute',
FLAGS.compute_manager)
compute2.start()
hosts = self.scheduler.driver.hosts_up(self.context, 'compute') hosts = self.scheduler.driver.hosts_up(self.context, 'compute')
self.assertEqual(2, len(hosts)) self.assertEqual(2, len(hosts))
compute1.kill() compute1.kill()
@@ -218,16 +199,8 @@ class SimpleDriverTestCase(test.TestCase):
def test_least_busy_host_gets_instance(self): def test_least_busy_host_gets_instance(self):
"""Ensures the host with less cores gets the next one""" """Ensures the host with less cores gets the next one"""
compute1 = service.Service('host1', compute1 = self.start_service('compute', host='host1')
'nova-compute', compute2 = self.start_service('compute', host='host2')
'compute',
FLAGS.compute_manager)
compute1.start()
compute2 = service.Service('host2',
'nova-compute',
'compute',
FLAGS.compute_manager)
compute2.start()
instance_id1 = self._create_instance() instance_id1 = self._create_instance()
compute1.run_instance(self.context, instance_id1) compute1.run_instance(self.context, instance_id1)
instance_id2 = self._create_instance() instance_id2 = self._create_instance()
@@ -241,16 +214,8 @@ class SimpleDriverTestCase(test.TestCase):
def test_specific_host_gets_instance(self): def test_specific_host_gets_instance(self):
"""Ensures if you set availability_zone it launches on that zone""" """Ensures if you set availability_zone it launches on that zone"""
compute1 = service.Service('host1', compute1 = self.start_service('compute', host='host1')
'nova-compute', compute2 = self.start_service('compute', host='host2')
'compute',
FLAGS.compute_manager)
compute1.start()
compute2 = service.Service('host2',
'nova-compute',
'compute',
FLAGS.compute_manager)
compute2.start()
instance_id1 = self._create_instance() instance_id1 = self._create_instance()
compute1.run_instance(self.context, instance_id1) compute1.run_instance(self.context, instance_id1)
instance_id2 = self._create_instance(availability_zone='nova:host1') instance_id2 = self._create_instance(availability_zone='nova:host1')
@@ -263,11 +228,7 @@ class SimpleDriverTestCase(test.TestCase):
compute2.kill() compute2.kill()
def test_wont_sechedule_if_specified_host_is_down(self): def test_wont_sechedule_if_specified_host_is_down(self):
compute1 = service.Service('host1', compute1 = self.start_service('compute', host='host1')
'nova-compute',
'compute',
FLAGS.compute_manager)
compute1.start()
s1 = db.service_get_by_args(self.context, 'host1', 'nova-compute') s1 = db.service_get_by_args(self.context, 'host1', 'nova-compute')
now = datetime.datetime.utcnow() now = datetime.datetime.utcnow()
delta = datetime.timedelta(seconds=FLAGS.service_down_time * 2) delta = datetime.timedelta(seconds=FLAGS.service_down_time * 2)
@@ -282,11 +243,7 @@ class SimpleDriverTestCase(test.TestCase):
compute1.kill() compute1.kill()
def test_will_schedule_on_disabled_host_if_specified(self): def test_will_schedule_on_disabled_host_if_specified(self):
compute1 = service.Service('host1', compute1 = self.start_service('compute', host='host1')
'nova-compute',
'compute',
FLAGS.compute_manager)
compute1.start()
s1 = db.service_get_by_args(self.context, 'host1', 'nova-compute') s1 = db.service_get_by_args(self.context, 'host1', 'nova-compute')
db.service_update(self.context, s1['id'], {'disabled': True}) db.service_update(self.context, s1['id'], {'disabled': True})
instance_id2 = self._create_instance(availability_zone='nova:host1') instance_id2 = self._create_instance(availability_zone='nova:host1')
@@ -298,16 +255,8 @@ class SimpleDriverTestCase(test.TestCase):
def test_too_many_cores(self): def test_too_many_cores(self):
"""Ensures we don't go over max cores""" """Ensures we don't go over max cores"""
compute1 = service.Service('host1', compute1 = self.start_service('compute', host='host1')
'nova-compute', compute2 = self.start_service('compute', host='host2')
'compute',
FLAGS.compute_manager)
compute1.start()
compute2 = service.Service('host2',
'nova-compute',
'compute',
FLAGS.compute_manager)
compute2.start()
instance_ids1 = [] instance_ids1 = []
instance_ids2 = [] instance_ids2 = []
for index in xrange(FLAGS.max_cores): for index in xrange(FLAGS.max_cores):
@@ -322,6 +271,7 @@ class SimpleDriverTestCase(test.TestCase):
self.scheduler.driver.schedule_run_instance, self.scheduler.driver.schedule_run_instance,
self.context, self.context,
instance_id) instance_id)
db.instance_destroy(self.context, instance_id)
for instance_id in instance_ids1: for instance_id in instance_ids1:
compute1.terminate_instance(self.context, instance_id) compute1.terminate_instance(self.context, instance_id)
for instance_id in instance_ids2: for instance_id in instance_ids2:
@@ -331,16 +281,8 @@ class SimpleDriverTestCase(test.TestCase):
def test_least_busy_host_gets_volume(self): def test_least_busy_host_gets_volume(self):
"""Ensures the host with less gigabytes gets the next one""" """Ensures the host with less gigabytes gets the next one"""
volume1 = service.Service('host1', volume1 = self.start_service('volume', host='host1')
'nova-volume', volume2 = self.start_service('volume', host='host2')
'volume',
FLAGS.volume_manager)
volume1.start()
volume2 = service.Service('host2',
'nova-volume',
'volume',
FLAGS.volume_manager)
volume2.start()
volume_id1 = self._create_volume() volume_id1 = self._create_volume()
volume1.create_volume(self.context, volume_id1) volume1.create_volume(self.context, volume_id1)
volume_id2 = self._create_volume() volume_id2 = self._create_volume()
@@ -354,16 +296,8 @@ class SimpleDriverTestCase(test.TestCase):
def test_too_many_gigabytes(self): def test_too_many_gigabytes(self):
"""Ensures we don't go over max gigabytes""" """Ensures we don't go over max gigabytes"""
volume1 = service.Service('host1', volume1 = self.start_service('volume', host='host1')
'nova-volume', volume2 = self.start_service('volume', host='host2')
'volume',
FLAGS.volume_manager)
volume1.start()
volume2 = service.Service('host2',
'nova-volume',
'volume',
FLAGS.volume_manager)
volume2.start()
volume_ids1 = [] volume_ids1 = []
volume_ids2 = [] volume_ids2 = []
for index in xrange(FLAGS.max_gigabytes): for index in xrange(FLAGS.max_gigabytes):

View File

@@ -204,11 +204,12 @@ class LibvirtConnTestCase(test.TestCase):
conn = libvirt_conn.LibvirtConnection(True) conn = libvirt_conn.LibvirtConnection(True)
uri = conn.get_uri() uri = conn.get_uri()
self.assertEquals(uri, testuri) self.assertEquals(uri, testuri)
db.instance_destroy(user_context, instance_ref['id'])
def tearDown(self): def tearDown(self):
super(LibvirtConnTestCase, self).tearDown()
self.manager.delete_project(self.project) self.manager.delete_project(self.project)
self.manager.delete_user(self.user) self.manager.delete_user(self.user)
super(LibvirtConnTestCase, self).tearDown()
class IptablesFirewallTestCase(test.TestCase): class IptablesFirewallTestCase(test.TestCase):
@@ -365,6 +366,7 @@ class IptablesFirewallTestCase(test.TestCase):
'--dports 80:81 -j ACCEPT' % security_group_chain \ '--dports 80:81 -j ACCEPT' % security_group_chain \
in self.out_rules, in self.out_rules,
"TCP port 80/81 acceptance rule wasn't added") "TCP port 80/81 acceptance rule wasn't added")
db.instance_destroy(admin_ctxt, instance_ref['id'])
class NWFilterTestCase(test.TestCase): class NWFilterTestCase(test.TestCase):
@@ -388,6 +390,7 @@ class NWFilterTestCase(test.TestCase):
def tearDown(self): def tearDown(self):
self.manager.delete_project(self.project) self.manager.delete_project(self.project)
self.manager.delete_user(self.user) self.manager.delete_user(self.user)
super(NWFilterTestCase, self).tearDown()
def test_cidr_rule_nwfilter_xml(self): def test_cidr_rule_nwfilter_xml(self):
cloud_controller = cloud.CloudController() cloud_controller = cloud.CloudController()
@@ -514,3 +517,4 @@ class NWFilterTestCase(test.TestCase):
self.fw.apply_instance_filter(instance) self.fw.apply_instance_filter(instance)
_ensure_all_called() _ensure_all_called()
self.teardown_security_group() self.teardown_security_group()
db.instance_destroy(admin_ctxt, instance_ref['id'])

View File

@@ -32,6 +32,7 @@ from nova.virt import xenapi_conn
from nova.virt.xenapi import fake as xenapi_fake from nova.virt.xenapi import fake as xenapi_fake
from nova.virt.xenapi import volume_utils from nova.virt.xenapi import volume_utils
from nova.virt.xenapi.vmops import SimpleDH from nova.virt.xenapi.vmops import SimpleDH
from nova.virt.xenapi.vmops import VMOps
from nova.tests.db import fakes as db_fakes from nova.tests.db import fakes as db_fakes
from nova.tests.xenapi import stubs from nova.tests.xenapi import stubs
from nova.tests.glance import stubs as glance_stubs from nova.tests.glance import stubs as glance_stubs
@@ -141,6 +142,10 @@ class XenAPIVolumeTestCase(test.TestCase):
self.stubs.UnsetAll() self.stubs.UnsetAll()
def reset_network(*args):
pass
class XenAPIVMTestCase(test.TestCase): class XenAPIVMTestCase(test.TestCase):
""" """
Unit tests for VM operations Unit tests for VM operations
@@ -162,6 +167,8 @@ class XenAPIVMTestCase(test.TestCase):
stubs.stubout_session(self.stubs, stubs.FakeSessionForVMTests) stubs.stubout_session(self.stubs, stubs.FakeSessionForVMTests)
stubs.stubout_get_this_vm_uuid(self.stubs) stubs.stubout_get_this_vm_uuid(self.stubs)
stubs.stubout_stream_disk(self.stubs) stubs.stubout_stream_disk(self.stubs)
stubs.stubout_is_vdi_pv(self.stubs)
self.stubs.Set(VMOps, 'reset_network', reset_network)
glance_stubs.stubout_glance_client(self.stubs, glance_stubs.stubout_glance_client(self.stubs,
glance_stubs.FakeGlance) glance_stubs.FakeGlance)
self.conn = xenapi_conn.get_connection(False) self.conn = xenapi_conn.get_connection(False)

View File

@@ -130,6 +130,12 @@ def stubout_stream_disk(stubs):
stubs.Set(vm_utils, '_stream_disk', f) stubs.Set(vm_utils, '_stream_disk', f)
def stubout_is_vdi_pv(stubs):
def f(_1):
return False
stubs.Set(vm_utils, '_is_vdi_pv', f)
class FakeSessionForVMTests(fake.SessionBase): class FakeSessionForVMTests(fake.SessionBase):
""" Stubs out a XenAPISession for VM tests """ """ Stubs out a XenAPISession for VM tests """
def __init__(self, uri): def __init__(self, uri):

View File

@@ -148,6 +148,7 @@ def WrapTwistedOptions(wrapped):
options.insert(0, '') options.insert(0, '')
args = FLAGS(options) args = FLAGS(options)
logging.setup()
argv = args[1:] argv = args[1:]
# ignore subcommands # ignore subcommands
@@ -258,7 +259,6 @@ def serve(filename):
print 'usage: %s [options] [start|stop|restart]' % argv[0] print 'usage: %s [options] [start|stop|restart]' % argv[0]
sys.exit(1) sys.exit(1)
logging.basicConfig()
logging.debug(_("Full set of FLAGS:")) logging.debug(_("Full set of FLAGS:"))
for flag in FLAGS: for flag in FLAGS:
logging.debug("%s : %s" % (flag, FLAGS.get(flag, None))) logging.debug("%s : %s" % (flag, FLAGS.get(flag, None)))

2130
po/ast.po Normal file

File diff suppressed because it is too large Load Diff

2137
po/cs.po Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,21 +1,21 @@
# Translations template for nova. # Danish translation for nova
# Copyright (C) 2011 ORGANIZATION # Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011
# This file is distributed under the same license as the nova project. # This file is distributed under the same license as the nova package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2011. # FIRST AUTHOR <EMAIL@ADDRESS>, 2011.
# #
#, fuzzy
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: nova 2011.1\n" "Project-Id-Version: nova\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" "Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2011-01-10 11:25-0800\n" "POT-Creation-Date: 2011-01-10 11:25-0800\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: 2011-01-15 21:46+0000\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: Soren Hansen <soren@linux2go.dk>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: Danish <da@li.org>\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 0.9.4\n" "X-Launchpad-Export-Date: 2011-02-05 05:36+0000\n"
"X-Generator: Launchpad (build 12177)\n"
#: nova/crypto.py:46 #: nova/crypto.py:46
msgid "Filename of root CA" msgid "Filename of root CA"
@@ -23,7 +23,7 @@ msgstr ""
#: nova/crypto.py:49 #: nova/crypto.py:49
msgid "Filename of private key" msgid "Filename of private key"
msgstr "" msgstr "Filnavn for privatnøgle"
#: nova/crypto.py:51 #: nova/crypto.py:51
msgid "Filename of root Certificate Revokation List" msgid "Filename of root Certificate Revokation List"
@@ -283,8 +283,8 @@ msgstr ""
#: nova/api/ec2/__init__.py:142 #: nova/api/ec2/__init__.py:142
#, python-format #, python-format
msgid "" msgid ""
"Access key %s has had %d failed authentications and will be locked out " "Access key %s has had %d failed authentications and will be locked out for "
"for %d minutes." "%d minutes."
msgstr "" msgstr ""
#: nova/api/ec2/__init__.py:179 nova/objectstore/handler.py:140 #: nova/api/ec2/__init__.py:179 nova/objectstore/handler.py:140
@@ -805,7 +805,8 @@ msgstr ""
#: nova/compute/api.py:94 #: nova/compute/api.py:94
#, python-format #, python-format
msgid "Instance quota exceeded. You can only run %s more instances of this type." msgid ""
"Instance quota exceeded. You can only run %s more instances of this type."
msgstr "" msgstr ""
#: nova/compute/api.py:109 #: nova/compute/api.py:109
@@ -957,7 +958,8 @@ msgstr ""
#: nova/compute/manager.py:289 #: nova/compute/manager.py:289
#, python-format #, python-format
msgid "trying to snapshot a non-running instance: %s (state: %s excepted: %s)" msgid ""
"trying to snapshot a non-running instance: %s (state: %s excepted: %s)"
msgstr "" msgstr ""
#: nova/compute/manager.py:301 #: nova/compute/manager.py:301
@@ -1697,9 +1699,8 @@ msgstr ""
#: nova/virt/xenapi_conn.py:113 #: nova/virt/xenapi_conn.py:113
msgid "" msgid ""
"Must specify xenapi_connection_url, xenapi_connection_username " "Must specify xenapi_connection_url, xenapi_connection_username (optionally), "
"(optionally), and xenapi_connection_password to use " "and xenapi_connection_password to use connection_type=xenapi"
"connection_type=xenapi"
msgstr "" msgstr ""
#: nova/virt/xenapi_conn.py:263 #: nova/virt/xenapi_conn.py:263
@@ -1826,7 +1827,7 @@ msgstr ""
#: nova/virt/xenapi/vm_utils.py:290 #: nova/virt/xenapi/vm_utils.py:290
#, python-format #, python-format
msgid "PV Kernel in VDI:%s" msgid "PV Kernel in VDI:%d"
msgstr "" msgstr ""
#: nova/virt/xenapi/vm_utils.py:318 #: nova/virt/xenapi/vm_utils.py:318
@@ -2126,5 +2127,4 @@ msgstr ""
#: nova/volume/manager.py:129 #: nova/volume/manager.py:129
#, python-format #, python-format
msgid "volume %s: deleted successfully" msgid "volume %s: deleted successfully"
msgstr "" msgstr "bind %s: slettet"

2137
po/de.po Normal file

File diff suppressed because it is too large Load Diff

2177
po/es.po Normal file

File diff suppressed because it is too large Load Diff

2141
po/it.po Normal file

File diff suppressed because it is too large Load Diff

2143
po/ja.po Normal file

File diff suppressed because it is too large Load Diff

2847
po/nova.pot Normal file

File diff suppressed because it is too large Load Diff

2148
po/pt_BR.po Normal file

File diff suppressed because it is too large Load Diff

2138
po/ru.po Normal file

File diff suppressed because it is too large Load Diff

2135
po/uk.po Normal file

File diff suppressed because it is too large Load Diff

2135
po/zh_CN.po Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -17,26 +17,245 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
# Colorizer Code is borrowed from Twisted:
# Copyright (c) 2001-2010 Twisted Matrix Laboratories.
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
"""Unittest runner for Nova.
To run all tests
python run_tests.py
To run a single test:
python run_tests.py test_compute:ComputeTestCase.test_run_terminate
To run a single test module:
python run_tests.py test_compute
or
python run_tests.py api.test_wsgi
"""
import gettext import gettext
import os import os
import unittest import unittest
import sys import sys
from nose import config from nose import config
from nose import result
from nose import core from nose import core
from nose import result
from nova import log as logging from nova import log as logging
from nova.tests import fake_flags
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)
class NovaTestResult(result.TextTestResult): class NovaTestResult(result.TextTestResult):
def __init__(self, *args, **kw): def __init__(self, *args, **kw):
result.TextTestResult.__init__(self, *args, **kw) result.TextTestResult.__init__(self, *args, **kw)
self._last_case = None self._last_case = None
self.colorizer = None
# NOTE(vish): 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
def getDescription(self, test): def getDescription(self, test):
return str(test) return str(test)
# NOTE(vish): copied from unittest with edit to add color
def addSuccess(self, test):
unittest.TestResult.addSuccess(self, test)
if self.showAll:
self.colorizer.write("OK", 'green')
self.stream.writeln()
elif self.dots:
self.stream.write('.')
self.stream.flush()
# NOTE(vish): copied from unittest with edit to add color
def addFailure(self, test, err):
unittest.TestResult.addFailure(self, test, err)
if self.showAll:
self.colorizer.write("FAIL", 'red')
self.stream.writeln()
elif self.dots:
self.stream.write('F')
self.stream.flush()
# NOTE(vish): copied from nose 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.
"""
stream = getattr(self, 'stream', None)
ec, ev, tb = err
try:
exc_info = self._exc_info_to_string(err, test)
except TypeError:
# 2.3 compat
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.passed = 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:
if self.showAll:
self.colorizer.write("ERROR", 'red')
self.stream.writeln()
elif self.dots:
stream.write('E')
def startTest(self, test): def startTest(self, test):
unittest.TestResult.startTest(self, test) unittest.TestResult.startTest(self, test)
current_case = test.test.__class__.__name__ current_case = test.test.__class__.__name__
@@ -60,13 +279,24 @@ class NovaTestRunner(core.TextTestRunner):
if __name__ == '__main__': if __name__ == '__main__':
logging.basicConfig() logging.setup()
# If any argument looks like a test name but doesn't have "nova.tests" in
# front of it, automatically add that so we don't have to type as much
argv = []
for x in sys.argv:
if x.startswith('test_'):
argv.append('nova.tests.%s' % x)
else:
argv.append(x)
testdir = os.path.abspath(os.path.join("nova", "tests"))
c = config.Config(stream=sys.stdout, c = config.Config(stream=sys.stdout,
env=os.environ, env=os.environ,
verbosity=3, verbosity=3,
workingDir=testdir,
plugins=core.DefaultPluginManager()) plugins=core.DefaultPluginManager())
runner = NovaTestRunner(stream=c.stream, runner = NovaTestRunner(stream=c.stream,
verbosity=c.verbosity, verbosity=c.verbosity,
config=c) config=c)
sys.exit(not core.run(config=c, testRunner=runner)) sys.exit(not core.run(config=c, testRunner=runner, argv=argv))