summaryrefslogtreecommitdiffstats
path: root/nova
diff options
context:
space:
mode:
authorArmando Migliaccio <armando.migliaccio@citrix.com>2010-11-25 10:46:58 +0000
committerArmando Migliaccio <armando.migliaccio@citrix.com>2010-11-25 10:46:58 +0000
commit71c358e69c80cbeb349db94be20a4c8cf2222276 (patch)
treed1b01edb17014af89ccbe9e7031824eb114fc417 /nova
parent9f722a0bcdb987c228f4ebf1e42c904a26d0ef73 (diff)
parent07ee9639a105a58b8b212fff607f4e0639d411da (diff)
small conflict resolution
Diffstat (limited to 'nova')
-rw-r--r--nova/adminclient.py16
-rw-r--r--nova/api/__init__.py1
-rw-r--r--nova/compute/monitor.py4
-rw-r--r--nova/flags.py4
-rw-r--r--nova/objectstore/handler.py4
-rw-r--r--nova/rpc.py27
-rw-r--r--nova/server.py4
-rw-r--r--nova/tests/misc_unittest.py48
-rw-r--r--nova/twistd.py4
-rw-r--r--nova/utils.py18
-rw-r--r--nova/virt/xenapi.py34
-rw-r--r--nova/wsgi.py2
12 files changed, 145 insertions, 21 deletions
diff --git a/nova/adminclient.py b/nova/adminclient.py
index af55197fc..5a62cce7d 100644
--- a/nova/adminclient.py
+++ b/nova/adminclient.py
@@ -22,13 +22,15 @@ Nova User API client library.
import base64
import boto
import httplib
+
+from nova import flags
from boto.ec2.regioninfo import RegionInfo
+FLAGS = flags.FLAGS
+
DEFAULT_CLC_URL = 'http://127.0.0.1:8773'
DEFAULT_REGION = 'nova'
-DEFAULT_ACCESS_KEY = 'admin'
-DEFAULT_SECRET_KEY = 'admin'
class UserInfo(object):
@@ -192,9 +194,13 @@ class HostInfo(object):
class NovaAdminClient(object):
- def __init__(self, clc_url=DEFAULT_CLC_URL, region=DEFAULT_REGION,
- access_key=DEFAULT_ACCESS_KEY, secret_key=DEFAULT_SECRET_KEY,
- **kwargs):
+ def __init__(
+ self,
+ clc_url=DEFAULT_CLC_URL,
+ region=DEFAULT_REGION,
+ access_key=FLAGS.aws_access_key_id,
+ secret_key=FLAGS.aws_secret_access_key,
+ **kwargs):
parts = self.split_clc_url(clc_url)
self.clc_url = clc_url
diff --git a/nova/api/__init__.py b/nova/api/__init__.py
index 7e75445a8..80f9f2109 100644
--- a/nova/api/__init__.py
+++ b/nova/api/__init__.py
@@ -22,7 +22,6 @@ Root WSGI middleware for all API controllers.
:osapi_subdomain: subdomain running the OpenStack API (default: api)
:ec2api_subdomain: subdomain running the EC2 API (default: ec2)
-:FAKE_subdomain: set to 'api' or 'ec2', requests default to that endpoint
"""
diff --git a/nova/compute/monitor.py b/nova/compute/monitor.py
index d0154600f..ce45b14f6 100644
--- a/nova/compute/monitor.py
+++ b/nova/compute/monitor.py
@@ -211,8 +211,8 @@ def store_graph(instance_id, filename):
# the response we can make our own client that does the actual
# request and hands it off to the response parser.
s3 = boto.s3.connection.S3Connection(
- aws_access_key_id='admin',
- aws_secret_access_key='admin',
+ aws_access_key_id=FLAGS.aws_access_key_id,
+ aws_secret_access_key=FLAGS.aws_secret_access_key,
is_secure=False,
calling_format=boto.s3.connection.OrdinaryCallingFormat(),
port=FLAGS.s3_port,
diff --git a/nova/flags.py b/nova/flags.py
index 07b469bca..f7ae26050 100644
--- a/nova/flags.py
+++ b/nova/flags.py
@@ -179,6 +179,8 @@ DEFINE_list('region_list',
[],
'list of region=url pairs separated by commas')
DEFINE_string('connection_type', 'libvirt', 'libvirt, xenapi or fake')
+DEFINE_string('aws_access_key_id', 'admin', 'AWS Access ID')
+DEFINE_string('aws_secret_access_key', 'admin', 'AWS Access Key')
DEFINE_integer('s3_port', 3333, 's3 port')
DEFINE_string('s3_host', '127.0.0.1', 's3 host')
DEFINE_string('compute_topic', 'compute', 'the topic compute nodes listen on')
@@ -196,6 +198,8 @@ DEFINE_integer('rabbit_port', 5672, 'rabbit port')
DEFINE_string('rabbit_userid', 'guest', 'rabbit userid')
DEFINE_string('rabbit_password', 'guest', 'rabbit password')
DEFINE_string('rabbit_virtual_host', '/', 'rabbit virtual host')
+DEFINE_integer('rabbit_retry_interval', 10, 'rabbit connection retry interval')
+DEFINE_integer('rabbit_max_retries', 12, 'rabbit connection attempts')
DEFINE_string('control_exchange', 'nova', 'the main exchange to connect to')
DEFINE_string('cc_host', '127.0.0.1', 'ip of api server')
DEFINE_integer('cc_port', 8773, 'cloud controller port')
diff --git a/nova/objectstore/handler.py b/nova/objectstore/handler.py
index b26906001..c8920b00c 100644
--- a/nova/objectstore/handler.py
+++ b/nova/objectstore/handler.py
@@ -61,6 +61,7 @@ from nova.objectstore import image
FLAGS = flags.FLAGS
+flags.DEFINE_string('s3_listen_host', '', 'Host to listen on.')
def render_xml(request, value):
@@ -438,6 +439,7 @@ def get_application():
# Disabled because of lack of proper introspection in Twisted
# or possibly different versions of twisted?
# pylint: disable-msg=E1101
- objectStoreService = internet.TCPServer(FLAGS.s3_port, factory)
+ objectStoreService = internet.TCPServer(FLAGS.s3_port, factory,
+ interface=FLAGS.s3_listen_host)
objectStoreService.setServiceParent(application)
return application
diff --git a/nova/rpc.py b/nova/rpc.py
index 9938b0838..86a29574f 100644
--- a/nova/rpc.py
+++ b/nova/rpc.py
@@ -38,8 +38,8 @@ from nova import fakerabbit
from nova import flags
from nova import context
-FLAGS = flags.FLAGS
+FLAGS = flags.FLAGS
LOG = logging.getLogger('amqplib')
LOG.setLevel(logging.DEBUG)
@@ -83,19 +83,24 @@ class Consumer(messaging.Consumer):
Contains methods for connecting the fetch method to async loops
"""
def __init__(self, *args, **kwargs):
- self.failed_connection = False
-
- while True:
+ for i in xrange(FLAGS.rabbit_max_retries):
+ if i > 0:
+ time.sleep(FLAGS.rabbit_retry_interval)
try:
super(Consumer, self).__init__(*args, **kwargs)
+ self.failed_connection = False
break
except: # Catching all because carrot sucks
- logging.exception("AMQP server on %s:%d is unreachable. " \
- "Trying again in 30 seconds." % (
- FLAGS.rabbit_host,
- FLAGS.rabbit_port))
- time.sleep(30)
- continue
+ logging.exception("AMQP server on %s:%d is unreachable." \
+ " Trying again in %d seconds." % (
+ FLAGS.rabbit_host,
+ FLAGS.rabbit_port,
+ FLAGS.rabbit_retry_interval))
+ self.failed_connection = True
+ if self.failed_connection:
+ logging.exception("Unable to connect to AMQP server" \
+ " after %d tries. Shutting down." % FLAGS.rabbit_max_retries)
+ sys.exit(1)
def fetch(self, no_ack=None, auto_ack=None, enable_callbacks=False):
"""Wraps the parent fetch with some logic for failed connections"""
@@ -103,7 +108,7 @@ class Consumer(messaging.Consumer):
# refactored into some sort of connection manager object
try:
if self.failed_connection:
- # NOTE(vish): conn is defined in the parent class, we can
+ # NOTE(vish): connection is defined in the parent class, we can
# recreate it as long as we create the backend too
# pylint: disable-msg=W0201
self.connection = Connection.recreate()
diff --git a/nova/server.py b/nova/server.py
index cb424caa1..a0ee54681 100644
--- a/nova/server.py
+++ b/nova/server.py
@@ -42,6 +42,8 @@ flags.DEFINE_bool('daemonize', False, 'daemonize this process')
# clutter.
flags.DEFINE_bool('use_syslog', True, 'output to syslog when daemonizing')
flags.DEFINE_string('logfile', None, 'log file to output to')
+flags.DEFINE_string('logdir', None, 'directory to keep log files in '
+ '(will be prepended to $logfile)')
flags.DEFINE_string('pidfile', None, 'pid file to output to')
flags.DEFINE_string('working_directory', './', 'working directory...')
flags.DEFINE_integer('uid', os.getuid(), 'uid under which to run')
@@ -119,6 +121,8 @@ def daemonize(args, name, main):
else:
if not FLAGS.logfile:
FLAGS.logfile = '%s.log' % name
+ if FLAGS.logdir:
+ FLAGS.logfile = os.path.join(FLAGS.logdir, FLAGS.logfile)
logfile = logging.FileHandler(FLAGS.logfile)
logfile.setFormatter(formatter)
logger.addHandler(logfile)
diff --git a/nova/tests/misc_unittest.py b/nova/tests/misc_unittest.py
new file mode 100644
index 000000000..856060afa
--- /dev/null
+++ b/nova/tests/misc_unittest.py
@@ -0,0 +1,48 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2010 OpenStack LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+import os
+import subprocess
+
+from nova import test
+from nova.utils import parse_mailmap, str_dict_replace
+
+
+class ProjectTestCase(test.TrialTestCase):
+ def test_authors_up_to_date(self):
+ if os.path.exists('../.bzr'):
+ log_cmd = subprocess.Popen(["bzr", "log", "-n0"],
+ stdout=subprocess.PIPE)
+ changelog = log_cmd.communicate()[0]
+ mailmap = parse_mailmap('../.mailmap')
+
+ contributors = set()
+ for l in changelog.split('\n'):
+ l = l.strip()
+ if (l.startswith('author:') or l.startswith('committer:')
+ and not l == 'committer: Tarmac'):
+ email = l.split(' ')[-1]
+ contributors.add(str_dict_replace(email, mailmap))
+
+ authors_file = open('../Authors', 'r').read()
+
+ missing = set()
+ for contributor in contributors:
+ if not contributor in authors_file:
+ missing.add(contributor)
+
+ self.assertTrue(len(missing) == 0,
+ '%r not listed in Authors' % missing)
diff --git a/nova/twistd.py b/nova/twistd.py
index 3ec0ff61e..cb5648ce6 100644
--- a/nova/twistd.py
+++ b/nova/twistd.py
@@ -43,6 +43,8 @@ else:
FLAGS = flags.FLAGS
+flags.DEFINE_string('logdir', None, 'directory to keep log files in '
+ '(will be prepended to $logfile)')
class TwistdServerOptions(ServerOptions):
@@ -246,6 +248,8 @@ def serve(filename):
FLAGS.logfile = '%s.log' % name
elif FLAGS.logfile.endswith('twistd.log'):
FLAGS.logfile = FLAGS.logfile.replace('twistd.log', '%s.log' % name)
+ if FLAGS.logdir:
+ FLAGS.logfile = os.path.join(FLAGS.logdir, FLAGS.logfile)
if not FLAGS.prefix:
FLAGS.prefix = name
elif FLAGS.prefix.endswith('twisted'):
diff --git a/nova/utils.py b/nova/utils.py
index 2970b93bb..142584df8 100644
--- a/nova/utils.py
+++ b/nova/utils.py
@@ -175,6 +175,24 @@ def parse_isotime(timestr):
return datetime.datetime.strptime(timestr, TIME_FORMAT)
+def parse_mailmap(mailmap='.mailmap'):
+ mapping = {}
+ if os.path.exists(mailmap):
+ fp = open(mailmap, 'r')
+ for l in fp:
+ l = l.strip()
+ if not l.startswith('#') and ' ' in l:
+ canonical_email, alias = l.split(' ')
+ mapping[alias] = canonical_email
+ return mapping
+
+
+def str_dict_replace(s, mapping):
+ for s1, s2 in mapping.iteritems():
+ s = s.replace(s1, s2)
+ return s
+
+
class LazyPluggable(object):
"""A pluggable backend loaded lazily based on some value."""
diff --git a/nova/virt/xenapi.py b/nova/virt/xenapi.py
index ec5e7456a..5bf98468e 100644
--- a/nova/virt/xenapi.py
+++ b/nova/virt/xenapi.py
@@ -289,11 +289,21 @@ class XenAPIConnection(object):
# Don't complain, just return. This lets us clean up instances
# that have already disappeared from the underlying platform.
defer.returnValue(None)
+ # Get the VDIs related to the VM
+ vdis = yield self._lookup_vm_vdis(vm)
try:
task = yield self._call_xenapi('Async.VM.hard_shutdown', vm)
yield self._wait_for_task(task)
except Exception, exc:
logging.warn(exc)
+ # Disk clean-up
+ if vdis:
+ for vdi in vdis:
+ try:
+ task = yield self._call_xenapi('Async.VDI.destroy', vdi)
+ yield self._wait_for_task(task)
+ except Exception, exc:
+ logging.warn(exc)
try:
task = yield self._call_xenapi('Async.VM.destroy', vm)
yield self._wait_for_task(task)
@@ -402,6 +412,30 @@ class XenAPIConnection(object):
True, {})
return sr
+ @utils.deferredToThread
+ def _lookup_vm_vdis(self, vm):
+ return self._lookup_vm_vdis_blocking(vm)
+
+ def _lookup_vm_vdis_blocking(self, vm):
+ # Firstly we get the VBDs, then the VDIs.
+ # TODO: do we leave the read-only devices?
+ vbds = self._conn.xenapi.VM.get_VBDs(vm)
+ vdis = []
+ if vbds:
+ for vbd in vbds:
+ try:
+ vdi = self._conn.xenapi.VBD.get_VDI(vbd)
+ # Test valid VDI
+ record = self._conn.xenapi.VDI.get_record(vdi)
+ except Exception, exc:
+ logging.warn(exc)
+ else:
+ vdis.append(vdi)
+ if len(vdis) > 0:
+ return vdis
+ else:
+ return None
+
def _wait_for_task(self, task):
"""Return a Deferred that will give the result of the given task.
The task is polled until it completes."""
diff --git a/nova/wsgi.py b/nova/wsgi.py
index b04b487ea..c7ee9ed14 100644
--- a/nova/wsgi.py
+++ b/nova/wsgi.py
@@ -28,7 +28,7 @@ from xml.dom import minidom
import eventlet
import eventlet.wsgi
-eventlet.patcher.monkey_patch(all=False, socket=True)
+eventlet.patcher.monkey_patch(all=False, socket=True, time=True)
import routes
import routes.middleware
import webob