summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.mailmap1
-rw-r--r--Authors2
-rwxr-xr-xbin/clear_rabbit_queues2
-rwxr-xr-xbin/nova-ajax-console-proxy2
-rwxr-xr-xbin/nova-direct-api2
-rwxr-xr-xbin/nova-manage11
-rw-r--r--nova/api/auth.py10
-rw-r--r--nova/api/ec2/__init__.py31
-rw-r--r--nova/api/openstack/common.py18
-rw-r--r--nova/api/openstack/compute/__init__.py2
-rw-r--r--nova/api/openstack/compute/contrib/hosts.py75
-rw-r--r--nova/api/openstack/compute/views/images.py6
-rw-r--r--nova/auth/ldapdriver.py2
-rw-r--r--nova/auth/manager.py2
-rw-r--r--nova/cloudpipe/pipelib.py2
-rw-r--r--nova/compute/api.py2
-rw-r--r--nova/compute/instance_types.py23
-rw-r--r--nova/compute/manager.py52
-rw-r--r--nova/compute/utils.py20
-rw-r--r--nova/console/manager.py2
-rw-r--r--nova/console/vmrc.py2
-rw-r--r--nova/console/vmrc_manager.py2
-rw-r--r--nova/console/xvp.py2
-rw-r--r--nova/consoleauth/__init__.py2
-rw-r--r--nova/consoleauth/manager.py2
-rw-r--r--nova/crypto.py9
-rw-r--r--nova/db/api.py6
-rw-r--r--nova/db/base.py2
-rw-r--r--nova/db/sqlalchemy/api.py6
-rw-r--r--nova/db/sqlalchemy/migrate_repo/versions/075_convert_bw_usage_to_store_network_id.py90
-rw-r--r--nova/db/sqlalchemy/models.py2
-rw-r--r--nova/flags.py12
-rw-r--r--nova/image/s3.py2
-rw-r--r--nova/ipv6/api.py2
-rw-r--r--nova/log.py6
-rw-r--r--nova/network/api.py6
-rw-r--r--nova/network/ldapdns.py2
-rwxr-xr-xnova/network/linux_net.py5
-rw-r--r--nova/network/manager.py7
-rw-r--r--nova/network/quantum/client.py28
-rw-r--r--nova/network/quantum/manager.py17
-rw-r--r--nova/network/quantum/melange_connection.py2
-rw-r--r--nova/network/quantum/quantum_connection.py29
-rw-r--r--nova/notifier/api.py2
-rw-r--r--nova/notifier/list_notifier.py2
-rw-r--r--nova/notifier/rabbit_notifier.py2
-rw-r--r--nova/objectstore/s3server.py2
-rw-r--r--nova/openstack/__init__.py15
-rw-r--r--nova/openstack/common/__init__.py15
-rw-r--r--nova/openstack/common/cfg.py (renamed from nova/common/cfg.py)0
-rw-r--r--nova/policy.py2
-rw-r--r--nova/quota.py12
-rwxr-xr-xnova/rootwrap/compute.py3
-rwxr-xr-xnova/rootwrap/filters.py17
-rw-r--r--nova/rpc/__init__.py6
-rw-r--r--nova/rpc/common.py2
-rw-r--r--nova/rpc/impl_qpid.py2
-rw-r--r--nova/scheduler/api.py2
-rw-r--r--nova/scheduler/driver.py2
-rw-r--r--nova/scheduler/filters/core_filter.py2
-rw-r--r--nova/scheduler/filters/ram_filter.py2
-rw-r--r--nova/scheduler/host_manager.py2
-rw-r--r--nova/scheduler/least_cost.py2
-rw-r--r--nova/scheduler/manager.py2
-rw-r--r--nova/scheduler/multi.py2
-rw-r--r--nova/scheduler/scheduler_options.py2
-rw-r--r--nova/scheduler/simple.py2
-rw-r--r--nova/scheduler/vsa.py2
-rw-r--r--nova/scheduler/zone_manager.py2
-rw-r--r--nova/service.py2
-rw-r--r--nova/test.py2
-rw-r--r--nova/tests/api/openstack/compute/contrib/test_hosts.py55
-rw-r--r--nova/tests/api/openstack/compute/test_flavors.py32
-rw-r--r--nova/tests/api/openstack/compute/test_images.py58
-rw-r--r--nova/tests/api/test_auth.py60
-rw-r--r--nova/tests/declare_flags.py2
-rw-r--r--nova/tests/fake_libvirt_utils.py4
-rw-r--r--nova/tests/runtime_flags.py2
-rw-r--r--nova/tests/test_cfg.py789
-rw-r--r--nova/tests/test_compute.py101
-rw-r--r--nova/tests/test_compute_utils.py9
-rw-r--r--nova/tests/test_flags.py2
-rw-r--r--nova/tests/test_imagecache.py243
-rw-r--r--nova/tests/test_instance_types.py8
-rw-r--r--nova/tests/test_libvirt.py46
-rw-r--r--nova/tests/test_linux_net.py25
-rw-r--r--nova/tests/test_notifier.py2
-rw-r--r--nova/tests/test_nova_rootwrap.py9
-rw-r--r--nova/tests/test_quota.py15
-rw-r--r--nova/tests/test_service.py2
-rw-r--r--nova/tests/test_utils.py21
-rw-r--r--nova/tests/test_virt_drivers.py9
-rw-r--r--nova/utils.py22
-rw-r--r--nova/virt/connection.py1
-rw-r--r--nova/virt/disk/api.py2
-rw-r--r--nova/virt/disk/nbd.py2
-rw-r--r--nova/virt/driver.py25
-rw-r--r--nova/virt/fake.py3
-rw-r--r--nova/virt/firewall.py4
-rw-r--r--nova/virt/interfaces.template2
-rw-r--r--nova/virt/libvirt/connection.py133
-rw-r--r--nova/virt/libvirt/firewall.py2
-rw-r--r--nova/virt/libvirt/imagecache.py364
-rw-r--r--nova/virt/libvirt/utils.py12
-rw-r--r--nova/virt/libvirt/vif.py5
-rw-r--r--nova/virt/vmwareapi/vim.py2
-rw-r--r--nova/virt/vmwareapi/vmops.py2
-rw-r--r--nova/virt/vmwareapi_conn.py11
-rw-r--r--nova/virt/xenapi/firewall.py4
-rw-r--r--nova/virt/xenapi/vif.py4
-rw-r--r--nova/virt/xenapi/vm_utils.py4
-rw-r--r--nova/virt/xenapi/vmops.py18
-rw-r--r--nova/virt/xenapi_conn.py27
-rw-r--r--nova/vnc/__init__.py2
-rw-r--r--nova/vnc/xvp_proxy.py2
-rw-r--r--nova/volume/api.py8
-rw-r--r--nova/volume/driver.py30
-rw-r--r--nova/volume/iscsi.py2
-rw-r--r--nova/volume/manager.py42
-rw-r--r--nova/volume/san.py3
-rw-r--r--nova/volume/xensm.py4
-rw-r--r--nova/vsa/api.py2
-rw-r--r--nova/vsa/manager.py2
-rw-r--r--po/pt_BR.po510
124 files changed, 1944 insertions, 1426 deletions
diff --git a/.mailmap b/.mailmap
index 9455109a7..8270e0c5c 100644
--- a/.mailmap
+++ b/.mailmap
@@ -39,6 +39,7 @@
<masumotok@nttdata.co.jp> <root@openstack2-api>
<matt.dietz@rackspace.com> <matthewdietz@Matthew-Dietzs-MacBook-Pro.local>
<matt.dietz@rackspace.com> <mdietz@openstack>
+<mikal@stillhq.com> <michael.still@canonical.com>
<mordred@inaugust.com> <mordred@hudson>
<naveedm9@gmail.com> <naveed.massjouni@rackspace.com>
<rnirmal@gmail.com> <nirmal.ranganathan@rackspace.com>
diff --git a/Authors b/Authors
index 574a34f30..ef89231cf 100644
--- a/Authors
+++ b/Authors
@@ -107,6 +107,7 @@ Lvov Maxim <usrleon@gmail.com>
Mandell Degerness <mdegerne@gmail.com>
Mark McLoughlin <markmc@redhat.com>
Mark Washenberger <mark.washenberger@rackspace.com>
+Maru Newby <mnewby@internap.com>
Masanori Itoh <itoumsn@nttdata.co.jp>
Matt Dietz <matt.dietz@rackspace.com>
Matthew Hooker <matt@cloudscaling.com>
@@ -169,3 +170,4 @@ Yuriy Taraday <yorik.sar@gmail.com>
Zed Shaw <zedshaw@zedshaw.com>
Zhixue Wu <Zhixue.Wu@citrix.com>
Zhongyue Luo <lzyeval@gmail.com>
+Ziad Sawalha <github@highbridgellc.com>
diff --git a/bin/clear_rabbit_queues b/bin/clear_rabbit_queues
index f697ef6b4..9d0d803a5 100755
--- a/bin/clear_rabbit_queues
+++ b/bin/clear_rabbit_queues
@@ -40,11 +40,11 @@ if os.path.exists(os.path.join(POSSIBLE_TOPDIR, 'nova', '__init__.py')):
gettext.install('nova', unicode=1)
-from nova.common import cfg
from nova import context
from nova import exception
from nova import flags
from nova import log as logging
+from nova.openstack.common import cfg
from nova import rpc
from nova import utils
diff --git a/bin/nova-ajax-console-proxy b/bin/nova-ajax-console-proxy
index 7dd5266a7..94d93cd0e 100755
--- a/bin/nova-ajax-console-proxy
+++ b/bin/nova-ajax-console-proxy
@@ -38,9 +38,9 @@ if os.path.exists(os.path.join(possible_topdir, 'nova', '__init__.py')):
sys.path.insert(0, possible_topdir)
-from nova.common import cfg
from nova import flags
from nova import log as logging
+from nova.openstack.common import cfg
from nova import rpc
from nova import service
from nova import utils
diff --git a/bin/nova-direct-api b/bin/nova-direct-api
index f77311914..6a79ef626 100755
--- a/bin/nova-direct-api
+++ b/bin/nova-direct-api
@@ -35,11 +35,11 @@ if os.path.exists(os.path.join(possible_topdir, 'nova', '__init__.py')):
sys.path.insert(0, possible_topdir)
-from nova.common import cfg
from nova import compute
from nova import flags
from nova import log as logging
from nova import network
+from nova.openstack.common import cfg
from nova import service
from nova import utils
from nova import volume
diff --git a/bin/nova-manage b/bin/nova-manage
index e89923d3c..6b15dea63 100755
--- a/bin/nova-manage
+++ b/bin/nova-manage
@@ -2307,7 +2307,16 @@ def methods_of(obj):
def main():
"""Parse options and call the appropriate class/method."""
- utils.default_flagfile()
+ flagfile = utils.default_flagfile()
+
+ if flagfile and not os.access(flagfile, os.R_OK):
+ st = os.stat(flagfile)
+ print "Could not read %s. Re-running with sudo" % flagfile
+ try:
+ os.execvp('sudo', ['sudo', '-u', '#%s' % st.st_uid] + sys.argv)
+ except:
+ print 'sudo failed, continuing as if nothing happened'
+
argv = FLAGS(sys.argv)
logging.setup()
diff --git a/nova/api/auth.py b/nova/api/auth.py
index 84ba3376d..316a8f72f 100644
--- a/nova/api/auth.py
+++ b/nova/api/auth.py
@@ -21,10 +21,10 @@ Common Auth Middleware.
import webob.dec
import webob.exc
-from nova.common import cfg
from nova import context
from nova import flags
from nova import log as logging
+from nova.openstack.common import cfg
from nova import wsgi
@@ -56,10 +56,10 @@ class NovaKeystoneContext(wsgi.Middleware):
@webob.dec.wsgify(RequestClass=wsgi.Request)
def __call__(self, req):
- try:
- user_id = req.headers['X_USER']
- except KeyError:
- logging.debug("X_USER not found in request")
+ user_id = req.headers.get('X_USER')
+ user_id = req.headers.get('X_USER_ID', user_id)
+ if user_id is None:
+ logging.debug("Neither X_USER_ID nor X_USER found in request")
return webob.exc.HTTPUnauthorized()
# get the roles
roles = [r.strip() for r in req.headers.get('X_ROLE', '').split(',')]
diff --git a/nova/api/ec2/__init__.py b/nova/api/ec2/__init__.py
index dfcddbc4e..bcd7b239e 100644
--- a/nova/api/ec2/__init__.py
+++ b/nova/api/ec2/__init__.py
@@ -32,11 +32,11 @@ from nova.api.ec2 import ec2utils
from nova.api.ec2 import faults
from nova.api import validator
from nova.auth import manager
-from nova.common import cfg
from nova import context
from nova import exception
from nova import flags
from nova import log as logging
+from nova.openstack.common import cfg
from nova import utils
from nova import wsgi
@@ -185,14 +185,27 @@ class EC2Token(wsgi.Middleware):
# Not part of authentication args
auth_params.pop('Signature')
- # Authenticate the request.
- creds = {'ec2Credentials': {'access': access,
- 'signature': signature,
- 'host': req.host,
- 'verb': req.method,
- 'path': req.path,
- 'params': auth_params,
- }}
+ if "ec2" in FLAGS.keystone_ec2_url:
+ LOG.warning("Configuration setting for keystone_ec2_url needs "
+ "to be updated to /tokens only. The /ec2 prefix is "
+ "being deprecated")
+ # Authenticate the request.
+ creds = {'ec2Credentials': {'access': access,
+ 'signature': signature,
+ 'host': req.host,
+ 'verb': req.method,
+ 'path': req.path,
+ 'params': auth_params,
+ }}
+ else:
+ # Authenticate the request.
+ creds = {'auth': {'OS-KSEC2:ec2Credentials': {'access': access,
+ 'signature': signature,
+ 'host': req.host,
+ 'verb': req.method,
+ 'path': req.path,
+ 'params': auth_params,
+ }}}
creds_json = utils.dumps(creds)
headers = {'Content-Type': 'application/json'}
diff --git a/nova/api/openstack/common.py b/nova/api/openstack/common.py
index b46a6c1eb..c19b8f103 100644
--- a/nova/api/openstack/common.py
+++ b/nova/api/openstack/common.py
@@ -457,14 +457,18 @@ class ViewBuilder(object):
"""Return href string with proper limit and marker params."""
params = request.params.copy()
params["marker"] = identifier
- url = os.path.join(request.application_url,
+ prefix = self._update_link_prefix(request.application_url,
+ FLAGS.osapi_compute_link_prefix)
+ url = os.path.join(prefix,
request.environ["nova.context"].project_id,
self._collection_name)
return "%s?%s" % (url, dict_to_query_str(params))
def _get_href_link(self, request, identifier):
"""Return an href string pointing to this object."""
- return os.path.join(request.application_url,
+ prefix = self._update_link_prefix(request.application_url,
+ FLAGS.osapi_compute_link_prefix)
+ return os.path.join(prefix,
request.environ["nova.context"].project_id,
self._collection_name,
str(identifier))
@@ -472,6 +476,8 @@ class ViewBuilder(object):
def _get_bookmark_link(self, request, identifier):
"""Create a URL that refers to a specific resource."""
base_url = remove_version_from_href(request.application_url)
+ base_url = self._update_link_prefix(base_url,
+ FLAGS.osapi_compute_link_prefix)
return os.path.join(base_url,
request.environ["nova.context"].project_id,
self._collection_name,
@@ -492,3 +498,11 @@ class ViewBuilder(object):
"href": self._get_next_link(request, last_item_id),
})
return links
+
+ def _update_link_prefix(self, orig_url, prefix):
+ if not prefix:
+ return orig_url
+ url_parts = list(urlparse.urlsplit(orig_url))
+ prefix_parts = list(urlparse.urlsplit(prefix))
+ url_parts[1] = prefix_parts[1]
+ return urlparse.urlunsplit(url_parts)
diff --git a/nova/api/openstack/compute/__init__.py b/nova/api/openstack/compute/__init__.py
index d035173ed..3884ffbad 100644
--- a/nova/api/openstack/compute/__init__.py
+++ b/nova/api/openstack/compute/__init__.py
@@ -31,9 +31,9 @@ from nova.api.openstack.compute import limits
from nova.api.openstack.compute import servers
from nova.api.openstack.compute import server_metadata
from nova.api.openstack.compute import versions
-from nova.common import cfg
from nova import flags
from nova import log as logging
+from nova.openstack.common import cfg
LOG = logging.getLogger('nova.api.openstack.compute')
diff --git a/nova/api/openstack/compute/contrib/hosts.py b/nova/api/openstack/compute/contrib/hosts.py
index 53f1a064a..6eee93e7b 100644
--- a/nova/api/openstack/compute/contrib/hosts.py
+++ b/nova/api/openstack/compute/contrib/hosts.py
@@ -68,6 +68,16 @@ class HostActionTemplate(xmlutil.TemplateBuilder):
return xmlutil.MasterTemplate(root, 1)
+class HostShowTemplate(xmlutil.TemplateBuilder):
+ def construct(self):
+ root = xmlutil.TemplateElement('host')
+ elem = xmlutil.make_flat_dict('resource', selector='host',
+ subselector='resource')
+ root.append(elem)
+
+ return xmlutil.MasterTemplate(root, 1)
+
+
class HostDeserializer(wsgi.XMLDeserializer):
def default(self, string):
try:
@@ -83,15 +93,6 @@ class HostDeserializer(wsgi.XMLDeserializer):
return dict(body=updates)
-class HostShowTemplate(xmlutil.TemplateBuilder):
- def construct(self):
- root = xmlutil.TemplateElement('host', selector='host')
- root.set('resource')
- root.set('usage')
-
- return xmlutil.MasterTemplate(root, 1)
-
-
def _list_hosts(req, service=None):
"""Returns a summary list of hosts, optionally filtering
by service type.
@@ -192,16 +193,10 @@ class HostController(object):
:param context: security context
:param host: hostname
- :returns:
- {'host': {'resource':D1, 'usage':{proj_id1:D2,..}}}
-
- 'resource' shows "available" and "in-use" vcpus, memory and disk.
- 'usage' shows "in-use" vcpus, memory and disk per project.
-
- D1: {'vcpus': 16, 'memory_mb': 2048, 'local_gb': 2048,
- 'vcpus_used': 12, 'memory_mb_used': 10240,
- 'local_gb_used': 64}
- D2: {'vcpus': 1, 'memory_mb': 2048, 'local_gb': 20}
+ :returns: expected to use HostShowTemplate.
+ ex. {'host': {'resource':D},..}
+ D: {'host': 'hostname','project': 'admin',
+ 'cpu': 1, 'memory_mb': 2048, 'disk_gb': 30}
"""
host = id
context = req.environ['nova.context']
@@ -222,16 +217,28 @@ class HostController(object):
# Getting total available/used resource
compute_ref = compute_ref['compute_node'][0]
- resource = {'vcpus': compute_ref['vcpus'],
- 'memory_mb': compute_ref['memory_mb'],
- 'local_gb': compute_ref['local_gb'],
- 'vcpus_used': compute_ref['vcpus_used'],
- 'memory_mb_used': compute_ref['memory_mb_used'],
- 'local_gb_used': compute_ref['local_gb_used']}
- usage = dict()
- if not instance_refs:
- return {'host':
- {'resource': resource, 'usage': usage}}
+ resources = [{'resource': {'host': host, 'project': '(total)',
+ 'cpu': compute_ref['vcpus'],
+ 'memory_mb': compute_ref['memory_mb'],
+ 'disk_gb': compute_ref['local_gb']}},
+ {'resource': {'host': host, 'project': '(used_now)',
+ 'cpu': compute_ref['vcpus_used'],
+ 'memory_mb': compute_ref['memory_mb_used'],
+ 'disk_gb': compute_ref['local_gb_used']}}]
+
+ cpu_sum = 0
+ mem_sum = 0
+ hdd_sum = 0
+ for i in instance_refs:
+ cpu_sum += i['vcpus']
+ mem_sum += i['memory_mb']
+ hdd_sum += i['root_gb'] + i['ephemeral_gb']
+
+ resources.append({'resource': {'host': host,
+ 'project': '(used_max)',
+ 'cpu': cpu_sum,
+ 'memory_mb': mem_sum,
+ 'disk_gb': hdd_sum}})
# Getting usage resource per project
project_ids = [i['project_id'] for i in instance_refs]
@@ -246,11 +253,13 @@ class HostController(object):
disk = [i['root_gb'] + i['ephemeral_gb'] for i in instance_refs
if i['project_id'] == project_id]
- usage[project_id] = {'vcpus': reduce(lambda x, y: x + y, vcpus),
- 'memory_mb': reduce(lambda x, y: x + y, mem),
- 'local_gb': reduce(lambda x, y: x + y, disk)}
+ resources.append({'resource': {'host': host,
+ 'project': project_id,
+ 'cpu': reduce(lambda x, y: x + y, vcpus),
+ 'memory_mb': reduce(lambda x, y: x + y, mem),
+ 'disk_gb': reduce(lambda x, y: x + y, disk)}})
- return {'host': {'resource': resource, 'usage': usage}}
+ return {'host': resources}
class Hosts(extensions.ExtensionDescriptor):
diff --git a/nova/api/openstack/compute/views/images.py b/nova/api/openstack/compute/views/images.py
index 5ef1af59b..865e7df85 100644
--- a/nova/api/openstack/compute/views/images.py
+++ b/nova/api/openstack/compute/views/images.py
@@ -18,9 +18,13 @@
import os.path
from nova.api.openstack import common
+from nova import flags
from nova import utils
+FLAGS = flags.FLAGS
+
+
class ViewBuilder(common.ViewBuilder):
_collection_name = "images"
@@ -109,6 +113,8 @@ class ViewBuilder(common.ViewBuilder):
def _get_alternate_link(self, request, identifier):
"""Create an alternate link for a specific flavor id."""
glance_url = utils.generate_glance_url()
+ glance_url = self._update_link_prefix(glance_url,
+ FLAGS.osapi_glance_link_prefix)
return os.path.join(glance_url,
request.environ["nova.context"].project_id,
self._collection_name,
diff --git a/nova/auth/ldapdriver.py b/nova/auth/ldapdriver.py
index 79da5bd8d..3cb0de783 100644
--- a/nova/auth/ldapdriver.py
+++ b/nova/auth/ldapdriver.py
@@ -27,10 +27,10 @@ public methods.
import functools
import sys
-from nova.common import cfg
from nova import exception
from nova import flags
from nova import log as logging
+from nova.openstack.common import cfg
ldap_opts = [
diff --git a/nova/auth/manager.py b/nova/auth/manager.py
index 234b9bf33..40f1fc842 100644
--- a/nova/auth/manager.py
+++ b/nova/auth/manager.py
@@ -30,13 +30,13 @@ import tempfile
import uuid
import zipfile
-from nova.common import cfg
from nova import context
from nova import crypto
from nova import db
from nova import exception
from nova import flags
from nova import log as logging
+from nova.openstack.common import cfg
from nova import utils
from nova.auth import signer
diff --git a/nova/cloudpipe/pipelib.py b/nova/cloudpipe/pipelib.py
index 3c92f72b1..7d43866e6 100644
--- a/nova/cloudpipe/pipelib.py
+++ b/nova/cloudpipe/pipelib.py
@@ -27,13 +27,13 @@ import string
import tempfile
import zipfile
-from nova.common import cfg
from nova import context
from nova import crypto
from nova import db
from nova import exception
from nova import flags
from nova import log as logging
+from nova.openstack.common import cfg
from nova import utils
# TODO(eday): Eventually changes these to something not ec2-specific
from nova.api.ec2 import cloud
diff --git a/nova/compute/api.py b/nova/compute/api.py
index 42c4ea4f0..f54d184dd 100644
--- a/nova/compute/api.py
+++ b/nova/compute/api.py
@@ -28,7 +28,6 @@ import novaclient
import webob.exc
from nova import block_device
-from nova.common import cfg
from nova.compute import aggregate_states
from nova.compute import instance_types
from nova.compute import power_state
@@ -40,6 +39,7 @@ from nova import flags
import nova.image
from nova import log as logging
from nova import network
+from nova.openstack.common import cfg
import nova.policy
from nova import quota
from nova import rpc
diff --git a/nova/compute/instance_types.py b/nova/compute/instance_types.py
index 583b2da4e..e6a6d4a88 100644
--- a/nova/compute/instance_types.py
+++ b/nova/compute/instance_types.py
@@ -118,8 +118,8 @@ def get_default_instance_type():
name = FLAGS.default_instance_type
try:
return get_instance_type_by_name(name)
- except exception.DBError:
- raise exception.ApiError(_("Unknown instance type: %s") % name)
+ except exception.InstanceTypeNotFound as e:
+ raise exception.ApiError(e)
def get_instance_type(instance_type_id):
@@ -130,9 +130,8 @@ def get_instance_type(instance_type_id):
ctxt = context.get_admin_context()
try:
return db.instance_type_get(ctxt, instance_type_id)
- except exception.DBError:
- msg = _("Unknown instance type: %s") % instance_type_id
- raise exception.ApiError(msg)
+ except exception.InstanceTypeNotFound as e:
+ raise exception.ApiError(e)
def get_instance_type_by_name(name):
@@ -144,16 +143,16 @@ def get_instance_type_by_name(name):
try:
return db.instance_type_get_by_name(ctxt, name)
- except exception.DBError:
- raise exception.ApiError(_("Unknown instance type: %s") % name)
+ except exception.InstanceTypeNotFound as e:
+ raise exception.ApiError(e)
# TODO(termie): flavor-specific code should probably be in the API that uses
# flavors.
def get_instance_type_by_flavor_id(flavorid):
- """Retrieve instance type by flavorid."""
+ """Retrieve instance type by flavorid.
+
+ :raises: FlavorNotFound
+ """
ctxt = context.get_admin_context()
- try:
- return db.instance_type_get_by_flavor_id(ctxt, flavorid)
- except exception.DBError:
- raise exception.ApiError(_("Unknown instance type: %s") % flavorid)
+ return db.instance_type_get_by_flavor_id(ctxt, flavorid)
diff --git a/nova/compute/manager.py b/nova/compute/manager.py
index 57026d635..e5600af32 100644
--- a/nova/compute/manager.py
+++ b/nova/compute/manager.py
@@ -45,7 +45,6 @@ from eventlet import greenthread
from nova import block_device
import nova.context
-from nova.common import cfg
from nova.compute import instance_types
from nova.compute import power_state
from nova.compute import task_states
@@ -59,6 +58,7 @@ from nova import manager
from nova import network
from nova.network import model as network_model
from nova.notifier import api as notifier
+from nova.openstack.common import cfg
from nova import rpc
from nova import utils
from nova.virt import driver
@@ -109,6 +109,13 @@ compute_opts = [
help="Action to take if a running deleted instance is detected."
"Valid options are 'noop', 'log' and 'reap'. "
"Set to 'noop' to disable."),
+ cfg.BoolOpt("use_image_cache_manager",
+ default=False,
+ help="Whether to manage images in the local cache."),
+ cfg.IntOpt("image_cache_manager_interval",
+ default=3600,
+ help="Number of periodic scheduler ticks to wait between "
+ "runs of the image cache manager."),
]
FLAGS = flags.FLAGS
@@ -195,6 +202,7 @@ class ComputeManager(manager.SchedulerDependentManager):
self.network_manager = utils.import_object(FLAGS.network_manager)
self._last_host_check = 0
self._last_bw_usage_poll = 0
+
super(ComputeManager, self).__init__(service_name="compute",
*args, **kwargs)
@@ -644,9 +652,10 @@ class ComputeManager(manager.SchedulerDependentManager):
# NOTE(vish): actual driver detach done in driver.destroy, so
# just tell nova-volume that we are done with it.
volume = self.volume_api.get(context, bdm['volume_id'])
+ connector = self.driver.get_volume_connector(instance)
self.volume_api.terminate_connection(context,
volume,
- FLAGS.my_ip)
+ connector)
self.volume_api.detach(context, volume)
except exception.DiskNotFound as exc:
LOG.warn(_("Ignoring DiskNotFound: %s") % exc)
@@ -1589,10 +1598,10 @@ class ComputeManager(manager.SchedulerDependentManager):
msg = _("instance %(instance_uuid)s: booting with "
"volume %(volume_id)s at %(mountpoint)s")
LOG.audit(msg % locals(), context=context)
- address = FLAGS.my_ip
+ connector = self.driver.get_volume_connector(instance)
connection_info = self.volume_api.initialize_connection(context,
volume,
- address)
+ connector)
self.volume_api.attach(context, volume, instance_id, mountpoint)
return connection_info
@@ -1608,10 +1617,10 @@ class ComputeManager(manager.SchedulerDependentManager):
msg = _("instance %(instance_uuid)s: attaching volume %(volume_id)s"
" to %(mountpoint)s")
LOG.audit(msg % locals(), context=context)
- address = FLAGS.my_ip
+ connector = self.driver.get_volume_connector(instance_ref)
connection_info = self.volume_api.initialize_connection(context,
volume,
- address)
+ connector)
try:
self.driver.attach_volume(connection_info,
instance_ref['name'],
@@ -1623,7 +1632,7 @@ class ComputeManager(manager.SchedulerDependentManager):
LOG.exception(msg % locals(), context=context)
self.volume_api.terminate_connection(context,
volume,
- address)
+ connector)
self.volume_api.attach(context, volume, instance_id, mountpoint)
values = {
@@ -1666,7 +1675,8 @@ class ComputeManager(manager.SchedulerDependentManager):
bdm = self._get_instance_volume_bdm(context, instance_id, volume_id)
self._detach_volume(context, instance_ref, bdm)
volume = self.volume_api.get(context, volume_id)
- self.volume_api.terminate_connection(context, volume, FLAGS.my_ip)
+ connector = self.driver.get_volume_connector(instance_ref)
+ self.volume_api.terminate_connection(context, volume, connector)
self.volume_api.detach(context.elevated(), volume)
self.db.block_device_mapping_destroy_by_instance_and_volume(
context, instance_id, volume_id)
@@ -1685,7 +1695,8 @@ class ComputeManager(manager.SchedulerDependentManager):
volume_id)
self._detach_volume(context, instance_ref, bdm)
volume = self.volume_api.get(context, volume_id)
- self.volume_api.terminate_connection(context, volume, FLAGS.my_ip)
+ connector = self.driver.get_volume_connector(instance_ref)
+ self.volume_api.terminate_connection(context, volume, connector)
except exception.NotFound:
pass
@@ -2077,10 +2088,14 @@ class ComputeManager(manager.SchedulerDependentManager):
return
for usage in bw_usage:
- vif = usage['virtual_interface']
+ mac = usage['mac_address']
+ vif = self.network_api.get_vif_by_mac_address(context, mac)
+ if not vif:
+ continue
+
self.db.bw_usage_update(context,
- vif.instance_id,
- vif.network.label,
+ vif['instance_id'],
+ mac,
start_time,
usage['bw_in'], usage['bw_out'])
@@ -2266,3 +2281,16 @@ class ComputeManager(manager.SchedulerDependentManager):
def remove_aggregate_host(self, context, aggregate_id, host):
"""Removes a host from a physical hypervisor pool."""
raise NotImplementedError()
+
+ @manager.periodic_task(
+ ticks_between_runs=FLAGS.image_cache_manager_interval)
+ def _run_image_cache_manager_pass(self, context):
+ """Run a single pass of the image cache manager."""
+
+ if not FLAGS.use_image_cache_manager:
+ return
+
+ try:
+ self.driver.manage_image_cache(context)
+ except NotImplementedError:
+ pass
diff --git a/nova/compute/utils.py b/nova/compute/utils.py
index b8b34fa81..1358160e8 100644
--- a/nova/compute/utils.py
+++ b/nova/compute/utils.py
@@ -22,6 +22,8 @@ from nova import context
from nova import db
from nova import exception
from nova import flags
+from nova import network
+from nova.network import model as network_model
from nova.notifier import api as notifier_api
from nova import utils
@@ -44,10 +46,26 @@ def notify_usage_exists(instance_ref, current_period=False):
else:
audit_start = begin
audit_end = end
+
+ if (instance_ref.get('info_cache') and
+ instance_ref['info_cache'].get('network_info')):
+
+ cached_info = instance_ref['info_cache']['network_info']
+ nw_info = network_model.NetworkInfo.hydrate(cached_info)
+ else:
+ nw_info = network.API().get_instance_nw_info(admin_context,
+ instance_ref)
+
for b in db.bw_usage_get_by_instance(admin_context,
instance_ref['id'],
audit_start):
- bw[b.network_label] = dict(bw_in=b.bw_in, bw_out=b.bw_out)
+ label = 'net-name-not-found-%s' % b['mac']
+ for vif in nw_info:
+ if vif['address'] == b['mac']:
+ label = vif['network']['label']
+ break
+
+ bw[label] = dict(bw_in=b.bw_in, bw_out=b.bw_out)
usage_info = utils.usage_from_instance(instance_ref,
audit_period_beginning=str(audit_start),
audit_period_ending=str(audit_end),
diff --git a/nova/console/manager.py b/nova/console/manager.py
index 220ac32c5..a181ee437 100644
--- a/nova/console/manager.py
+++ b/nova/console/manager.py
@@ -19,10 +19,10 @@
import socket
-from nova.common import cfg
from nova import exception
from nova import flags
from nova import log as logging
+from nova.openstack.common import cfg
from nova import manager
from nova import rpc
from nova import utils
diff --git a/nova/console/vmrc.py b/nova/console/vmrc.py
index e29254d60..a104a5f7b 100644
--- a/nova/console/vmrc.py
+++ b/nova/console/vmrc.py
@@ -20,9 +20,9 @@
import base64
import json
-from nova.common import cfg
from nova import exception
from nova import flags
+from nova.openstack.common import cfg
from nova.virt.vmwareapi import vim_util
diff --git a/nova/console/vmrc_manager.py b/nova/console/vmrc_manager.py
index 03cc46bf6..161499830 100644
--- a/nova/console/vmrc_manager.py
+++ b/nova/console/vmrc_manager.py
@@ -17,11 +17,11 @@
"""VMRC Console Manager."""
-from nova.common import cfg
from nova import exception
from nova import flags
from nova import log as logging
from nova import manager
+from nova.openstack.common import cfg
from nova import rpc
from nova import utils
from nova.virt import vmwareapi_conn
diff --git a/nova/console/xvp.py b/nova/console/xvp.py
index 2b8dcc1e0..35e57f086 100644
--- a/nova/console/xvp.py
+++ b/nova/console/xvp.py
@@ -22,12 +22,12 @@ import signal
from Cheetah import Template
-from nova.common import cfg
from nova import context
from nova import db
from nova import exception
from nova import flags
from nova import log as logging
+from nova.openstack.common import cfg
from nova import utils
diff --git a/nova/consoleauth/__init__.py b/nova/consoleauth/__init__.py
index 4048ae433..4b28776c0 100644
--- a/nova/consoleauth/__init__.py
+++ b/nova/consoleauth/__init__.py
@@ -18,8 +18,8 @@
"""Module to authenticate Consoles."""
-from nova.common import cfg
from nova import flags
+from nova.openstack.common import cfg
consoleauth_topic_opt = \
diff --git a/nova/consoleauth/manager.py b/nova/consoleauth/manager.py
index 08ddd5a3b..b3f85e1f9 100644
--- a/nova/consoleauth/manager.py
+++ b/nova/consoleauth/manager.py
@@ -22,10 +22,10 @@ import os
import sys
import time
-from nova.common import cfg
from nova import flags
from nova import log as logging
from nova import manager
+from nova.openstack.common import cfg
from nova import utils
diff --git a/nova/crypto.py b/nova/crypto.py
index a8b10de9b..79e40337b 100644
--- a/nova/crypto.py
+++ b/nova/crypto.py
@@ -22,25 +22,24 @@ Includes root and intermediate CAs, SSH key_pairs and x509 certificates.
"""
+from __future__ import absolute_import
+
import base64
-import gettext
import hashlib
import os
import shutil
import string
import tempfile
-import utils
import Crypto.Cipher.AES
-gettext.install('nova', unicode=1)
-
-from nova.common import cfg
from nova import context
from nova import db
from nova import exception
from nova import flags
from nova import log as logging
+from nova.openstack.common import cfg
+from nova import utils
LOG = logging.getLogger("nova.crypto")
diff --git a/nova/db/api.py b/nova/db/api.py
index de7b1de74..c73844a8c 100644
--- a/nova/db/api.py
+++ b/nova/db/api.py
@@ -43,9 +43,9 @@ these objects be simple dictionaries.
"""
-from nova.common import cfg
from nova import exception
from nova import flags
+from nova.openstack.common import cfg
from nova import utils
@@ -1549,14 +1549,14 @@ def bw_usage_get_all_by_filters(context, filters):
def bw_usage_update(context,
instance_id,
- network_label,
+ mac,
start_period,
bw_in, bw_out):
"""Update cached bw usage for an instance and network
Creates new record if needed."""
return IMPL.bw_usage_update(context,
instance_id,
- network_label,
+ mac,
start_period,
bw_in, bw_out)
diff --git a/nova/db/base.py b/nova/db/base.py
index 77b7d82a7..a1b3bf711 100644
--- a/nova/db/base.py
+++ b/nova/db/base.py
@@ -18,9 +18,9 @@
"""Base class for classes that need modular database access."""
-from nova.common import cfg
from nova import utils
from nova import flags
+from nova.openstack.common import cfg
db_driver_opt = \
diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py
index 7a0f9b200..b27ac9689 100644
--- a/nova/db/sqlalchemy/api.py
+++ b/nova/db/sqlalchemy/api.py
@@ -3710,7 +3710,7 @@ def bw_usage_get_all_by_filters(context, filters):
@require_context
def bw_usage_update(context,
instance_id,
- network_label,
+ mac,
start_period,
bw_in, bw_out,
session=None):
@@ -3722,14 +3722,14 @@ def bw_usage_update(context,
read_deleted="yes").\
filter_by(instance_id=instance_id).\
filter_by(start_period=start_period).\
- filter_by(network_label=network_label).\
+ filter_by(mac=mac).\
first()
if not bwusage:
bwusage = models.BandwidthUsage()
bwusage.instance_id = instance_id
bwusage.start_period = start_period
- bwusage.network_label = network_label
+ bwusage.mac = mac
bwusage.last_refreshed = utils.utcnow()
bwusage.bw_in = bw_in
diff --git a/nova/db/sqlalchemy/migrate_repo/versions/075_convert_bw_usage_to_store_network_id.py b/nova/db/sqlalchemy/migrate_repo/versions/075_convert_bw_usage_to_store_network_id.py
new file mode 100644
index 000000000..e75d6a6d9
--- /dev/null
+++ b/nova/db/sqlalchemy/migrate_repo/versions/075_convert_bw_usage_to_store_network_id.py
@@ -0,0 +1,90 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2011 OpenStack LLC.
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+from sqlalchemy import *
+from migrate import *
+
+from nova import utils
+
+
+meta = MetaData()
+
+
+def upgrade(migrate_engine):
+ meta.bind = migrate_engine
+ bw_usage_cache = Table('bw_usage_cache', meta,
+ Column('id', Integer, primary_key=True),
+ Column('network_label', String(255)),
+ Column('instance_id', Integer, nullable=False),
+ Column('start_period', DateTime, nullable=False),
+ Column('last_refreshed', DateTime),
+ Column('bw_in', BigInteger),
+ Column('bw_out', BigInteger),
+ Column('created_at', DateTime(timezone=False),
+ default=utils.utcnow()),
+ Column('updated_at', DateTime(timezone=False),
+ onupdate=utils.utcnow()),
+ Column('deleted_at', DateTime(timezone=False)),
+ Column('deleted', Boolean(create_constraint=True,
+ name=None)))
+
+ vifs = Table('virtual_interfaces', meta, autoload=True)
+ networks = Table('networks', meta, autoload=True)
+ mac_column = Column('mac', String(255))
+
+ bw_usage_cache.create_column(mac_column)
+
+ bw_usage_cache.update()\
+ .values(mac=select([vifs.c.address])\
+ .where(and_(networks.c.label == bw_usage_cache.c.network_label,
+ networks.c.id == vifs.c.network_id))\
+ .as_scalar()).execute()
+
+ bw_usage_cache.c.network_label.drop()
+
+
+def downgrade(migrate_engine):
+ meta.bind = migrate_engine
+ bw_usage_cache = Table('bw_usage_cache', meta,
+ Column('id', Integer, primary_key=True),
+ Column('network_uuid', String(36)),
+ Column('instance_id', Integer, nullable=False),
+ Column('start_period', DateTime, nullable=False),
+ Column('last_refreshed', DateTime),
+ Column('bw_in', BigInteger),
+ Column('bw_out', BigInteger),
+ Column('created_at', DateTime(timezone=False),
+ default=utils.utcnow()),
+ Column('updated_at', DateTime(timezone=False),
+ onupdate=utils.utcnow()),
+ Column('deleted_at', DateTime(timezone=False)),
+ Column('deleted', Boolean(create_constraint=True,
+ name=None)))
+
+ vifs = Table('virtual_interfaces', meta, autoload=True)
+ network = Table('networks', meta, autoload=True)
+ network_label_column = Column('network_label', String(255))
+
+ bw_usage_cache.create_column(network_label_column)
+
+ bw_usage_cache.update()\
+ .values(network_label=select([network.c.label])\
+ .where(and_(network.c.id == vifs.c.network_id,
+ vifs.c.address == bw_usage_cache.c.mac))\
+ .as_scalar()).execute()
+
+ bw_usage_cache.c.network_uuid.drop()
diff --git a/nova/db/sqlalchemy/models.py b/nova/db/sqlalchemy/models.py
index f7b9a555c..df7f42c8d 100644
--- a/nova/db/sqlalchemy/models.py
+++ b/nova/db/sqlalchemy/models.py
@@ -927,7 +927,7 @@ class BandwidthUsage(BASE, NovaBase):
__tablename__ = 'bw_usage_cache'
id = Column(Integer, primary_key=True, nullable=False)
instance_id = Column(Integer, nullable=False)
- network_label = Column(String(255))
+ mac = Column(String(255), nullable=False)
start_period = Column(DateTime, nullable=False)
last_refreshed = Column(DateTime)
bw_in = Column(BigInteger)
diff --git a/nova/flags.py b/nova/flags.py
index 4c0d61498..3f3560057 100644
--- a/nova/flags.py
+++ b/nova/flags.py
@@ -32,7 +32,7 @@ import sys
import gflags
-from nova.common import cfg
+from nova.openstack.common import cfg
class FlagValues(object):
@@ -338,6 +338,14 @@ global_opts = [
cfg.StrOpt('osapi_path',
default='/v1.1/',
help='suffix for openstack'),
+ cfg.StrOpt('osapi_compute_link_prefix',
+ default=None,
+ help='Base URL that will be presented to users in links '
+ 'to the Openstack Compute API'),
+ cfg.StrOpt('osapi_glance_link_prefix',
+ default=None,
+ help='Base URL that will be presented to users in links '
+ 'to glance resources'),
cfg.IntOpt('osapi_max_limit',
default=1000,
help='max number of items returned in a collection response'),
@@ -442,7 +450,7 @@ global_opts = [
default=100,
help='default partition size for shared capacity'),
cfg.StrOpt('firewall_driver',
- default='nova.virt.libvirt.firewall.IptablesFirewallDriver',
+ default='nova.virt.firewall.IptablesFirewallDriver',
help='Firewall driver (defaults to iptables)'),
cfg.StrOpt('image_service',
default='nova.image.glance.GlanceImageService',
diff --git a/nova/image/s3.py b/nova/image/s3.py
index ee11c163c..2be1b5ede 100644
--- a/nova/image/s3.py
+++ b/nova/image/s3.py
@@ -31,11 +31,11 @@ import eventlet
from nova import rpc
import nova.db.api
-from nova.common import cfg
from nova import exception
from nova import flags
from nova import image
from nova import log as logging
+from nova.openstack.common import cfg
from nova import utils
from nova.api.ec2 import ec2utils
diff --git a/nova/ipv6/api.py b/nova/ipv6/api.py
index 5931b8ba6..ea6d8eb22 100644
--- a/nova/ipv6/api.py
+++ b/nova/ipv6/api.py
@@ -14,8 +14,8 @@
# License for the specific language governing permissions and limitations
# under the License.
-from nova.common import cfg
from nova import flags
+from nova.openstack.common import cfg
from nova import utils
diff --git a/nova/log.py b/nova/log.py
index c0be3b95b..c0bc256cc 100644
--- a/nova/log.py
+++ b/nova/log.py
@@ -40,9 +40,9 @@ import sys
import traceback
import nova
-from nova.common import cfg
from nova import flags
from nova import local
+from nova.openstack.common import cfg
from nova import version
@@ -63,10 +63,6 @@ log_opts = [
cfg.StrOpt('logging_exception_prefix',
default='(%(name)s): TRACE: ',
help='prefix each line of exception output with this format'),
- cfg.StrOpt('logging_debug_format_suffix',
- default='from (pid=%(process)d) %(funcName)s '
- '%(pathname)s:%(lineno)d',
- help='data to append to log format when level is DEBUG'),
cfg.StrOpt('instance_format',
default='[instance: %(uuid)s] ',
help='If an instance is passed with the log message, format '
diff --git a/nova/network/api.py b/nova/network/api.py
index 257c642a9..27e07b869 100644
--- a/nova/network/api.py
+++ b/nova/network/api.py
@@ -99,6 +99,12 @@ class API(base.Base):
{'method': 'get_vifs_by_instance',
'args': {'instance_id': instance['id']}})
+ def get_vif_by_mac_address(self, context, mac_address):
+ return rpc.call(context,
+ FLAGS.network_topic,
+ {'method': 'get_vif_by_mac_address',
+ 'args': {'mac_address': mac_address}})
+
def allocate_floating_ip(self, context, pool=None):
"""Adds a floating ip to a project from a pool. (allocates)"""
# NOTE(vish): We don't know which network host should get the ip
diff --git a/nova/network/ldapdns.py b/nova/network/ldapdns.py
index a5491a259..a6d921186 100644
--- a/nova/network/ldapdns.py
+++ b/nova/network/ldapdns.py
@@ -19,10 +19,10 @@ import tempfile
import time
from nova.auth import fakeldap
-from nova.common import cfg
from nova import exception
from nova import flags
from nova import log as logging
+from nova.openstack.common import cfg
LOG = logging.getLogger("nova.network.manager")
diff --git a/nova/network/linux_net.py b/nova/network/linux_net.py
index 56d07f983..fdfcffb86 100755
--- a/nova/network/linux_net.py
+++ b/nova/network/linux_net.py
@@ -24,11 +24,11 @@ import inspect
import netaddr
import os
-from nova.common import cfg
from nova import db
from nova import exception
from nova import flags
from nova import log as logging
+from nova.openstack.common import cfg
from nova import utils
@@ -944,10 +944,11 @@ class LinuxBridgeInterfaceDriver(LinuxNetInterfaceDriver):
def plug(self, network, mac_address, gateway=True):
if network.get('vlan', None) is not None:
+ iface = FLAGS.vlan_interface or network['bridge_interface']
LinuxBridgeInterfaceDriver.ensure_vlan_bridge(
network['vlan'],
network['bridge'],
- network['bridge_interface'],
+ iface,
network,
mac_address)
else:
diff --git a/nova/network/manager.py b/nova/network/manager.py
index c6d3122b6..053305992 100644
--- a/nova/network/manager.py
+++ b/nova/network/manager.py
@@ -56,7 +56,6 @@ import socket
from eventlet import greenpool
import netaddr
-from nova.common import cfg
from nova.compute import api as compute_api
from nova.compute import instance_types
from nova import context
@@ -68,6 +67,7 @@ from nova import log as logging
from nova import manager
from nova.network import api as network_api
from nova.network import model as network_model
+from nova.openstack.common import cfg
import nova.policy
from nova import quota
from nova import utils
@@ -1476,6 +1476,11 @@ class NetworkManager(manager.SchedulerDependentManager):
fixed = self.db.fixed_ip_get(context, id)
return dict(fixed.iteritems())
+ def get_vif_by_mac_address(self, context, mac_address):
+ """Returns the vifs record for the mac_address"""
+ return self.db.virtual_interface_get_by_address(context,
+ mac_address)
+
class FlatManager(NetworkManager):
"""Basic network where no vlans are used.
diff --git a/nova/network/quantum/client.py b/nova/network/quantum/client.py
index 2e5d6f707..edd214326 100644
--- a/nova/network/quantum/client.py
+++ b/nova/network/quantum/client.py
@@ -44,12 +44,16 @@ class JSONSerializer(object):
def deserialize(self, data, content_type):
return json.loads(data)
+# Quantum API v1.0 uses 420 + 430 for network + port not found
+# Quantum API v1.1 uses 404 for network + port not found
+NOT_FOUND_CODES = set((404, 420, 430))
+
# The full client lib will expose more
# granular exceptions, for now, just try to distinguish
# between the cases we care about.
class QuantumNotFoundException(Exception):
- """Indicates that Quantum Server returned 404"""
+ """Indicates that Quantum Server returned a not-found error code"""
pass
@@ -90,7 +94,7 @@ class api_call(object):
class Client(object):
"""A base client class - derived from Glance.BaseClient"""
- action_prefix = '/v1.0/tenants/{tenant_id}'
+ action_prefix = '/v1.1/tenants/{tenant_id}'
"""Action query strings"""
networks_path = "/networks"
@@ -188,7 +192,7 @@ class Client(object):
self.logger.debug("Quantum Client Reply (code = %s) :\n %s" \
% (str(status_code), data))
- if status_code == httplib.NOT_FOUND:
+ if status_code in NOT_FOUND_CODES:
raise QuantumNotFoundException(
_("Quantum entity not found: %s" % data))
@@ -233,10 +237,18 @@ class Client(object):
format = self.format
return "application/%s" % (format)
+ def append_filter_params(self, url, filter_ops):
+ if len(filter_ops) > 0:
+ url += "?"
+ for fkey, fval in filter_ops.values():
+ url += "%s=%s&" % (fkey, fval)
+
@api_call
- def list_networks(self):
+ def list_networks(self, filter_ops={}):
"""Fetches a list of all networks for a tenant"""
- return self.do_request("GET", self.networks_path)
+ url = self.networks_path
+ self.append_filter_params(url, filter_ops)
+ return self.do_request("GET", url)
@api_call
def show_network_details(self, network):
@@ -261,9 +273,11 @@ class Client(object):
return self.do_request("DELETE", self.network_path % (network))
@api_call
- def list_ports(self, network):
+ def list_ports(self, network, filter_ops={}):
"""Fetches a list of ports on a given network"""
- return self.do_request("GET", self.ports_path % (network))
+ url = self.ports_path % (network)
+ self.append_filter_params(url, filter_ops)
+ return self.do_request("GET", url)
@api_call
def show_port_details(self, network, port):
diff --git a/nova/network/quantum/manager.py b/nova/network/quantum/manager.py
index 518676be0..8f2aa0a4a 100644
--- a/nova/network/quantum/manager.py
+++ b/nova/network/quantum/manager.py
@@ -19,7 +19,6 @@ import time
from netaddr import IPNetwork, IPAddress
-from nova.common import cfg
from nova.compute import instance_types
from nova import context
from nova import db
@@ -29,6 +28,7 @@ from nova import log as logging
from nova.network import manager
from nova.network.quantum import melange_ipam_lib
from nova.network.quantum import quantum_connection
+from nova.openstack.common import cfg
from nova import utils
LOG = logging.getLogger("nova.network.quantum.manager")
@@ -474,11 +474,12 @@ class QuantumManager(manager.FloatingIP, manager.FlatManager):
if vif.get('network_id') is not None:
network = db.network_get(admin_context, vif['network_id'])
net_tenant_id = net_tenant_dict[network['uuid']]
+ if net_tenant_id is None:
+ net_tenant_id = FLAGS.quantum_default_tenant_id
network = {'id': network['id'],
'uuid': network['uuid'],
- 'bridge': 'ovs_flag',
- 'label': self.q_conn.get_network_name(net_tenant_id,
- network['uuid']),
+ 'bridge': '', # Quantum ignores this field
+ 'label': network['label'],
'project_id': net_tenant_id}
networks[vif['uuid']] = network
@@ -538,6 +539,7 @@ class QuantumManager(manager.FloatingIP, manager.FlatManager):
self.ipam.deallocate_ips_by_vif(context, ipam_tenant_id,
net_id, vif_ref)
+ db.virtual_interface_delete(admin_context, vif_ref['id'])
# If DHCP is enabled on this network then we need to update the
# leases and restart the server.
@@ -551,13 +553,6 @@ class QuantumManager(manager.FloatingIP, manager.FlatManager):
'|%(instance_id)s|, vif_uuid: |%(vif_uuid)s|')
LOG.critical(msg % locals)
- try:
- db.virtual_interface_delete_by_instance(admin_context,
- instance_id)
- except exception.InstanceNotFound:
- LOG.error(_("Attempted to deallocate non-existent instance: %s" %
- (instance_id)))
-
# TODO(bgh): At some point we should consider merging enable_dhcp() and
# update_dhcp()
# TODO(tr3buchet): agree, i'm curious why they differ even now..
diff --git a/nova/network/quantum/melange_connection.py b/nova/network/quantum/melange_connection.py
index 499ace6b3..c7e3c606d 100644
--- a/nova/network/quantum/melange_connection.py
+++ b/nova/network/quantum/melange_connection.py
@@ -20,9 +20,9 @@ import socket
import urllib
import json
-from nova.common import cfg
from nova import flags
from nova import log as logging
+from nova.openstack.common import cfg
melange_opts = [
diff --git a/nova/network/quantum/quantum_connection.py b/nova/network/quantum/quantum_connection.py
index 914b816d1..ba34d026c 100644
--- a/nova/network/quantum/quantum_connection.py
+++ b/nova/network/quantum/quantum_connection.py
@@ -15,10 +15,10 @@
# License for the specific language governing permissions and limitations
# under the License.
-from nova.common import cfg
from nova import flags
from nova import log as logging
from nova.network.quantum import client as quantum_client
+from nova.openstack.common import cfg
LOG = logging.getLogger("nova.network.quantum.quantum_connection")
@@ -117,18 +117,21 @@ class QuantumClientConnection(object):
"""Given a tenant and network, search for the port UUID that
has the specified interface-id attachment.
"""
- # FIXME(danwent): this will be inefficient until the Quantum
- # API implements querying a port by the interface-id
- port_list_resdict = self.client.list_ports(net_id, tenant=tenant_id)
- for p in port_list_resdict["ports"]:
- port_id = p["id"]
- port_get_resdict = self.client.show_port_attachment(net_id,
- port_id, tenant=tenant_id)
- # Skip ports without an attachment
- if "id" not in port_get_resdict["attachment"]:
- continue
- if attachment_id == port_get_resdict["attachment"]["id"]:
- return port_id
+ port_list = []
+ try:
+ port_list_resdict = self.client.list_ports(net_id,
+ tenant=tenant_id,
+ filter_ops={'attachment': attachment_id})
+ port_list = port_list_resdict["ports"]
+ except quantum_client.QuantumNotFoundException:
+ return None
+
+ port_list_len = len(port_list)
+ if port_list_len != 1:
+ LOG.error("Expected single port with attachment "
+ "%(attachment_id)s, found %(port_list_len)s" % locals())
+ if port_list_len >= 1:
+ return port_list[0]['id']
return None
def get_attached_ports(self, tenant_id, network_id):
diff --git a/nova/notifier/api.py b/nova/notifier/api.py
index 50730cb0f..4a59e0ba1 100644
--- a/nova/notifier/api.py
+++ b/nova/notifier/api.py
@@ -15,10 +15,10 @@
import uuid
-from nova.common import cfg
from nova import flags
from nova import utils
from nova import log as logging
+from nova.openstack.common import cfg
LOG = logging.getLogger('nova.exception')
diff --git a/nova/notifier/list_notifier.py b/nova/notifier/list_notifier.py
index 29c6ba720..d952b613e 100644
--- a/nova/notifier/list_notifier.py
+++ b/nova/notifier/list_notifier.py
@@ -13,9 +13,9 @@
# License for the specific language governing permissions and limitations
# under the License.
-from nova.common import cfg
from nova import flags
from nova import log as logging
+from nova.openstack.common import cfg
from nova import utils
from nova.exception import ClassNotFound
diff --git a/nova/notifier/rabbit_notifier.py b/nova/notifier/rabbit_notifier.py
index c88f76cb0..25956c611 100644
--- a/nova/notifier/rabbit_notifier.py
+++ b/nova/notifier/rabbit_notifier.py
@@ -16,8 +16,8 @@
import nova.context
-from nova.common import cfg
from nova import flags
+from nova.openstack.common import cfg
from nova import rpc
diff --git a/nova/objectstore/s3server.py b/nova/objectstore/s3server.py
index 1ba8d44cf..e5217b4b9 100644
--- a/nova/objectstore/s3server.py
+++ b/nova/objectstore/s3server.py
@@ -44,9 +44,9 @@ import urllib
import routes
import webob
-from nova.common import cfg
from nova import flags
from nova import log as logging
+from nova.openstack.common import cfg
from nova import utils
from nova import wsgi
diff --git a/nova/openstack/__init__.py b/nova/openstack/__init__.py
new file mode 100644
index 000000000..0a3b98867
--- /dev/null
+++ b/nova/openstack/__init__.py
@@ -0,0 +1,15 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright (c) 2011 Red Hat, Inc.
+#
+# 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.
diff --git a/nova/openstack/common/__init__.py b/nova/openstack/common/__init__.py
new file mode 100644
index 000000000..0a3b98867
--- /dev/null
+++ b/nova/openstack/common/__init__.py
@@ -0,0 +1,15 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright (c) 2011 Red Hat, Inc.
+#
+# 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.
diff --git a/nova/common/cfg.py b/nova/openstack/common/cfg.py
index bfb7b8a19..bfb7b8a19 100644
--- a/nova/common/cfg.py
+++ b/nova/openstack/common/cfg.py
diff --git a/nova/policy.py b/nova/policy.py
index ccf1f4624..09b3ab988 100644
--- a/nova/policy.py
+++ b/nova/policy.py
@@ -17,10 +17,10 @@
"""Policy Engine For Nova"""
-from nova.common import cfg
from nova.common import policy
from nova import exception
from nova import flags
+from nova.openstack.common import cfg
from nova import utils
diff --git a/nova/quota.py b/nova/quota.py
index 95fa317d5..4a5eac4b4 100644
--- a/nova/quota.py
+++ b/nova/quota.py
@@ -18,8 +18,8 @@
"""Quotas for instances, volumes, and floating ips."""
-from nova.common import cfg
from nova import db
+from nova.openstack.common import cfg
from nova import flags
@@ -110,9 +110,13 @@ def allowed_instances(context, requested_instances, instance_type):
allowed_cores = _get_request_allotment(requested_cores, used_cores,
quota['cores'])
allowed_ram = _get_request_allotment(requested_ram, used_ram, quota['ram'])
- allowed_instances = min(allowed_instances,
- allowed_cores // instance_type['vcpus'],
- allowed_ram // instance_type['memory_mb'])
+ if instance_type['vcpus']:
+ allowed_instances = min(allowed_instances,
+ allowed_cores // instance_type['vcpus'])
+ if instance_type['memory_mb']:
+ allowed_instances = min(allowed_instances,
+ allowed_ram // instance_type['memory_mb'])
+
return min(requested_instances, allowed_instances)
diff --git a/nova/rootwrap/compute.py b/nova/rootwrap/compute.py
index 8b7736cbd..65e6dfebb 100755
--- a/nova/rootwrap/compute.py
+++ b/nova/rootwrap/compute.py
@@ -168,4 +168,7 @@ filterlist = [
# nova/virt/libvirt/utils.py: 'mkswap'
# nova/virt/xenapi/vm_utils.py: 'mkswap'
filters.CommandFilter("/sbin/mkswap", "root"),
+
+ # nova/virt/libvirt/connection.py:
+ filters.ReadFileFilter("/etc/iscsi/initiatorname.iscsi"),
]
diff --git a/nova/rootwrap/filters.py b/nova/rootwrap/filters.py
index d16fc9a57..faaeb11f7 100755
--- a/nova/rootwrap/filters.py
+++ b/nova/rootwrap/filters.py
@@ -123,3 +123,20 @@ class KillFilter(CommandFilter):
# Incorrect PID
return False
return True
+
+
+class ReadFileFilter(CommandFilter):
+ """Specific filter for the utils.read_file_as_root call"""
+
+ def __init__(self, file_path, *args):
+ self.file_path = file_path
+ super(ReadFileFilter, self).__init__("/bin/cat", "root", *args)
+
+ def match(self, userargs):
+ if userargs[0] != 'cat':
+ return False
+ if userargs[1] != self.file_path:
+ return False
+ if len(userargs) != 2:
+ return False
+ return True
diff --git a/nova/rpc/__init__.py b/nova/rpc/__init__.py
index a6067432e..7c6ed29d0 100644
--- a/nova/rpc/__init__.py
+++ b/nova/rpc/__init__.py
@@ -17,10 +17,10 @@
# License for the specific language governing permissions and limitations
# under the License.
-from nova.common import cfg
-from nova.utils import import_object
-from nova.rpc.common import RemoteError, LOG
from nova import flags
+from nova.openstack.common import cfg
+from nova.rpc.common import RemoteError, LOG
+from nova.utils import import_object
rpc_backend_opt = \
diff --git a/nova/rpc/common.py b/nova/rpc/common.py
index 70d5d07ba..696639e03 100644
--- a/nova/rpc/common.py
+++ b/nova/rpc/common.py
@@ -19,10 +19,10 @@
import copy
-from nova.common import cfg
from nova import exception
from nova import flags
from nova import log as logging
+from nova.openstack.common import cfg
LOG = logging.getLogger('nova.rpc')
diff --git a/nova/rpc/impl_qpid.py b/nova/rpc/impl_qpid.py
index 353c7e502..1ed20ba81 100644
--- a/nova/rpc/impl_qpid.py
+++ b/nova/rpc/impl_qpid.py
@@ -25,8 +25,8 @@ import greenlet
import qpid.messaging
import qpid.messaging.exceptions
-from nova.common import cfg
from nova import flags
+from nova.openstack.common import cfg
from nova.rpc import amqp as rpc_amqp
from nova.rpc import common as rpc_common
from nova.rpc.common import LOG
diff --git a/nova/scheduler/api.py b/nova/scheduler/api.py
index c814ad664..814e45c6f 100644
--- a/nova/scheduler/api.py
+++ b/nova/scheduler/api.py
@@ -22,11 +22,11 @@ import functools
from novaclient import v1_1 as novaclient
from novaclient import exceptions as novaclient_exceptions
-from nova.common import cfg
from nova import db
from nova import exception
from nova import flags
from nova import log as logging
+from nova.openstack.common import cfg
from nova import rpc
from nova import utils
diff --git a/nova/scheduler/driver.py b/nova/scheduler/driver.py
index 5af98485d..f73eebc52 100644
--- a/nova/scheduler/driver.py
+++ b/nova/scheduler/driver.py
@@ -22,7 +22,6 @@ Scheduler base class that all Schedulers should inherit from
"""
from nova.api.ec2 import ec2utils
-from nova.common import cfg
from nova.compute import api as compute_api
from nova.compute import power_state
from nova.compute import vm_states
@@ -30,6 +29,7 @@ from nova import db
from nova import exception
from nova import flags
from nova import log as logging
+from nova.openstack.common import cfg
from nova import rpc
from nova.scheduler import host_manager
from nova.scheduler import zone_manager
diff --git a/nova/scheduler/filters/core_filter.py b/nova/scheduler/filters/core_filter.py
index d76eceeef..5afc63c24 100644
--- a/nova/scheduler/filters/core_filter.py
+++ b/nova/scheduler/filters/core_filter.py
@@ -15,9 +15,9 @@
# License for the specific language governing permissions and limitations
# under the License.
-from nova.common import cfg
from nova import flags
from nova import log as logging
+from nova.openstack.common import cfg
from nova.scheduler.filters import abstract_filter
diff --git a/nova/scheduler/filters/ram_filter.py b/nova/scheduler/filters/ram_filter.py
index 67c9f72b8..8bae04949 100644
--- a/nova/scheduler/filters/ram_filter.py
+++ b/nova/scheduler/filters/ram_filter.py
@@ -14,9 +14,9 @@
# License for the specific language governing permissions and limitations
# under the License.
-from nova.common import cfg
from nova import flags
from nova import log as logging
+from nova.openstack.common import cfg
from nova.scheduler.filters import abstract_filter
LOG = logging.getLogger('nova.scheduler.filter.ram_filter')
diff --git a/nova/scheduler/host_manager.py b/nova/scheduler/host_manager.py
index a56f154fc..925a8637a 100644
--- a/nova/scheduler/host_manager.py
+++ b/nova/scheduler/host_manager.py
@@ -21,11 +21,11 @@ import datetime
import types
import UserDict
-from nova.common import cfg
from nova import db
from nova import exception
from nova import flags
from nova import log as logging
+from nova.openstack.common import cfg
from nova import utils
diff --git a/nova/scheduler/least_cost.py b/nova/scheduler/least_cost.py
index 90ba4c2a0..4711ac4f3 100644
--- a/nova/scheduler/least_cost.py
+++ b/nova/scheduler/least_cost.py
@@ -22,8 +22,8 @@ The cost-function and weights are tabulated, and the host with the least cost
is then selected for provisioning.
"""
-from nova.common import cfg
from nova import flags
+from nova.openstack.common import cfg
from nova import log as logging
diff --git a/nova/scheduler/manager.py b/nova/scheduler/manager.py
index dc1b2c56a..e4eb08d11 100644
--- a/nova/scheduler/manager.py
+++ b/nova/scheduler/manager.py
@@ -23,13 +23,13 @@ Scheduler Service
import functools
-from nova.common import cfg
from nova.compute import vm_states
from nova import db
from nova import exception
from nova import flags
from nova import log as logging
from nova import manager
+from nova.openstack.common import cfg
from nova import rpc
from nova import utils
diff --git a/nova/scheduler/multi.py b/nova/scheduler/multi.py
index 3bc67052f..08d4bf0e6 100644
--- a/nova/scheduler/multi.py
+++ b/nova/scheduler/multi.py
@@ -21,8 +21,8 @@
Scheduler that allows routing some calls to one driver and others to another.
"""
-from nova.common import cfg
from nova import flags
+from nova.openstack.common import cfg
from nova import utils
from nova.scheduler import driver
diff --git a/nova/scheduler/scheduler_options.py b/nova/scheduler/scheduler_options.py
index 0a6086fc6..63a77d08d 100644
--- a/nova/scheduler/scheduler_options.py
+++ b/nova/scheduler/scheduler_options.py
@@ -24,9 +24,9 @@ import datetime
import json
import os
-from nova.common import cfg
from nova import flags
from nova import log as logging
+from nova.openstack.common import cfg
scheduler_json_config_location_opt = \
diff --git a/nova/scheduler/simple.py b/nova/scheduler/simple.py
index e913730c7..94db0a475 100644
--- a/nova/scheduler/simple.py
+++ b/nova/scheduler/simple.py
@@ -21,10 +21,10 @@
Simple Scheduler
"""
-from nova.common import cfg
from nova import db
from nova import flags
from nova import exception
+from nova.openstack.common import cfg
from nova.scheduler import driver
from nova.scheduler import chance
from nova import utils
diff --git a/nova/scheduler/vsa.py b/nova/scheduler/vsa.py
index 989841d37..ee50ae978 100644
--- a/nova/scheduler/vsa.py
+++ b/nova/scheduler/vsa.py
@@ -19,11 +19,11 @@
VSA Simple Scheduler
"""
-from nova.common import cfg
from nova import context
from nova import db
from nova import flags
from nova import log as logging
+from nova.openstack.common import cfg
from nova import rpc
from nova import utils
from nova import exception
diff --git a/nova/scheduler/zone_manager.py b/nova/scheduler/zone_manager.py
index c27e6bdbe..e94039a6b 100644
--- a/nova/scheduler/zone_manager.py
+++ b/nova/scheduler/zone_manager.py
@@ -23,10 +23,10 @@ import traceback
from eventlet import greenpool
from novaclient import v1_1 as novaclient
-from nova.common import cfg
from nova import db
from nova import flags
from nova import log as logging
+from nova.openstack.common import cfg
from nova import utils
diff --git a/nova/service.py b/nova/service.py
index 56f706c4b..fc62a3b08 100644
--- a/nova/service.py
+++ b/nova/service.py
@@ -25,12 +25,12 @@ import os
import eventlet
import greenlet
-from nova.common import cfg
from nova import context
from nova import db
from nova import exception
from nova import flags
from nova import log as logging
+from nova.openstack.common import cfg
from nova import rpc
from nova import utils
from nova import version
diff --git a/nova/test.py b/nova/test.py
index f8e9c390f..7fe4b4abb 100644
--- a/nova/test.py
+++ b/nova/test.py
@@ -33,10 +33,10 @@ import mox
import nose.plugins.skip
import stubout
-from nova.common import cfg
from nova import flags
import nova.image.fake
from nova import log
+from nova.openstack.common import cfg
from nova import utils
from nova import service
from nova.testing.fake import rabbit
diff --git a/nova/tests/api/openstack/compute/contrib/test_hosts.py b/nova/tests/api/openstack/compute/contrib/test_hosts.py
index 925dc0d53..a16b8a5f5 100644
--- a/nova/tests/api/openstack/compute/contrib/test_hosts.py
+++ b/nova/tests/api/openstack/compute/contrib/test_hosts.py
@@ -184,17 +184,6 @@ class HostTestCase(test.TestCase):
self.controller.show,
self.req, dest)
- def _dic_is_equal(self, dic1, dic2, keys=None):
- """Compares 2 dictionary contents(Helper method)"""
- if not keys:
- keys = ['vcpus', 'memory_mb', 'local_gb',
- 'vcpus_used', 'memory_mb_used', 'local_gb_used']
-
- for key in keys:
- if not (dic1[key] == dic2[key]):
- return False
- return True
-
def _create_compute_service(self):
"""Create compute-manager(ComputeNode and Service record)."""
ctxt = context.get_admin_context()
@@ -218,14 +207,13 @@ class HostTestCase(test.TestCase):
result = self.controller.show(self.req, s_ref['host'])
- # result checking
- c1 = ('resource' in result['host'] and
- 'usage' in result['host'])
- compute_node = s_ref['compute_node'][0]
- c2 = self._dic_is_equal(result['host']['resource'],
- compute_node)
- c3 = result['host']['usage'] == {}
- self.assertTrue(c1 and c2 and c3)
+ proj = ['(total)', '(used_now)', '(used_max)']
+ column = ['host', 'project', 'cpu', 'memory_mb', 'disk_gb']
+ self.assertEqual(len(result['host']), 3)
+ for resource in result['host']:
+ self.assertTrue(resource['resource']['project'] in proj)
+ self.assertEqual(len(resource['resource']), 5)
+ self.assertTrue(set(resource['resource'].keys()) == set(column))
db.service_destroy(ctxt, s_ref['id'])
def test_show_works_correctly(self):
@@ -238,28 +226,13 @@ class HostTestCase(test.TestCase):
result = self.controller.show(self.req, s_ref['host'])
- c1 = ('resource' in result['host'] and
- 'usage' in result['host'])
- compute_node = s_ref['compute_node'][0]
- c2 = self._dic_is_equal(result['host']['resource'],
- compute_node)
- c3 = result['host']['usage'].keys() == ['p-01', 'p-02']
- keys = ['vcpus', 'memory_mb']
- c4 = self._dic_is_equal(
- result['host']['usage']['p-01'], i_ref1, keys)
- disk = i_ref2['root_gb'] + i_ref2['ephemeral_gb']
- if result['host']['usage']['p-01']['local_gb'] == disk:
- c6 = True
- else:
- c6 = False
- c5 = self._dic_is_equal(
- result['host']['usage']['p-02'], i_ref2, keys)
- if result['host']['usage']['p-02']['local_gb'] == disk:
- c7 = True
- else:
- c7 = False
- self.assertTrue(c1 and c2 and c3 and c4 and c5 and c6 and c7)
-
+ proj = ['(total)', '(used_now)', '(used_max)', 'p-01', 'p-02']
+ column = ['host', 'project', 'cpu', 'memory_mb', 'disk_gb']
+ self.assertEqual(len(result['host']), 5)
+ for resource in result['host']:
+ self.assertTrue(resource['resource']['project'] in proj)
+ self.assertEqual(len(resource['resource']), 5)
+ self.assertTrue(set(resource['resource'].keys()) == set(column))
db.service_destroy(ctxt, s_ref['id'])
db.instance_destroy(ctxt, i_ref1['id'])
db.instance_destroy(ctxt, i_ref2['id'])
diff --git a/nova/tests/api/openstack/compute/test_flavors.py b/nova/tests/api/openstack/compute/test_flavors.py
index 8ad5eea0c..465a57497 100644
--- a/nova/tests/api/openstack/compute/test_flavors.py
+++ b/nova/tests/api/openstack/compute/test_flavors.py
@@ -24,11 +24,15 @@ from nova.api.openstack.compute import flavors
from nova.api.openstack import xmlutil
import nova.compute.instance_types
from nova import exception
+from nova import flags
from nova import test
from nova import utils
from nova.tests.api.openstack import fakes
+FLAGS = flags.FLAGS
+
+
NS = "{http://docs.openstack.org/compute/api/v1.1}"
ATOMNS = "{http://www.w3.org/2005/Atom}"
@@ -130,6 +134,34 @@ class FlavorsTest(test.TestCase):
}
self.assertEqual(flavor, expected)
+ def test_get_flavor_with_custom_link_prefix(self):
+ self.flags(osapi_compute_link_prefix='http://zoo.com:42',
+ osapi_glance_link_prefix='http://circus.com:34')
+ req = fakes.HTTPRequest.blank('/v2/fake/flavors/1')
+ flavor = self.controller.show(req, '1')
+ expected = {
+ "flavor": {
+ "id": "1",
+ "name": "flavor 1",
+ "ram": "256",
+ "disk": "10",
+ "rxtx_factor": "",
+ "swap": "",
+ "vcpus": "",
+ "links": [
+ {
+ "rel": "self",
+ "href": "http://zoo.com:42/v2/fake/flavors/1",
+ },
+ {
+ "rel": "bookmark",
+ "href": "http://zoo.com:42/fake/flavors/1",
+ },
+ ],
+ },
+ }
+ self.assertEqual(flavor, expected)
+
def test_get_flavor_list(self):
req = fakes.HTTPRequest.blank('/v2/fake/flavors')
flavor = self.controller.index(req)
diff --git a/nova/tests/api/openstack/compute/test_images.py b/nova/tests/api/openstack/compute/test_images.py
index 893574241..460bf437f 100644
--- a/nova/tests/api/openstack/compute/test_images.py
+++ b/nova/tests/api/openstack/compute/test_images.py
@@ -26,6 +26,7 @@ from lxml import etree
import stubout
import webob
+from nova import flags
from nova.api.openstack.compute import images
from nova.api.openstack.compute.views import images as images_view
from nova.api.openstack import xmlutil
@@ -34,6 +35,9 @@ from nova import utils
from nova.tests.api.openstack import fakes
+FLAGS = flags.FLAGS
+
+
NS = "{http://docs.openstack.org/compute/api/v1.1}"
ATOMNS = "{http://www.w3.org/2005/Atom}"
NOW_API_FORMAT = "2010-10-11T10:30:22Z"
@@ -117,6 +121,60 @@ class ImagesControllerTest(test.TestCase):
self.assertDictMatch(expected_image, actual_image)
+ def test_get_image_with_custom_prefix(self):
+ self.flags(osapi_compute_link_prefix='http://zoo.com:42',
+ osapi_glance_link_prefix='http://circus.com:34')
+ fake_req = fakes.HTTPRequest.blank('/v2/fake/images/123')
+ actual_image = self.controller.show(fake_req, '124')
+ href = "http://zoo.com:42/v2/fake/images/124"
+ bookmark = "http://zoo.com:42/fake/images/124"
+ alternate = "http://circus.com:34/fake/images/124"
+ server_uuid = "aa640691-d1a7-4a67-9d3c-d35ee6b3cc74"
+ server_href = "http://localhost/v2/servers/" + server_uuid
+ server_bookmark = "http://localhost/servers/" + server_uuid
+
+ expected_image = {
+ "image": {
+ "id": "124",
+ "name": "queued snapshot",
+ "updated": NOW_API_FORMAT,
+ "created": NOW_API_FORMAT,
+ "status": "SAVING",
+ "progress": 25,
+ "minDisk": 0,
+ "minRam": 0,
+ 'server': {
+ 'id': server_uuid,
+ "links": [{
+ "rel": "self",
+ "href": server_href,
+ },
+ {
+ "rel": "bookmark",
+ "href": server_bookmark,
+ }],
+ },
+ "metadata": {
+ "instance_uuid": server_uuid,
+ "user_id": "fake",
+ },
+ "links": [{
+ "rel": "self",
+ "href": href,
+ },
+ {
+ "rel": "bookmark",
+ "href": bookmark,
+ },
+ {
+ "rel": "alternate",
+ "type": "application/vnd.openstack.image",
+ "href": alternate
+ }],
+ },
+ }
+ self.assertDictMatch(expected_image, actual_image)
+
def test_get_image_404(self):
fake_req = fakes.HTTPRequest.blank('/v2/fake/images/unknown')
self.assertRaises(webob.exc.HTTPNotFound,
diff --git a/nova/tests/api/test_auth.py b/nova/tests/api/test_auth.py
new file mode 100644
index 000000000..0625957f7
--- /dev/null
+++ b/nova/tests/api/test_auth.py
@@ -0,0 +1,60 @@
+# Copyright (c) 2012 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 webob
+
+import nova.api.auth
+from nova import test
+
+
+class TestNovaKeystoneContextMiddleware(test.TestCase):
+
+ def setUp(self):
+
+ @webob.dec.wsgify()
+ def fake_app(req):
+ self.context = req.environ['nova.context']
+ return webob.Response()
+
+ self.context = None
+ self.middleware = nova.api.auth.NovaKeystoneContext(fake_app)
+ self.request = webob.Request.blank('/')
+ self.request.headers['X_TENANT_ID'] = 'testtenantid'
+ self.request.headers['X_AUTH_TOKEN'] = 'testauthtoken'
+
+ def tearDown(self):
+ pass
+
+ def test_no_user_or_user_id(self):
+ response = self.request.get_response(self.middleware)
+ self.assertEqual(response.status, '401 Unauthorized')
+
+ def test_user_only(self):
+ self.request.headers['X_USER_ID'] = 'testuserid'
+ response = self.request.get_response(self.middleware)
+ self.assertEqual(response.status, '200 OK')
+ self.assertEqual(self.context.user_id, 'testuserid')
+
+ def test_user_id_only(self):
+ self.request.headers['X_USER'] = 'testuser'
+ response = self.request.get_response(self.middleware)
+ self.assertEqual(response.status, '200 OK')
+ self.assertEqual(self.context.user_id, 'testuser')
+
+ def test_user_id_trumps_user(self):
+ self.request.headers['X_USER_ID'] = 'testuserid'
+ self.request.headers['X_USER'] = 'testuser'
+ response = self.request.get_response(self.middleware)
+ self.assertEqual(response.status, '200 OK')
+ self.assertEqual(self.context.user_id, 'testuserid')
diff --git a/nova/tests/declare_flags.py b/nova/tests/declare_flags.py
index 9dc578867..cb6726a7c 100644
--- a/nova/tests/declare_flags.py
+++ b/nova/tests/declare_flags.py
@@ -16,8 +16,8 @@
# License for the specific language governing permissions and limitations
# under the License.
-from nova.common import cfg
from nova import flags
+from nova.openstack.common import cfg
FLAGS = flags.FLAGS
FLAGS.add_option(cfg.IntOpt('answer', default=42, help='test flag'))
diff --git a/nova/tests/fake_libvirt_utils.py b/nova/tests/fake_libvirt_utils.py
index f1d4a8ec7..27b753a64 100644
--- a/nova/tests/fake_libvirt_utils.py
+++ b/nova/tests/fake_libvirt_utils.py
@@ -21,6 +21,10 @@ disk_sizes = {}
disk_backing_files = {}
+def get_iscsi_initiator():
+ return "fake.initiator.iqn"
+
+
def create_image(disk_format, path, size):
pass
diff --git a/nova/tests/runtime_flags.py b/nova/tests/runtime_flags.py
index 1a28f4fbd..279d51162 100644
--- a/nova/tests/runtime_flags.py
+++ b/nova/tests/runtime_flags.py
@@ -16,8 +16,8 @@
# License for the specific language governing permissions and limitations
# under the License.
-from nova.common import cfg
from nova import flags
+from nova.openstack.common import cfg
FLAGS = flags.FLAGS
FLAGS.add_option(cfg.IntOpt('runtime_answer', default=54, help='test flag'))
diff --git a/nova/tests/test_cfg.py b/nova/tests/test_cfg.py
deleted file mode 100644
index 6d02134e1..000000000
--- a/nova/tests/test_cfg.py
+++ /dev/null
@@ -1,789 +0,0 @@
-# vim: tabstop=4 shiftwidth=4 softtabstop=4
-
-# Copyright 2011 Red Hat, Inc.
-#
-# 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 sys
-import StringIO
-import tempfile
-
-import stubout
-
-from nova import test
-from nova.common.cfg import *
-
-
-class BaseTestCase(test.TestCase):
-
- def setUp(self):
- self.conf = ConfigOpts(prog='test',
- version='1.0',
- usage='%prog FOO BAR',
- default_config_files=[])
- self.tempfiles = []
- self.stubs = stubout.StubOutForTesting()
-
- def tearDown(self):
- self.remove_tempfiles()
- self.stubs.UnsetAll()
-
- def create_tempfiles(self, files):
- for (basename, contents) in files:
- (fd, path) = tempfile.mkstemp(prefix=basename)
- self.tempfiles.append(path)
- try:
- os.write(fd, contents)
- finally:
- os.close(fd)
- return self.tempfiles[-len(files):]
-
- def remove_tempfiles(self):
- for p in self.tempfiles:
- os.remove(p)
-
-
-class LeftoversTestCase(BaseTestCase):
-
- def test_leftovers(self):
- self.conf.register_cli_opt(StrOpt('foo'))
- self.conf.register_cli_opt(StrOpt('bar'))
-
- leftovers = self.conf(['those', '--foo', 'this',
- 'thems', '--bar', 'that', 'these'])
-
- self.assertEquals(leftovers, ['those', 'thems', 'these'])
-
-
-class FindConfigFilesTestCase(BaseTestCase):
-
- def test_find_config_files(self):
- config_files = \
- [os.path.expanduser('~/.blaa/blaa.conf'), '/etc/foo.conf']
-
- self.stubs.Set(os.path, 'exists', lambda p: p in config_files)
-
- self.assertEquals(find_config_files(project='blaa', prog='foo'),
- config_files)
-
-
-class CliOptsTestCase(BaseTestCase):
-
- def _do_cli_test(self, opt_class, default, cli_args, value):
- self.conf.register_cli_opt(opt_class('foo', default=default))
-
- self.conf(cli_args)
-
- self.assertTrue(hasattr(self.conf, 'foo'))
- self.assertEquals(self.conf.foo, value)
-
- def test_str_default(self):
- self._do_cli_test(StrOpt, None, [], None)
-
- def test_str_arg(self):
- self._do_cli_test(StrOpt, None, ['--foo', 'bar'], 'bar')
-
- def test_bool_default(self):
- self._do_cli_test(BoolOpt, False, [], False)
-
- def test_bool_arg(self):
- self._do_cli_test(BoolOpt, None, ['--foo'], True)
-
- def test_bool_arg_inverse(self):
- self._do_cli_test(BoolOpt, None, ['--foo', '--nofoo'], False)
-
- def test_int_default(self):
- self._do_cli_test(IntOpt, 10, [], 10)
-
- def test_int_arg(self):
- self._do_cli_test(IntOpt, None, ['--foo=20'], 20)
-
- def test_float_default(self):
- self._do_cli_test(FloatOpt, 1.0, [], 1.0)
-
- def test_float_arg(self):
- self._do_cli_test(FloatOpt, None, ['--foo', '2.0'], 2.0)
-
- def test_list_default(self):
- self._do_cli_test(ListOpt, ['bar'], [], ['bar'])
-
- def test_list_arg(self):
- self._do_cli_test(ListOpt, None,
- ['--foo', 'blaa,bar'], ['blaa', 'bar'])
-
- def test_multistr_default(self):
- self._do_cli_test(MultiStrOpt, ['bar'], [], ['bar'])
-
- def test_multistr_arg(self):
- self._do_cli_test(MultiStrOpt, None,
- ['--foo', 'blaa', '--foo', 'bar'], ['blaa', 'bar'])
-
- def test_help(self):
- self.stubs.Set(sys, 'stdout', StringIO.StringIO())
- self.assertRaises(SystemExit, self.conf, ['--help'])
- self.assertTrue('FOO BAR' in sys.stdout.getvalue())
- self.assertTrue('--version' in sys.stdout.getvalue())
- self.assertTrue('--help' in sys.stdout.getvalue())
- self.assertTrue('--config-file=PATH' in sys.stdout.getvalue())
-
- def test_version(self):
- self.stubs.Set(sys, 'stdout', StringIO.StringIO())
- self.assertRaises(SystemExit, self.conf, ['--version'])
- self.assertTrue('1.0' in sys.stdout.getvalue())
-
- def test_config_file(self):
- paths = self.create_tempfiles([('1.conf', '[DEFAULT]'),
- ('2.conf', '[DEFAULT]')])
-
- self.conf(['--config-file', paths[0], '--config-file', paths[1]])
-
- self.assertEquals(self.conf.config_file, paths)
-
-
-class ConfigFileOptsTestCase(BaseTestCase):
-
- def test_conf_file_str_default(self):
- self.conf.register_opt(StrOpt('foo', default='bar'))
-
- paths = self.create_tempfiles([('test.conf',
- '[DEFAULT]\n')])
-
- self.conf(['--config-file', paths[0]])
-
- self.assertTrue(hasattr(self.conf, 'foo'))
- self.assertEquals(self.conf.foo, 'bar')
-
- def test_conf_file_str_value(self):
- self.conf.register_opt(StrOpt('foo'))
-
- paths = self.create_tempfiles([('test.conf',
- '[DEFAULT]\n'
- 'foo = bar\n')])
-
- self.conf(['--config-file', paths[0]])
-
- self.assertTrue(hasattr(self.conf, 'foo'))
- self.assertEquals(self.conf.foo, 'bar')
-
- def test_conf_file_str_value_override(self):
- self.conf.register_cli_opt(StrOpt('foo'))
-
- paths = self.create_tempfiles([('1.conf',
- '[DEFAULT]\n'
- 'foo = baar\n'),
- ('2.conf',
- '[DEFAULT]\n'
- 'foo = baaar\n')])
-
- self.conf(['--foo', 'bar',
- '--config-file', paths[0],
- '--config-file', paths[1]])
-
- self.assertTrue(hasattr(self.conf, 'foo'))
- self.assertEquals(self.conf.foo, 'baaar')
-
- def test_conf_file_int_default(self):
- self.conf.register_opt(IntOpt('foo', default=666))
-
- paths = self.create_tempfiles([('test.conf',
- '[DEFAULT]\n')])
-
- self.conf(['--config-file', paths[0]])
-
- self.assertTrue(hasattr(self.conf, 'foo'))
- self.assertEquals(self.conf.foo, 666)
-
- def test_conf_file_int_value(self):
- self.conf.register_opt(IntOpt('foo'))
-
- paths = self.create_tempfiles([('test.conf',
- '[DEFAULT]\n'
- 'foo = 666\n')])
-
- self.conf(['--config-file', paths[0]])
-
- self.assertTrue(hasattr(self.conf, 'foo'))
- self.assertEquals(self.conf.foo, 666)
-
- def test_conf_file_int_value_override(self):
- self.conf.register_cli_opt(IntOpt('foo'))
-
- paths = self.create_tempfiles([('1.conf',
- '[DEFAULT]\n'
- 'foo = 66\n'),
- ('2.conf',
- '[DEFAULT]\n'
- 'foo = 666\n')])
-
- self.conf(['--foo', '6',
- '--config-file', paths[0],
- '--config-file', paths[1]])
-
- self.assertTrue(hasattr(self.conf, 'foo'))
- self.assertEquals(self.conf.foo, 666)
-
- def test_conf_file_float_default(self):
- self.conf.register_opt(FloatOpt('foo', default=6.66))
-
- paths = self.create_tempfiles([('test.conf',
- '[DEFAULT]\n')])
-
- self.conf(['--config-file', paths[0]])
-
- self.assertTrue(hasattr(self.conf, 'foo'))
- self.assertEquals(self.conf.foo, 6.66)
-
- def test_conf_file_float_value(self):
- self.conf.register_opt(FloatOpt('foo'))
-
- paths = self.create_tempfiles([('test.conf',
- '[DEFAULT]\n'
- 'foo = 6.66\n')])
-
- self.conf(['--config-file', paths[0]])
-
- self.assertTrue(hasattr(self.conf, 'foo'))
- self.assertEquals(self.conf.foo, 6.66)
-
- def test_conf_file_float_value_override(self):
- self.conf.register_cli_opt(FloatOpt('foo'))
-
- paths = self.create_tempfiles([('1.conf',
- '[DEFAULT]\n'
- 'foo = 6.6\n'),
- ('2.conf',
- '[DEFAULT]\n'
- 'foo = 6.66\n')])
-
- self.conf(['--foo', '6',
- '--config-file', paths[0],
- '--config-file', paths[1]])
-
- self.assertTrue(hasattr(self.conf, 'foo'))
- self.assertEquals(self.conf.foo, 6.66)
-
- def test_conf_file_list_default(self):
- self.conf.register_opt(ListOpt('foo', default=['bar']))
-
- paths = self.create_tempfiles([('test.conf',
- '[DEFAULT]\n')])
-
- self.conf(['--config-file', paths[0]])
-
- self.assertTrue(hasattr(self.conf, 'foo'))
- self.assertEquals(self.conf.foo, ['bar'])
-
- def test_conf_file_list_value(self):
- self.conf.register_opt(ListOpt('foo'))
-
- paths = self.create_tempfiles([('test.conf',
- '[DEFAULT]\n'
- 'foo = bar\n')])
-
- self.conf(['--config-file', paths[0]])
-
- self.assertTrue(hasattr(self.conf, 'foo'))
- self.assertEquals(self.conf.foo, ['bar'])
-
- def test_conf_file_list_value_override(self):
- self.conf.register_cli_opt(ListOpt('foo'))
-
- paths = self.create_tempfiles([('1.conf',
- '[DEFAULT]\n'
- 'foo = bar,bar\n'),
- ('2.conf',
- '[DEFAULT]\n'
- 'foo = b,a,r\n')])
-
- self.conf(['--foo', 'bar',
- '--config-file', paths[0],
- '--config-file', paths[1]])
-
- self.assertTrue(hasattr(self.conf, 'foo'))
- self.assertEquals(self.conf.foo, ['b', 'a', 'r'])
-
- def test_conf_file_multistr_default(self):
- self.conf.register_opt(MultiStrOpt('foo', default=['bar']))
-
- paths = self.create_tempfiles([('test.conf',
- '[DEFAULT]\n')])
-
- self.conf(['--config-file', paths[0]])
-
- self.assertTrue(hasattr(self.conf, 'foo'))
- self.assertEquals(self.conf.foo, ['bar'])
-
- def test_conf_file_multistr_value(self):
- self.conf.register_opt(MultiStrOpt('foo'))
-
- paths = self.create_tempfiles([('test.conf',
- '[DEFAULT]\n'
- 'foo = bar\n')])
-
- self.conf(['--config-file', paths[0]])
-
- self.assertTrue(hasattr(self.conf, 'foo'))
- self.assertEquals(self.conf.foo, ['bar'])
-
- def test_conf_file_multistr_values_append(self):
- self.conf.register_cli_opt(ListOpt('foo'))
-
- paths = self.create_tempfiles([('1.conf',
- '[DEFAULT]\n'
- 'foo = bar\n'),
- ('2.conf',
- '[DEFAULT]\n'
- 'foo = bar\n')])
-
- self.conf(['--foo', 'bar',
- '--config-file', paths[0],
- '--config-file', paths[1]])
-
- self.assertTrue(hasattr(self.conf, 'foo'))
-
- # FIXME(markmc): values spread across the CLI and multiple
- # config files should be appended
- # self.assertEquals(self.conf.foo, ['bar', 'bar', 'bar'])
-
-
-class OptGroupsTestCase(BaseTestCase):
-
- def test_arg_group(self):
- blaa_group = OptGroup('blaa')
- self.conf.register_group(blaa_group)
- self.conf.register_cli_opt(StrOpt('foo'), group=blaa_group)
-
- self.conf(['--blaa-foo', 'bar'])
-
- self.assertTrue(hasattr(self.conf, 'blaa'))
- self.assertTrue(hasattr(self.conf.blaa, 'foo'))
- self.assertEquals(self.conf.blaa.foo, 'bar')
-
- def test_arg_group_by_name(self):
- self.conf.register_group(OptGroup('blaa'))
- self.conf.register_cli_opt(StrOpt('foo'), group='blaa')
-
- self.conf(['--blaa-foo', 'bar'])
-
- self.assertTrue(hasattr(self.conf, 'blaa'))
- self.assertTrue(hasattr(self.conf.blaa, 'foo'))
- self.assertEquals(self.conf.blaa.foo, 'bar')
-
- def test_arg_group_with_default(self):
- self.conf.register_group(OptGroup('blaa'))
- self.conf.register_cli_opt(StrOpt('foo', default='bar'), group='blaa')
-
- self.conf([])
-
- self.assertTrue(hasattr(self.conf, 'blaa'))
- self.assertTrue(hasattr(self.conf.blaa, 'foo'))
- self.assertEquals(self.conf.blaa.foo, 'bar')
-
- def test_arg_group_in_config_file(self):
- self.conf.register_group(OptGroup('blaa'))
- self.conf.register_opt(StrOpt('foo'), group='blaa')
-
- paths = self.create_tempfiles([('test.conf',
- '[blaa]\n'
- 'foo = bar\n')])
-
- self.conf(['--config-file', paths[0]])
-
- self.assertTrue(hasattr(self.conf, 'blaa'))
- self.assertTrue(hasattr(self.conf.blaa, 'foo'))
- self.assertEquals(self.conf.blaa.foo, 'bar')
-
-
-class TemplateSubstitutionTestCase(BaseTestCase):
-
- def _prep_test_str_sub(self, foo_default=None, bar_default=None):
- self.conf.register_cli_opt(StrOpt('foo', default=foo_default))
- self.conf.register_cli_opt(StrOpt('bar', default=bar_default))
-
- def _assert_str_sub(self):
- self.assertTrue(hasattr(self.conf, 'bar'))
- self.assertEquals(self.conf.bar, 'blaa')
-
- def test_str_sub_default_from_default(self):
- self._prep_test_str_sub(foo_default='blaa', bar_default='$foo')
-
- self.conf([])
-
- self._assert_str_sub()
-
- def test_str_sub_default_from_arg(self):
- self._prep_test_str_sub(bar_default='$foo')
-
- self.conf(['--foo', 'blaa'])
-
- self._assert_str_sub()
-
- def test_str_sub_default_from_config_file(self):
- self._prep_test_str_sub(bar_default='$foo')
-
- paths = self.create_tempfiles([('test.conf',
- '[DEFAULT]\n'
- 'foo = blaa\n')])
-
- self.conf(['--config-file', paths[0]])
-
- self._assert_str_sub()
-
- def test_str_sub_arg_from_default(self):
- self._prep_test_str_sub(foo_default='blaa')
-
- self.conf(['--bar', '$foo'])
-
- self._assert_str_sub()
-
- def test_str_sub_arg_from_arg(self):
- self._prep_test_str_sub()
-
- self.conf(['--foo', 'blaa', '--bar', '$foo'])
-
- self._assert_str_sub()
-
- def test_str_sub_arg_from_config_file(self):
- self._prep_test_str_sub()
-
- paths = self.create_tempfiles([('test.conf',
- '[DEFAULT]\n'
- 'foo = blaa\n')])
-
- self.conf(['--config-file', paths[0], '--bar=$foo'])
-
- self._assert_str_sub()
-
- def test_str_sub_config_file_from_default(self):
- self._prep_test_str_sub(foo_default='blaa')
-
- paths = self.create_tempfiles([('test.conf',
- '[DEFAULT]\n'
- 'bar = $foo\n')])
-
- self.conf(['--config-file', paths[0]])
-
- self._assert_str_sub()
-
- def test_str_sub_config_file_from_arg(self):
- self._prep_test_str_sub()
-
- paths = self.create_tempfiles([('test.conf',
- '[DEFAULT]\n'
- 'bar = $foo\n')])
-
- self.conf(['--config-file', paths[0], '--foo=blaa'])
-
- self._assert_str_sub()
-
- def test_str_sub_config_file_from_config_file(self):
- self._prep_test_str_sub()
-
- paths = self.create_tempfiles([('test.conf',
- '[DEFAULT]\n'
- 'bar = $foo\n'
- 'foo = blaa\n')])
-
- self.conf(['--config-file', paths[0]])
-
- self._assert_str_sub()
-
- def test_str_sub_group_from_default(self):
- self.conf.register_cli_opt(StrOpt('foo', default='blaa'))
- self.conf.register_group(OptGroup('ba'))
- self.conf.register_cli_opt(StrOpt('r', default='$foo'), group='ba')
-
- self.conf([])
-
- self.assertTrue(hasattr(self.conf, 'ba'))
- self.assertTrue(hasattr(self.conf.ba, 'r'))
- self.assertEquals(self.conf.ba.r, 'blaa')
-
-
-class ReparseTestCase(BaseTestCase):
-
- def test_reparse(self):
- self.conf.register_group(OptGroup('blaa'))
- self.conf.register_cli_opt(StrOpt('foo', default='r'), group='blaa')
-
- paths = self.create_tempfiles([('test.conf',
- '[blaa]\n'
- 'foo = b\n')])
-
- self.conf(['--config-file', paths[0]])
-
- self.assertTrue(hasattr(self.conf, 'blaa'))
- self.assertTrue(hasattr(self.conf.blaa, 'foo'))
- self.assertEquals(self.conf.blaa.foo, 'b')
-
- self.conf(['--blaa-foo', 'a'])
-
- self.assertTrue(hasattr(self.conf, 'blaa'))
- self.assertTrue(hasattr(self.conf.blaa, 'foo'))
- self.assertEquals(self.conf.blaa.foo, 'a')
-
- self.conf([])
-
- self.assertTrue(hasattr(self.conf, 'blaa'))
- self.assertTrue(hasattr(self.conf.blaa, 'foo'))
- self.assertEquals(self.conf.blaa.foo, 'r')
-
-
-class OverridesTestCase(BaseTestCase):
-
- def test_no_default_override(self):
- self.conf.register_opt(StrOpt('foo'))
- self.conf([])
- self.assertEquals(self.conf.foo, None)
- self.conf.set_default('foo', 'bar')
- self.assertEquals(self.conf.foo, 'bar')
-
- def test_default_override(self):
- self.conf.register_opt(StrOpt('foo', default='foo'))
- self.conf([])
- self.assertEquals(self.conf.foo, 'foo')
- self.conf.set_default('foo', 'bar')
- self.assertEquals(self.conf.foo, 'bar')
- self.conf.set_default('foo', None)
- self.assertEquals(self.conf.foo, 'foo')
-
- def test_override(self):
- self.conf.register_opt(StrOpt('foo'))
- self.conf.set_override('foo', 'bar')
- self.conf([])
- self.assertEquals(self.conf.foo, 'bar')
-
- def test_group_no_default_override(self):
- self.conf.register_group(OptGroup('blaa'))
- self.conf.register_opt(StrOpt('foo'), group='blaa')
- self.conf([])
- self.assertEquals(self.conf.blaa.foo, None)
- self.conf.set_default('foo', 'bar', group='blaa')
- self.assertEquals(self.conf.blaa.foo, 'bar')
-
- def test_group_default_override(self):
- self.conf.register_group(OptGroup('blaa'))
- self.conf.register_opt(StrOpt('foo', default='foo'), group='blaa')
- self.conf([])
- self.assertEquals(self.conf.blaa.foo, 'foo')
- self.conf.set_default('foo', 'bar', group='blaa')
- self.assertEquals(self.conf.blaa.foo, 'bar')
- self.conf.set_default('foo', None, group='blaa')
- self.assertEquals(self.conf.blaa.foo, 'foo')
-
- def test_group_override(self):
- self.conf.register_group(OptGroup('blaa'))
- self.conf.register_opt(StrOpt('foo'), group='blaa')
- self.conf.set_override('foo', 'bar', group='blaa')
- self.conf([])
- self.assertEquals(self.conf.blaa.foo, 'bar')
-
-
-class SadPathTestCase(BaseTestCase):
-
- def test_unknown_attr(self):
- self.conf([])
- self.assertFalse(hasattr(self.conf, 'foo'))
- self.assertRaises(NoSuchOptError, getattr, self.conf, 'foo')
-
- def test_unknown_attr_is_attr_error(self):
- self.conf([])
- self.assertFalse(hasattr(self.conf, 'foo'))
- self.assertRaises(AttributeError, getattr, self.conf, 'foo')
-
- def test_unknown_group_attr(self):
- self.conf.register_group(OptGroup('blaa'))
-
- self.conf([])
-
- self.assertTrue(hasattr(self.conf, 'blaa'))
- self.assertFalse(hasattr(self.conf.blaa, 'foo'))
- self.assertRaises(NoSuchOptError, getattr, self.conf.blaa, 'foo')
-
- def test_ok_duplicate(self):
- opt = StrOpt('foo')
- self.conf.register_cli_opt(opt)
- self.conf.register_cli_opt(opt)
-
- self.conf([])
-
- self.assertTrue(hasattr(self.conf, 'foo'))
- self.assertEquals(self.conf.foo, None)
-
- def test_error_duplicate(self):
- self.conf.register_cli_opt(StrOpt('foo'))
- self.assertRaises(DuplicateOptError,
- self.conf.register_cli_opt, StrOpt('foo'))
-
- def test_error_duplicate_with_different_dest(self):
- self.conf.register_cli_opt(StrOpt('foo', dest='f'))
- self.assertRaises(DuplicateOptError,
- self.conf.register_cli_opt, StrOpt('foo'))
-
- def test_error_duplicate_short(self):
- self.conf.register_cli_opt(StrOpt('foo', short='f'))
- self.assertRaises(DuplicateOptError,
- self.conf.register_cli_opt, StrOpt('bar', short='f'))
-
- def test_no_such_group(self):
- self.assertRaises(NoSuchGroupError, self.conf.register_cli_opt,
- StrOpt('foo'), group='blaa')
-
- def test_already_parsed(self):
- self.conf([])
-
- self.assertRaises(ArgsAlreadyParsedError,
- self.conf.register_cli_opt, StrOpt('foo'))
-
- def test_bad_cli_arg(self):
- self.stubs.Set(sys, 'stderr', StringIO.StringIO())
-
- self.assertRaises(SystemExit, self.conf, ['--foo'])
-
- self.assertTrue('error' in sys.stderr.getvalue())
- self.assertTrue('--foo' in sys.stderr.getvalue())
-
- def _do_test_bad_cli_value(self, opt_class):
- self.conf.register_cli_opt(opt_class('foo'))
-
- self.stubs.Set(sys, 'stderr', StringIO.StringIO())
-
- self.assertRaises(SystemExit, self.conf, ['--foo', 'bar'])
-
- self.assertTrue('foo' in sys.stderr.getvalue())
- self.assertTrue('bar' in sys.stderr.getvalue())
-
- def test_bad_int_arg(self):
- self._do_test_bad_cli_value(IntOpt)
-
- def test_bad_float_arg(self):
- self._do_test_bad_cli_value(FloatOpt)
-
- def test_conf_file_not_found(self):
- paths = self.create_tempfiles([('test.conf', '')])
- os.remove(paths[0])
- self.tempfiles.remove(paths[0])
-
- self.assertRaises(ConfigFilesNotFoundError,
- self.conf, ['--config-file', paths[0]])
-
- def test_conf_file_broken(self):
- paths = self.create_tempfiles([('test.conf', 'foo')])
-
- self.assertRaises(ConfigFileParseError,
- self.conf, ['--config-file', paths[0]])
-
- def _do_test_conf_file_bad_value(self, opt_class):
- self.conf.register_opt(opt_class('foo'))
-
- def test_conf_file_bad_bool(self):
- self._do_test_conf_file_bad_value(BoolOpt)
-
- def test_conf_file_bad_int(self):
- self._do_test_conf_file_bad_value(IntOpt)
-
- def test_conf_file_bad_float(self):
- self._do_test_conf_file_bad_value(FloatOpt)
-
- def test_str_sub_from_group(self):
- self.conf.register_group(OptGroup('f'))
- self.conf.register_cli_opt(StrOpt('oo', default='blaa'), group='f')
- self.conf.register_cli_opt(StrOpt('bar', default='$f.oo'))
-
- self.conf([])
-
- self.assertFalse(hasattr(self.conf, 'bar'))
- self.assertRaises(TemplateSubstitutionError, getattr, self.conf, 'bar')
-
- def test_set_default_unknown_attr(self):
- self.conf([])
- self.assertRaises(NoSuchOptError, self.conf.set_default, 'foo', 'bar')
-
- def test_set_default_unknown_group(self):
- self.conf([])
- self.assertRaises(NoSuchGroupError,
- self.conf.set_default, 'foo', 'bar', group='blaa')
-
- def test_set_override_unknown_attr(self):
- self.conf([])
- self.assertRaises(NoSuchOptError, self.conf.set_override, 'foo', 'bar')
-
- def test_set_override_unknown_group(self):
- self.conf([])
- self.assertRaises(NoSuchGroupError,
- self.conf.set_override, 'foo', 'bar', group='blaa')
-
-
-class OptDumpingTestCase(BaseTestCase):
-
- class FakeLogger:
-
- def __init__(self, test_case, expected_lvl):
- self.test_case = test_case
- self.expected_lvl = expected_lvl
- self.logged = []
-
- def log(self, lvl, fmt, *args):
- self.test_case.assertEquals(lvl, self.expected_lvl)
- self.logged.append(fmt % args)
-
- def test_log_opt_values(self):
- self.conf.register_cli_opt(StrOpt('foo'))
- self.conf.register_group(OptGroup('blaa'))
- self.conf.register_cli_opt(StrOpt('bar'), 'blaa')
-
- self.conf(['--foo', 'this', '--blaa-bar', 'that'])
-
- logger = self.FakeLogger(self, 666)
-
- self.conf.log_opt_values(logger, 666)
-
- self.assertEquals(logger.logged, [
- "*" * 80,
- "Configuration options gathered from:",
- "command line args: ['--foo', 'this', '--blaa-bar', 'that']",
- "config files: []",
- "=" * 80,
- "config_file = []",
- "foo = this",
- "blaa.bar = that",
- "*" * 80,
- ])
-
-
-class CommonOptsTestCase(BaseTestCase):
-
- def setUp(self):
- super(CommonOptsTestCase, self).setUp()
- self.conf = CommonConfigOpts()
-
- def test_debug_verbose(self):
- self.conf(['--debug', '--verbose'])
-
- self.assertEquals(self.conf.debug, True)
- self.assertEquals(self.conf.verbose, True)
-
- def test_logging_opts(self):
- self.conf([])
-
- self.assertTrue(self.conf.log_config is None)
- self.assertTrue(self.conf.log_file is None)
- self.assertTrue(self.conf.log_dir is None)
-
- self.assertEquals(self.conf.log_format,
- CommonConfigOpts.DEFAULT_LOG_FORMAT)
- self.assertEquals(self.conf.log_date_format,
- CommonConfigOpts.DEFAULT_LOG_DATE_FORMAT)
-
- self.assertEquals(self.conf.use_syslog, False)
diff --git a/nova/tests/test_compute.py b/nova/tests/test_compute.py
index 400e6949f..d99aed310 100644
--- a/nova/tests/test_compute.py
+++ b/nova/tests/test_compute.py
@@ -190,6 +190,15 @@ class BaseTestCase(test.TestCase):
class ComputeTestCase(BaseTestCase):
+ def setUp(self):
+ def fake_get_nw_info(cls, ctxt, instance):
+ self.assertTrue(ctxt.is_admin)
+ return fake_network.fake_get_instance_nw_info(self.stubs, 1, 1,
+ spectacular=True)
+
+ super(ComputeTestCase, self).setUp()
+ self.stubs.Set(nova.network.API, 'get_instance_nw_info',
+ fake_get_nw_info)
def test_wrap_instance_fault(self):
inst_uuid = "fake_uuid"
@@ -966,38 +975,66 @@ class ComputeTestCase(BaseTestCase):
def test_finish_resize(self):
"""Contrived test to ensure finish_resize doesn't raise anything"""
+ nw_info = fake_network.fake_get_instance_nw_info(self.stubs,
+ spectacular=True)
+
def fake(*args, **kwargs):
pass
+ def fake_nw_info(*args, **kwargs):
+ return nw_info
+
+ # NOTE(jkoelker) There is a bit of a stubbing issue here.
+ # fake_network stubs out a bunch of stuff which
+ # this functional test expects to be acting on
+ # the db or the stubs it sets.
+ self.stubs.UnsetAll()
+ self.stubs.SmartUnsetAll()
+ self.setUp()
+
self.stubs.Set(self.compute.driver, 'finish_migration', fake)
- self.stubs.Set(self.compute.network_api, 'get_instance_nw_info', fake)
+ self.stubs.Set(self.compute.network_api, 'get_instance_nw_info',
+ fake_nw_info)
+ fake_network.stub_out_nw_api_get_instance_nw_info(self.stubs,
+ func=fake_nw_info)
context = self.context.elevated()
+
instance = self._create_fake_instance()
self.compute.prep_resize(context, instance['uuid'], 1,
filter_properties={})
migration_ref = db.migration_get_by_instance_and_status(context,
instance['uuid'], 'pre-migrating')
- try:
- self.compute.finish_resize(context, instance['uuid'],
- int(migration_ref['id']), {})
- except KeyError, e:
- # Only catch key errors. We want other reasons for the test to
- # fail to actually error out so we don't obscure anything
- self.fail()
-
+ self.compute.finish_resize(context, instance['uuid'],
+ int(migration_ref['id']), {})
self.compute.terminate_instance(self.context, instance['uuid'])
def test_finish_resize_handles_error(self):
"""Make sure we don't leave the instance in RESIZE on error"""
+ nw_info = fake_network.fake_get_instance_nw_info(self.stubs,
+ spectacular=True)
+
def throw_up(*args, **kwargs):
raise Exception()
def fake(*args, **kwargs):
pass
+ def fake_nw_info(*args, **kwargs):
+ return nw_info
+
+ # NOTE(jkoelker) There is a bit of a stubbing issue here.
+ # fake_network stubs out a bunch of stuff which
+ # this functional test expects to be acting on
+ # the db or the stubs it sets.
+ self.stubs.UnsetAll()
+ self.stubs.SmartUnsetAll()
+ self.setUp()
+
self.stubs.Set(self.compute.driver, 'finish_migration', throw_up)
self.stubs.Set(self.compute.network_api, 'get_instance_nw_info', fake)
+ fake_network.stub_out_nw_api_get_instance_nw_info(self.stubs,
+ func=fake_nw_info)
context = self.context.elevated()
instance = self._create_fake_instance()
self.compute.prep_resize(context, instance['uuid'], 1,
@@ -1123,13 +1160,32 @@ class ComputeTestCase(BaseTestCase):
def test_finish_revert_resize(self):
"""Ensure that the flavor is reverted to the original on revert"""
- context = self.context.elevated()
- instance = self._create_fake_instance()
- instance_uuid = instance['uuid']
+ nw_info = fake_network.fake_get_instance_nw_info(self.stubs,
+ spectacular=True)
def fake(*args, **kwargs):
pass
+ def fake_nw_info(*args, **kwargs):
+ return nw_info
+
+ # NOTE(jkoelker) There is a bit of a stubbing issue here.
+ # fake_network stubs out a bunch of stuff which
+ # this functional test expects to be acting on
+ # the db or the stubs it sets.
+ self.stubs.UnsetAll()
+ self.stubs.SmartUnsetAll()
+ self.setUp()
+
+ self.stubs.Set(self.compute.network_api, 'get_instance_nw_info',
+ fake_nw_info)
+ fake_network.stub_out_nw_api_get_instance_nw_info(self.stubs,
+ func=fake_nw_info)
+
+ context = self.context.elevated()
+ instance = self._create_fake_instance()
+ instance_uuid = instance['uuid']
+
self.stubs.Set(self.compute.driver, 'finish_migration', fake)
self.stubs.Set(self.compute.driver, 'finish_revert_migration', fake)
self.stubs.Set(self.compute.network_api, 'get_instance_nw_info', fake)
@@ -1450,7 +1506,14 @@ class ComputeTestCase(BaseTestCase):
class ComputeAPITestCase(BaseTestCase):
def setUp(self):
+ def fake_get_nw_info(cls, ctxt, instance):
+ self.assertTrue(ctxt.is_admin)
+ return fake_network.fake_get_instance_nw_info(self.stubs, 1, 1,
+ spectacular=True)
+
super(ComputeAPITestCase, self).setUp()
+ self.stubs.Set(nova.network.API, 'get_instance_nw_info',
+ fake_get_nw_info)
self.compute_api = compute.API()
self.fake_image = {
'id': 1,
@@ -2267,17 +2330,9 @@ class ComputeAPITestCase(BaseTestCase):
fixed_address):
called['associate'] = True
- def fake_get_nw_info(cls, ctxt, instance):
- self.assertTrue(ctxt.is_admin)
- return fake_network.fake_get_instance_nw_info(self.stubs, 1, 1,
- spectacular=True)
-
self.stubs.Set(nova.network.API, 'associate_floating_ip',
fake_associate_ip_network_api)
- self.stubs.Set(nova.network.API, 'get_instance_nw_info',
- fake_get_nw_info)
-
instance = self._create_fake_instance()
instance_uuid = instance['uuid']
address = '0.1.2.3'
@@ -2995,12 +3050,6 @@ class ComputeAPITestCase(BaseTestCase):
self.assertTrue(self.compute_api.get_lock(self.context, instance))
def test_add_remove_security_group(self):
- def fake_get_nw_info(cls, ctxt, instance):
- return fake_network.fake_get_instance_nw_info(self.stubs, 1, 1,
- spectacular=True)
-
- self.stubs.Set(nova.network.API, 'get_instance_nw_info',
- fake_get_nw_info)
instance = self._create_fake_instance()
self.compute.run_instance(self.context, instance['uuid'])
diff --git a/nova/tests/test_compute_utils.py b/nova/tests/test_compute_utils.py
index 71463fbc0..8e35d1905 100644
--- a/nova/tests/test_compute_utils.py
+++ b/nova/tests/test_compute_utils.py
@@ -29,6 +29,7 @@ import nova.image.fake
from nova.compute import utils as compute_utils
from nova.compute import instance_types
from nova.notifier import test_notifier
+from nova.tests import fake_network
LOG = logging.getLogger('nova.tests.compute_utils')
@@ -39,7 +40,15 @@ flags.DECLARE('stub_network', 'nova.compute.manager')
class UsageInfoTestCase(test.TestCase):
def setUp(self):
+ def fake_get_nw_info(cls, ctxt, instance):
+ self.assertTrue(ctxt.is_admin)
+ return fake_network.fake_get_instance_nw_info(self.stubs, 1, 1,
+ spectacular=True)
+
super(UsageInfoTestCase, self).setUp()
+ self.stubs.Set(nova.network.API, 'get_instance_nw_info',
+ fake_get_nw_info)
+
self.flags(connection_type='fake',
stub_network=True,
notification_driver='nova.notifier.test_notifier',
diff --git a/nova/tests/test_flags.py b/nova/tests/test_flags.py
index 02ee49ef0..bea34007a 100644
--- a/nova/tests/test_flags.py
+++ b/nova/tests/test_flags.py
@@ -21,8 +21,8 @@ import exceptions
import os
import tempfile
-from nova.common import cfg
from nova import flags
+from nova.openstack.common import cfg
from nova import test
FLAGS = flags.FLAGS
diff --git a/nova/tests/test_imagecache.py b/nova/tests/test_imagecache.py
new file mode 100644
index 000000000..dee937bd2
--- /dev/null
+++ b/nova/tests/test_imagecache.py
@@ -0,0 +1,243 @@
+#!/usr/bin/python
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 Michael Still and Canonical Inc
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+
+import hashlib
+import os
+import shutil
+import tempfile
+import time
+
+from nova import test
+
+from nova import db
+from nova import flags
+from nova import log as logging
+from nova.virt.libvirt import imagecache
+from nova.virt.libvirt import utils as virtutils
+
+
+flags.DECLARE('instances_path', 'nova.compute.manager')
+FLAGS = flags.FLAGS
+
+LOG = logging.getLogger('nova.tests.test_imagecache')
+
+
+class ImageCacheManagerTestCase(test.TestCase):
+
+ def test_read_stored_checksum_missing(self):
+ self.stubs.Set(os.path, 'exists', lambda x: False)
+
+ csum = imagecache.read_stored_checksum('/tmp/foo')
+ self.assertEquals(csum, None)
+
+ def test_read_stored_checksum(self):
+ try:
+ dirname = tempfile.mkdtemp()
+ fname = os.path.join(dirname, 'aaa')
+
+ csum_input = 'fdghkfhkgjjksfdgjksjkghsdf'
+ f = open('%s.sha1' % fname, 'w')
+ f.write('%s\n' % csum_input)
+ f.close()
+
+ csum_output = imagecache.read_stored_checksum(fname)
+
+ self.assertEquals(csum_input, csum_output)
+
+ finally:
+ shutil.rmtree(dirname)
+
+ def test_list_base_images(self):
+ listing = ['00000001',
+ 'ephemeral_0_20_None',
+ 'e97222e91fc4241f49a7f520d1dcf446751129b3_sm',
+ 'e09c675c2d1cfac32dae3c2d83689c8c94bc693b_sm',
+ 'e97222e91fc4241f49a7f520d1dcf446751129b3',
+ '00000004']
+
+ self.stubs.Set(os, 'listdir', lambda x: listing)
+ self.stubs.Set(os.path, 'isfile', lambda x: True)
+
+ base_dir = '/var/lib/nova/instances/_base'
+ image_cache_manager = imagecache.ImageCacheManager()
+ image_cache_manager._list_base_images(base_dir)
+
+ self.assertEquals(len(image_cache_manager.unexplained_images), 3)
+
+ expected = os.path.join(base_dir,
+ 'e97222e91fc4241f49a7f520d1dcf446751129b3')
+ self.assertTrue(expected in image_cache_manager.unexplained_images)
+
+ unexpected = os.path.join(base_dir, '00000004')
+ self.assertFalse(unexpected in image_cache_manager.unexplained_images)
+
+ for ent in image_cache_manager.unexplained_images:
+ self.assertTrue(ent.startswith(base_dir))
+
+ def test_list_running_instances(self):
+ self.stubs.Set(db, 'instance_get_all',
+ lambda x: [{'image_ref': 'image-1',
+ 'host': FLAGS.host,
+ 'name': 'inst-1'},
+ {'image_ref': 'image-2',
+ 'host': FLAGS.host,
+ 'name': 'inst-2'},
+ {'image_ref': 'image-2',
+ 'host': 'remotehost',
+ 'name': 'inst-3'}])
+
+ image_cache_manager = imagecache.ImageCacheManager()
+
+ # The argument here should be a context, but its mocked out
+ image_cache_manager._list_running_instances(None)
+
+ self.assertEqual(len(image_cache_manager.used_images), 2)
+ self.assertTrue(image_cache_manager.used_images['image-1'] ==
+ (1, 0, ['inst-1']))
+ self.assertTrue(image_cache_manager.used_images['image-2'] ==
+ (1, 1, ['inst-2', 'inst-3']))
+
+ self.assertEqual(len(image_cache_manager.image_popularity), 2)
+ self.assertEqual(image_cache_manager.image_popularity['image-1'], 1)
+ self.assertEqual(image_cache_manager.image_popularity['image-2'], 2)
+
+ def test_list_backing_images(self):
+ self.stubs.Set(os, 'listdir',
+ lambda x: ['_base', 'instance-00000001',
+ 'instance-00000002', 'instance-00000003'])
+ self.stubs.Set(os.path, 'exists',
+ lambda x: x.find('instance-') != -1)
+ self.stubs.Set(virtutils, 'get_disk_backing_file',
+ lambda x: 'e97222e91fc4241f49a7f520d1dcf446751129b3_sm')
+
+ found = os.path.join(FLAGS.instances_path, '_base',
+ 'e97222e91fc4241f49a7f520d1dcf446751129b3_sm')
+
+ image_cache_manager = imagecache.ImageCacheManager()
+ image_cache_manager.unexplained_images = [found]
+
+ inuse_images = image_cache_manager._list_backing_images()
+
+ self.assertEquals(inuse_images, [found])
+ self.assertEquals(len(image_cache_manager.unexplained_images), 0)
+
+ def test_find_base_file_nothing(self):
+ self.stubs.Set(os.path, 'exists', lambda x: False)
+
+ base_dir = '/var/lib/nova/instances/_base'
+ fingerprint = '549867354867'
+ image_cache_manager = imagecache.ImageCacheManager()
+ res = list(image_cache_manager._find_base_file(base_dir, fingerprint))
+
+ self.assertEqual(0, len(res))
+
+ def test_find_base_file_small(self):
+ self.stubs.Set(os.path, 'exists',
+ lambda x: x.endswith('549867354867_sm'))
+
+ base_dir = '/var/lib/nova/instances/_base'
+ fingerprint = '549867354867'
+ image_cache_manager = imagecache.ImageCacheManager()
+ res = list(image_cache_manager._find_base_file(base_dir, fingerprint))
+
+ base_file = os.path.join(base_dir, fingerprint + '_sm')
+ self.assertTrue(res == [(base_file, True)])
+
+ def test_find_base_file_both(self):
+ self.stubs.Set(os.path, 'exists', lambda x: True)
+
+ base_dir = '/var/lib/nova/instances/_base'
+ fingerprint = '549867354867'
+ image_cache_manager = imagecache.ImageCacheManager()
+ res = list(image_cache_manager._find_base_file(base_dir, fingerprint))
+
+ base_file1 = os.path.join(base_dir, fingerprint)
+ base_file2 = os.path.join(base_dir, fingerprint + '_sm')
+ self.assertTrue(res == [(base_file1, False), (base_file2, True)])
+
+ def test_verify_checksum(self):
+ testdata = ('OpenStack Software delivers a massively scalable cloud '
+ 'operating system.')
+ img = {'container_format': 'ami', 'id': '42'}
+
+ try:
+ dirname = tempfile.mkdtemp()
+ fname = os.path.join(dirname, 'aaa')
+
+ f = open(fname, 'w')
+ f.write(testdata)
+ f.close()
+
+ # Checksum is valid
+ f = open('%s.sha1' % fname, 'w')
+ csum = hashlib.sha1()
+ csum.update(testdata)
+ f.write(csum.hexdigest())
+ f.close()
+
+ image_cache_manager = imagecache.ImageCacheManager()
+ res = image_cache_manager._verify_checksum(img, fname)
+ self.assertTrue(res)
+
+ # Checksum is invalid
+ f = open('%s.sha1' % fname, 'w')
+ f.write('banana')
+ f.close()
+
+ image_cache_manager = imagecache.ImageCacheManager()
+ res = image_cache_manager._verify_checksum(img, fname)
+ self.assertFalse(res)
+
+ # Checksum file missing
+ os.remove('%s.sha1' % fname)
+ image_cache_manager = imagecache.ImageCacheManager()
+ res = image_cache_manager._verify_checksum(img, fname)
+ self.assertEquals(res, None)
+
+ finally:
+ shutil.rmtree(dirname)
+
+ def test_remove_base_file(self):
+ try:
+ dirname = tempfile.mkdtemp()
+ fname = os.path.join(dirname, 'aaa')
+
+ f = open(fname, 'w')
+ f.write('data')
+ f.close()
+
+ f = open('%s.sha1' % fname, 'w')
+ f.close()
+
+ image_cache_manager = imagecache.ImageCacheManager()
+ image_cache_manager._remove_base_file(fname)
+
+ # Files are initially too new to delete
+ self.assertTrue(os.path.exists(fname))
+ self.assertTrue(os.path.exists('%s.sha1' % fname))
+
+ # Old files get cleaned up though
+ os.utime(fname, (-1, time.time() - 100000))
+ image_cache_manager._remove_base_file(fname)
+
+ self.assertFalse(os.path.exists(fname))
+ self.assertFalse(os.path.exists('%s.sha1' % fname))
+
+ finally:
+ shutil.rmtree(dirname)
diff --git a/nova/tests/test_instance_types.py b/nova/tests/test_instance_types.py
index b0613c757..29b812a2b 100644
--- a/nova/tests/test_instance_types.py
+++ b/nova/tests/test_instance_types.py
@@ -174,7 +174,7 @@ class InstanceTypeTestCase(test.TestCase):
def test_will_not_get_bad_default_instance_type(self):
"""ensures error raised on bad default instance type"""
FLAGS.default_instance_type = 'unknown_flavor'
- self.assertRaises(exception.InstanceTypeNotFoundByName,
+ self.assertRaises(exception.ApiError,
instance_types.get_default_instance_type)
def test_will_get_instance_type_by_id(self):
@@ -185,12 +185,12 @@ class InstanceTypeTestCase(test.TestCase):
def test_will_not_get_instance_type_by_unknown_id(self):
"""Ensure get by name returns default flavor with no name"""
- self.assertRaises(exception.InstanceTypeNotFound,
+ self.assertRaises(exception.ApiError,
instance_types.get_instance_type, 10000)
def test_will_not_get_instance_type_with_bad_id(self):
"""Ensure get by name returns default flavor with bad name"""
- self.assertRaises(exception.InstanceTypeNotFound,
+ self.assertRaises(exception.ApiError,
instance_types.get_instance_type, 'asdf')
def test_instance_type_get_by_None_name_returns_default(self):
@@ -201,7 +201,7 @@ class InstanceTypeTestCase(test.TestCase):
def test_will_not_get_instance_type_with_bad_name(self):
"""Ensure get by name returns default flavor with bad name"""
- self.assertRaises(exception.InstanceTypeNotFoundByName,
+ self.assertRaises(exception.ApiError,
instance_types.get_instance_type_by_name, 10000)
def test_will_not_get_instance_by_unknown_flavor_id(self):
diff --git a/nova/tests/test_libvirt.py b/nova/tests/test_libvirt.py
index cbe45ed2f..72c9f8802 100644
--- a/nova/tests/test_libvirt.py
+++ b/nova/tests/test_libvirt.py
@@ -123,6 +123,10 @@ class LibvirtVolumeTestCase(test.TestCase):
def get_hypervisor_type(self):
return self.hyperv
self.fake_conn = FakeLibvirtConnection("Xen")
+ self.connr = {
+ 'ip': '127.0.0.1',
+ 'initiator': 'fake_initiator'
+ }
def test_libvirt_iscsi_driver(self):
# NOTE(vish) exists is to make driver assume connecting worked
@@ -136,8 +140,7 @@ class LibvirtVolumeTestCase(test.TestCase):
'name': name,
'provider_auth': None,
'provider_location': '%s,fake %s' % (location, iqn)}
- address = '127.0.0.1'
- connection_info = vol_driver.initialize_connection(vol, '127.0.0.1')
+ connection_info = vol_driver.initialize_connection(vol, self.connr)
mount_device = "vde"
xml = libvirt_driver.connect_volume(connection_info, mount_device)
tree = xml_to_tree(xml)
@@ -145,7 +148,7 @@ class LibvirtVolumeTestCase(test.TestCase):
self.assertEqual(tree.get('type'), 'block')
self.assertEqual(tree.find('./source').get('dev'), dev_str)
libvirt_driver.disconnect_volume(connection_info, mount_device)
- connection_info = vol_driver.terminate_connection(vol, '127.0.0.1')
+ connection_info = vol_driver.terminate_connection(vol, self.connr)
expected_commands = [('iscsiadm', '-m', 'node', '-T', iqn,
'-p', location),
('iscsiadm', '-m', 'node', '-T', iqn,
@@ -167,8 +170,7 @@ class LibvirtVolumeTestCase(test.TestCase):
libvirt_driver = volume.LibvirtNetVolumeDriver(self.fake_conn)
name = 'volume-00000001'
vol = {'id': 1, 'name': name}
- address = '127.0.0.1'
- connection_info = vol_driver.initialize_connection(vol, address)
+ connection_info = vol_driver.initialize_connection(vol, self.connr)
mount_device = "vde"
xml = libvirt_driver.connect_volume(connection_info, mount_device)
tree = xml_to_tree(xml)
@@ -176,15 +178,14 @@ class LibvirtVolumeTestCase(test.TestCase):
self.assertEqual(tree.find('./source').get('protocol'), 'sheepdog')
self.assertEqual(tree.find('./source').get('name'), name)
libvirt_driver.disconnect_volume(connection_info, mount_device)
- connection_info = vol_driver.terminate_connection(vol, '127.0.0.1')
+ connection_info = vol_driver.terminate_connection(vol, self.connr)
def test_libvirt_rbd_driver(self):
vol_driver = volume_driver.RBDDriver()
libvirt_driver = volume.LibvirtNetVolumeDriver(self.fake_conn)
name = 'volume-00000001'
vol = {'id': 1, 'name': name}
- address = '127.0.0.1'
- connection_info = vol_driver.initialize_connection(vol, address)
+ connection_info = vol_driver.initialize_connection(vol, self.connr)
mount_device = "vde"
xml = libvirt_driver.connect_volume(connection_info, mount_device)
tree = xml_to_tree(xml)
@@ -193,7 +194,7 @@ class LibvirtVolumeTestCase(test.TestCase):
rbd_name = '%s/%s' % (FLAGS.rbd_pool, name)
self.assertEqual(tree.find('./source').get('name'), rbd_name)
libvirt_driver.disconnect_volume(connection_info, mount_device)
- connection_info = vol_driver.terminate_connection(vol, '127.0.0.1')
+ connection_info = vol_driver.terminate_connection(vol, self.connr)
class CacheConcurrencyTestCase(test.TestCase):
@@ -355,6 +356,22 @@ class LibvirtConnTestCase(test.TestCase):
return db.service_create(context.get_admin_context(), service_ref)
+ def test_get_connector(self):
+ initiator = 'fake.initiator.iqn'
+ ip = 'fakeip'
+ self.flags(my_ip=ip)
+
+ conn = connection.LibvirtConnection(True)
+ expected = {
+ 'ip': ip,
+ 'initiator': initiator
+ }
+ volume = {
+ 'id': 'fake'
+ }
+ result = conn.get_volume_connector(volume)
+ self.assertDictMatch(expected, result)
+
def test_preparing_xml_info(self):
conn = connection.LibvirtConnection(True)
instance_ref = db.instance_create(self.context, self.test_instance)
@@ -1764,6 +1781,17 @@ class NWFilterTestCase(test.TestCase):
class LibvirtUtilsTestCase(test.TestCase):
+ def test_get_iscsi_initiator(self):
+ self.mox.StubOutWithMock(utils, 'execute')
+ initiator = 'fake.initiator.iqn'
+ rval = ("junk\nInitiatorName=%s\njunk\n" % initiator, None)
+ utils.execute('cat', '/etc/iscsi/initiatorname.iscsi',
+ run_as_root=True).AndReturn(rval)
+ # Start test
+ self.mox.ReplayAll()
+ result = libvirt_utils.get_iscsi_initiator()
+ self.assertEqual(initiator, result)
+
def test_create_image(self):
self.mox.StubOutWithMock(utils, 'execute')
utils.execute('qemu-img', 'create', '-f', 'raw',
diff --git a/nova/tests/test_linux_net.py b/nova/tests/test_linux_net.py
index 21c5284a5..f81bb0cbc 100644
--- a/nova/tests/test_linux_net.py
+++ b/nova/tests/test_linux_net.py
@@ -432,6 +432,31 @@ class LinuxNetworkTestCase(test.TestCase):
driver.plug({"bridge": "br100", "bridge_interface": "eth0"},
"fakemac")
+ def test_vlan_override(self):
+ """Makes sure vlan_interface flag overrides network bridge_interface.
+
+ Allows heterogeneous networks a la bug 833426"""
+
+ driver = linux_net.LinuxBridgeInterfaceDriver()
+
+ @classmethod
+ def test_ensure(_self, vlan, bridge, interface, network, mac_address):
+ self.passed_interface = interface
+
+ self.stubs.Set(linux_net.LinuxBridgeInterfaceDriver,
+ 'ensure_vlan_bridge', test_ensure)
+
+ network = {
+ "bridge": "br100",
+ "bridge_interface": "base_interface",
+ "vlan": "fake"
+ }
+ driver.plug(network, "fakemac")
+ self.assertEqual(self.passed_interface, "base_interface")
+ self.flags(vlan_interface="override_interface")
+ driver.plug(network, "fakemac")
+ self.assertEqual(self.passed_interface, "override_interface")
+
def _test_initialize_gateway(self, existing, expected, routes=''):
self.flags(fake_network=False)
executes = []
diff --git a/nova/tests/test_notifier.py b/nova/tests/test_notifier.py
index 00f367f49..b13f203a4 100644
--- a/nova/tests/test_notifier.py
+++ b/nova/tests/test_notifier.py
@@ -16,6 +16,7 @@
import stubout
import nova
+import nova.notifier.no_op_notifier
from nova import log
import nova.notifier.api
from nova.notifier.api import notify
@@ -26,6 +27,7 @@ class NotifierTestCase(test.TestCase):
"""Test case for notifications"""
def setUp(self):
super(NotifierTestCase, self).setUp()
+ self.flags(notification_driver='nova.notifier.no_op_notifier')
self.stubs = stubout.StubOutForTesting()
def tearDown(self):
diff --git a/nova/tests/test_nova_rootwrap.py b/nova/tests/test_nova_rootwrap.py
index 4dc476615..38cce3b35 100644
--- a/nova/tests/test_nova_rootwrap.py
+++ b/nova/tests/test_nova_rootwrap.py
@@ -93,6 +93,15 @@ class RootwrapTestCase(test.TestCase):
# Providing -9 signal should work
self.assertTrue(f.match(usercmd))
+ def test_ReadFileFilter(self):
+ goodfn = '/good/file.name'
+ f = filters.ReadFileFilter(goodfn)
+ usercmd = ['cat', '/bad/file']
+ self.assertFalse(f.match(['cat', '/bad/file']))
+ usercmd = ['cat', goodfn]
+ self.assertEqual(f.get_command(usercmd), ['/bin/cat', goodfn])
+ self.assertTrue(f.match(usercmd))
+
def test_skips(self):
# Check that all filters are skipped and that the last matches
usercmd = ["cat", "/"]
diff --git a/nova/tests/test_quota.py b/nova/tests/test_quota.py
index 3c267b8b0..23660333a 100644
--- a/nova/tests/test_quota.py
+++ b/nova/tests/test_quota.py
@@ -46,7 +46,8 @@ class QuotaTestCase(test.TestCase):
quota_cores=4,
quota_volumes=2,
quota_gigabytes=20,
- quota_floating_ips=1)
+ quota_floating_ips=1,
+ network_manager='nova.network.manager.FlatDHCPManager')
self.network = self.network = self.start_service('network')
self.user_id = 'admin'
@@ -97,9 +98,19 @@ class QuotaTestCase(test.TestCase):
dict(memory_mb=4096, vcpus=2, root_gb=40, flavorid=3),
'm1.large': dict(memory_mb=8192, vcpus=4, root_gb=80, flavorid=4),
'm1.xlarge':
- dict(memory_mb=16384, vcpus=8, root_gb=160, flavorid=5)}
+ dict(memory_mb=16384, vcpus=8, root_gb=160, flavorid=5),
+ 'm1.nocpu': dict(memory_mb=512, vcpus=0, root_gb=0, flavorid=6),
+ 'm1.nomem': dict(memory_mb=0, vcpus=1, root_gb=0, flavorid=7)}
return instance_types[name]
+ def test_quota_no_mem_no_cpu(self):
+ num_instances = quota.allowed_instances(self.context, 100,
+ self._get_instance_type('m1.nocpu'))
+ self.assertEqual(num_instances, 2)
+ num_instances = quota.allowed_instances(self.context, 100,
+ self._get_instance_type('m1.nomem'))
+ self.assertEqual(num_instances, 2)
+
def test_quota_overrides(self):
"""Make sure overriding a projects quotas works"""
num_instances = quota.allowed_instances(self.context, 100,
diff --git a/nova/tests/test_service.py b/nova/tests/test_service.py
index c8a18f7d8..edede55b3 100644
--- a/nova/tests/test_service.py
+++ b/nova/tests/test_service.py
@@ -22,11 +22,11 @@ Unit Tests for remote procedure calls using queue
import mox
-from nova.common import cfg
from nova import context
from nova import db
from nova import exception
from nova import flags
+from nova.openstack.common import cfg
from nova import test
from nova import service
from nova import manager
diff --git a/nova/tests/test_utils.py b/nova/tests/test_utils.py
index a99356acb..5da717bee 100644
--- a/nova/tests/test_utils.py
+++ b/nova/tests/test_utils.py
@@ -17,7 +17,9 @@
import __builtin__
import mox
import datetime
+import hashlib
import os
+import StringIO
import tempfile
import nova
@@ -380,6 +382,18 @@ class GenericUtilsTestCase(test.TestCase):
self.assertTrue([c for c in password
if c in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'])
+ def test_read_file_as_root(self):
+ def fake_execute(*args, **kwargs):
+ if args[1] == 'bad':
+ raise exception.ProcessExecutionError
+ return 'fakecontents', None
+
+ self.stubs.Set(utils, 'execute', fake_execute)
+ contents = utils.read_file_as_root('good')
+ self.assertEqual(contents, 'fakecontents')
+ self.assertRaises(exception.FileNotFound,
+ utils.read_file_as_root, 'bad')
+
class IsUUIDLikeTestCase(test.TestCase):
def assertUUIDLike(self, val, expected):
@@ -679,3 +693,10 @@ class DeprecationTest(test.TestCase):
self.mox.ReplayAll()
result = utils.service_is_up(service)
self.assertFalse(result)
+
+ def test_hash_file(self):
+ data = 'Mary had a little lamb, its fleece as white as snow'
+ flo = StringIO.StringIO(data)
+ h1 = utils.hash_file(flo)
+ h2 = hashlib.sha1(data).hexdigest()
+ self.assertEquals(h1, h2)
diff --git a/nova/tests/test_virt_drivers.py b/nova/tests/test_virt_drivers.py
index adf8f8eb8..2cda7a61e 100644
--- a/nova/tests/test_virt_drivers.py
+++ b/nova/tests/test_virt_drivers.py
@@ -225,6 +225,12 @@ class _VirtDriverTestCase(test.TestCase):
self.connection.list_instances())
@catch_notimplementederror
+ def test_get_volume_connector(self):
+ result = self.connection.get_volume_connector({'id': 'fake'})
+ self.assertTrue('ip' in result)
+ self.assertTrue('initiator' in result)
+
+ @catch_notimplementederror
def test_attach_detach_volume(self):
instance_ref, network_info = self._get_running_instance()
self.connection.attach_volume({'driver_volume_type': 'fake'},
@@ -444,13 +450,14 @@ class LibvirtConnTestCase(_VirtDriverTestCase):
# Point _VirtDriverTestCase at the right module
self.driver_module = nova.virt.libvirt.connection
+ FLAGS.firewall_driver = nova.virt.libvirt.firewall.drivers[0]
super(LibvirtConnTestCase, self).setUp()
FLAGS.rescue_image_id = "2"
FLAGS.rescue_kernel_id = "3"
FLAGS.rescue_ramdisk_id = None
def tearDown(self):
- super(LibvirtConnTestCase, self).setUp()
+ super(LibvirtConnTestCase, self).tearDown()
# Restore libvirt
import nova.virt.libvirt.connection
diff --git a/nova/utils.py b/nova/utils.py
index d1968ac4d..a98897d82 100644
--- a/nova/utils.py
+++ b/nova/utils.py
@@ -22,6 +22,7 @@
import contextlib
import datetime
import functools
+import hashlib
import inspect
import json
import lockfile
@@ -45,10 +46,10 @@ from eventlet import semaphore
from eventlet.green import subprocess
import netaddr
-from nova.common import cfg
from nova import exception
from nova import flags
from nova import log as logging
+from nova.openstack.common import cfg
LOG = logging.getLogger("nova.utils")
@@ -324,7 +325,7 @@ def default_flagfile(filename='nova.conf', args=None):
args = sys.argv
for arg in args:
if arg.find('flagfile') != -1:
- break
+ return arg[arg.index('flagfile') + 1:]
else:
if not os.path.isabs(filename):
# turn relative filename into an absolute path
@@ -337,6 +338,7 @@ def default_flagfile(filename='nova.conf', args=None):
if os.path.exists(filename):
flagfile = '--flagfile=%s' % filename
args.insert(1, flagfile)
+ return filename
def debug(arg):
@@ -1194,6 +1196,13 @@ def read_cached_file(filename, cache_info, reload_func=None):
return cache_info['data']
+def hash_file(file_like_object):
+ """Generate a hash for the contents of a file."""
+ checksum = hashlib.sha1()
+ any(map(checksum.update, iter(lambda: file_like_object.read(32768), '')))
+ return checksum.hexdigest()
+
+
@contextlib.contextmanager
def temporary_mutation(obj, **kwargs):
"""Temporarily set the attr on a particular object to a given value then
@@ -1404,3 +1413,12 @@ def generate_mac_address():
random.randint(0x00, 0xff),
random.randint(0x00, 0xff)]
return ':'.join(map(lambda x: "%02x" % x, mac))
+
+
+def read_file_as_root(file_path):
+ """Secure helper to read file as root."""
+ try:
+ out, _err = execute('cat', file_path, run_as_root=True)
+ return out
+ except exception.ProcessExecutionError:
+ raise exception.FileNotFound(file_path=file_path)
diff --git a/nova/virt/connection.py b/nova/virt/connection.py
index ad9998fa2..44bed9b4c 100644
--- a/nova/virt/connection.py
+++ b/nova/virt/connection.py
@@ -56,6 +56,7 @@ def get_connection(read_only=False):
* fake
* libvirt
* xenapi
+ * vmwareapi
"""
# TODO(termie): maybe lazy load after initial check for permissions
# TODO(termie): check whether we can be disconnected
diff --git a/nova/virt/disk/api.py b/nova/virt/disk/api.py
index 223f08a2f..929e17a55 100644
--- a/nova/virt/disk/api.py
+++ b/nova/virt/disk/api.py
@@ -29,10 +29,10 @@ import json
import os
import tempfile
-from nova.common import cfg
from nova import exception
from nova import flags
from nova import log as logging
+from nova.openstack.common import cfg
from nova import utils
from nova.virt.disk import guestfs
from nova.virt.disk import loop
diff --git a/nova/virt/disk/nbd.py b/nova/virt/disk/nbd.py
index 19904d694..d43fd3250 100644
--- a/nova/virt/disk/nbd.py
+++ b/nova/virt/disk/nbd.py
@@ -18,8 +18,8 @@
import os
import time
-from nova.common import cfg
from nova import flags
+from nova.openstack.common import cfg
from nova import utils
from nova.virt.disk import mount
diff --git a/nova/virt/driver.py b/nova/virt/driver.py
index 84037e6dd..d87a7286a 100644
--- a/nova/virt/driver.py
+++ b/nova/virt/driver.py
@@ -612,3 +612,28 @@ class ComputeDriver(object):
"""
# TODO(tr3buchet): update all subclasses and remove this
return True
+
+ def manage_image_cache(self, context):
+ """
+ Manage the driver's local image cache.
+
+ Some drivers chose to cache images for instances on disk. This method
+ is an opportunity to do management of that cache which isn't directly
+ related to other calls into the driver. The prime example is to clean
+ the cache and remove images which are no longer of interest.
+ """
+ raise NotImplementedError()
+
+ def get_volume_connector(self, instance):
+ """
+ Get connector information for the instance for attaching to volumes.
+
+ Connector information is a dictionary representing the ip of the
+ machine that will be making the connection and and the name of the
+ iscsi initiator as follows:
+ {
+ 'ip': ip,
+ 'initiator': initiator,
+ }
+ """
+ raise NotImplementedError()
diff --git a/nova/virt/fake.py b/nova/virt/fake.py
index 780d644eb..ff8da4724 100644
--- a/nova/virt/fake.py
+++ b/nova/virt/fake.py
@@ -301,3 +301,6 @@ class FakeConnection(driver.ComputeDriver):
def get_disk_available_least(self):
""" """
pass
+
+ def get_volume_connector(self, instance):
+ return {'ip': '127.0.0.1', 'initiator': 'fake'}
diff --git a/nova/virt/firewall.py b/nova/virt/firewall.py
index 2af28d7f1..2996147c7 100644
--- a/nova/virt/firewall.py
+++ b/nova/virt/firewall.py
@@ -17,11 +17,11 @@
# License for the specific language governing permissions and limitations
# under the License.
-from nova.common import cfg
from nova import context
from nova import db
from nova import flags
from nova import log as logging
+from nova.openstack.common import cfg
from nova import utils
from nova.virt import netutils
@@ -135,7 +135,7 @@ class IptablesFirewallDriver(FirewallDriver):
self.instances[instance['id']] = instance
self.network_infos[instance['id']] = network_info
self.add_filters_for_instance(instance)
- LOG.debug(_('Filters added to the instance: %r'), instance)
+ LOG.debug(_('Filters added to instance %s'), instance['uuid'])
self.refresh_provider_fw_rules()
LOG.debug(_('Provider Firewall Rules refreshed'))
self.iptables.apply()
diff --git a/nova/virt/interfaces.template b/nova/virt/interfaces.template
index ad8c1bcdb..e75c37357 100644
--- a/nova/virt/interfaces.template
+++ b/nova/virt/interfaces.template
@@ -14,7 +14,9 @@ iface ${ifc.name} inet static
netmask ${ifc.netmask}
broadcast ${ifc.broadcast}
gateway ${ifc.gateway}
+#if $ifc.dns
dns-nameservers ${ifc.dns}
+#end if
#if $use_ipv6
iface ${ifc.name} inet6 static
diff --git a/nova/virt/libvirt/connection.py b/nova/virt/libvirt/connection.py
index 4455dacec..37ad07736 100644
--- a/nova/virt/libvirt/connection.py
+++ b/nova/virt/libvirt/connection.py
@@ -54,7 +54,6 @@ from xml.etree import ElementTree
from nova.auth import manager
from nova import block_device
-from nova.common import cfg
from nova.compute import instance_types
from nova.compute import power_state
from nova import context as nova_context
@@ -63,10 +62,13 @@ from nova import exception
from nova import flags
import nova.image
from nova import log as logging
+from nova.openstack.common import cfg
from nova import utils
-from nova.virt.disk import api as disk
from nova.virt import driver
from nova.virt import images
+from nova.virt.disk import api as disk
+from nova.virt.libvirt import firewall
+from nova.virt.libvirt import imagecache
from nova.virt.libvirt import utils as libvirt_utils
@@ -186,10 +188,12 @@ class LibvirtConnection(driver.ComputeDriver):
super(LibvirtConnection, self).__init__()
self._host_state = None
+ self._initiator = None
self._wrapped_conn = None
self.container = None
self.read_only = read_only
-
+ if FLAGS.firewall_driver not in firewall.drivers:
+ FLAGS['firewall_driver'].SetDefault(firewall.drivers[0])
fw_class = utils.import_class(FLAGS.firewall_driver)
self.firewall_driver = fw_class(get_connection=self._get_connection)
self.vif_driver = utils.import_object(FLAGS.libvirt_vif_driver)
@@ -209,6 +213,8 @@ class LibvirtConnection(driver.ComputeDriver):
self.default_ephemeral_device = self._disk_prefix + 'b'
self.default_swap_device = self._disk_prefix + 'c'
+ self.image_cache_manager = imagecache.ImageCacheManager()
+
@property
def host_state(self):
if not self._host_state:
@@ -420,6 +426,16 @@ class LibvirtConnection(driver.ComputeDriver):
if os.path.exists(target):
shutil.rmtree(target)
+ def get_volume_connector(self, _instance):
+ if not self._initiator:
+ self._initiator = libvirt_utils.get_iscsi_initiator()
+ if not self._initiator:
+ LOG.warn(_('Could not determine iscsi initiator name'))
+ return {
+ 'ip': FLAGS.my_ip,
+ 'initiator': self._initiator,
+ }
+
def volume_driver_method(self, method_name, connection_info,
*args, **kwargs):
driver_type = connection_info.get('driver_volume_type')
@@ -690,8 +706,7 @@ class LibvirtConnection(driver.ComputeDriver):
block_device_info=block_device_info)
domain = self._create_new_domain(xml)
- LOG.debug(_("instance %s: is running"), instance['name'],
- instance=instance)
+ LOG.debug(_("instance is running"), instance=instance)
self.firewall_driver.apply_instance_filter(instance, network_info)
def _wait_for_boot():
@@ -701,13 +716,13 @@ class LibvirtConnection(driver.ComputeDriver):
try:
state = self.get_info(instance_name)['state']
except exception.NotFound:
- msg = _("During reboot, %s disappeared.") % instance_name
- LOG.error(msg, instance=instance)
+ LOG.error(_("During reboot, instance disappeared."),
+ instance=instance)
raise utils.LoopingCallDone
if state == power_state.RUNNING:
- msg = _("Instance %s spawned successfully.") % instance_name
- LOG.info(msg, instance=instance)
+ LOG.info(_("Instance spawned successfully."),
+ instance=instance)
raise utils.LoopingCallDone
timer = utils.LoopingCall(_wait_for_boot)
@@ -720,7 +735,7 @@ class LibvirtConnection(driver.ComputeDriver):
if virsh_output.startswith('/dev/'):
LOG.info(_("cool, it's a device"))
out, err = utils.execute('dd',
- "if=%s" % virsh_output,
+ 'if=%s' % virsh_output,
'iflag=nonblock',
run_as_root=True,
check_exit_code=False)
@@ -734,10 +749,11 @@ class LibvirtConnection(driver.ComputeDriver):
fp.write(data)
return fpath
- def _inject_files(self, instance, files):
+ def _inject_files(self, instance, files, partition):
disk_path = os.path.join(FLAGS.instances_path,
instance['name'], 'disk')
- disk.inject_files(disk_path, files, use_cow=FLAGS.use_cow_images)
+ disk.inject_files(disk_path, files, partition=partition,
+ use_cow=FLAGS.use_cow_images)
@exception.wrap_exception()
def get_console_output(self, instance):
@@ -748,7 +764,8 @@ class LibvirtConnection(driver.ComputeDriver):
if FLAGS.libvirt_type == 'xen':
# Xen is special
- virsh_output = utils.execute('virsh', 'ttyconsole',
+ virsh_output = utils.execute('virsh',
+ 'ttyconsole',
instance['name'])
data = self._flush_xen_console(virsh_output)
fpath = self._append_to_file(data, console_log)
@@ -823,7 +840,6 @@ class LibvirtConnection(driver.ComputeDriver):
"""
generating = 'image_id' not in kwargs
-
if not os.path.exists(target):
base_dir = os.path.join(FLAGS.instances_path, '_base')
if not os.path.exists(base_dir):
@@ -866,6 +882,16 @@ class LibvirtConnection(driver.ComputeDriver):
"""Grab image to raw format"""
images.fetch_to_raw(context, image_id, target, user_id, project_id)
+ if FLAGS.checksum_base_images:
+ f = open(target, 'r')
+ checksum = utils.hash_file(f)
+ f.close()
+
+ checksum_fname = '%s.sha1' % target
+ fd = os.open(checksum_filename, os.O_WRONLY, mode=0444)
+ os.write(fd, checksum)
+ os.close(fd)
+
@staticmethod
def _create_local(target, local_size, unit='G', fs_format=None):
"""Create a blank image of specified size"""
@@ -888,7 +914,7 @@ class LibvirtConnection(driver.ComputeDriver):
libvirt_utils.create_image('raw', target, '%dM' % swap_mb)
libvirt_utils.mkfs('swap', target)
- def _create_image(self, context, inst, libvirt_xml, suffix='',
+ def _create_image(self, context, instance, libvirt_xml, suffix='',
disk_images=None, network_info=None,
block_device_info=None):
if not suffix:
@@ -897,13 +923,13 @@ class LibvirtConnection(driver.ComputeDriver):
# syntactic nicety
def basepath(fname='', suffix=suffix):
return os.path.join(FLAGS.instances_path,
- inst['name'],
+ instance['name'],
fname + suffix)
# ensure directories exist and are writable
libvirt_utils.ensure_tree(basepath(suffix=''))
- LOG.info(_('instance %s: Creating image'), inst['name'])
+ LOG.info(_('Creating image'), instance=instance)
libvirt_utils.write_to_file(basepath('libvirt.xml'), libvirt_xml)
if FLAGS.libvirt_type == 'lxc':
@@ -914,9 +940,9 @@ class LibvirtConnection(driver.ComputeDriver):
libvirt_utils.write_to_file(basepath('console.log', ''), '', 007)
if not disk_images:
- disk_images = {'image_id': inst['image_ref'],
- 'kernel_id': inst['kernel_id'],
- 'ramdisk_id': inst['ramdisk_id']}
+ disk_images = {'image_id': instance['image_ref'],
+ 'kernel_id': instance['kernel_id'],
+ 'ramdisk_id': instance['ramdisk_id']}
if disk_images['kernel_id']:
fname = disk_images['kernel_id']
@@ -925,8 +951,8 @@ class LibvirtConnection(driver.ComputeDriver):
target=basepath('kernel'),
fname=fname,
image_id=disk_images['kernel_id'],
- user_id=inst['user_id'],
- project_id=inst['project_id'])
+ user_id=instance['user_id'],
+ project_id=instance['project_id'])
if disk_images['ramdisk_id']:
fname = disk_images['ramdisk_id']
self._cache_image(fn=libvirt_utils.fetch_image,
@@ -934,19 +960,19 @@ class LibvirtConnection(driver.ComputeDriver):
target=basepath('ramdisk'),
fname=fname,
image_id=disk_images['ramdisk_id'],
- user_id=inst['user_id'],
- project_id=inst['project_id'])
+ user_id=instance['user_id'],
+ project_id=instance['project_id'])
root_fname = hashlib.sha1(str(disk_images['image_id'])).hexdigest()
- size = inst['root_gb'] * 1024 * 1024 * 1024
+ size = instance['root_gb'] * 1024 * 1024 * 1024
- inst_type_id = inst['instance_type_id']
+ inst_type_id = instance['instance_type_id']
inst_type = instance_types.get_instance_type(inst_type_id)
if size == 0 or suffix == '.rescue':
size = None
root_fname += "_sm"
else:
- root_fname += "_%d" % inst['root_gb']
+ root_fname += "_%d" % instance['root_gb']
if not self._volume_in_mapping(self.default_root_device,
block_device_info):
@@ -956,31 +982,31 @@ class LibvirtConnection(driver.ComputeDriver):
fname=root_fname,
cow=FLAGS.use_cow_images,
image_id=disk_images['image_id'],
- user_id=inst['user_id'],
- project_id=inst['project_id'],
+ user_id=instance['user_id'],
+ project_id=instance['project_id'],
size=size)
- ephemeral_gb = inst['ephemeral_gb']
+ ephemeral_gb = instance['ephemeral_gb']
if ephemeral_gb and not self._volume_in_mapping(
self.default_ephemeral_device, block_device_info):
fn = functools.partial(self._create_ephemeral,
fs_label='ephemeral0',
- os_type=inst.os_type)
+ os_type=instance.os_type)
self._cache_image(fn=fn,
target=basepath('disk.local'),
fname="ephemeral_%s_%s_%s" %
- ("0", ephemeral_gb, inst.os_type),
+ ("0", ephemeral_gb, instance.os_type),
cow=FLAGS.use_cow_images,
ephemeral_size=ephemeral_gb)
for eph in driver.block_device_info_get_ephemerals(block_device_info):
fn = functools.partial(self._create_ephemeral,
fs_label='ephemeral%d' % eph['num'],
- os_type=inst.os_type)
+ os_type=instance.os_type)
self._cache_image(fn=fn,
target=basepath(_get_eph_disk(eph)),
fname="ephemeral_%s_%s_%s" %
- (eph['num'], eph['size'], inst.os_type),
+ (eph['num'], eph['size'], instance.os_type),
cow=FLAGS.use_cow_images,
ephemeral_size=eph['size'])
@@ -1005,11 +1031,11 @@ class LibvirtConnection(driver.ComputeDriver):
# partitioned disk image where the target partition is the first
# partition
target_partition = None
- if not inst['kernel_id']:
+ if not instance['kernel_id']:
target_partition = "1"
- config_drive_id = inst.get('config_drive_id')
- config_drive = inst.get('config_drive')
+ config_drive_id = instance.get('config_drive_id')
+ config_drive = instance.get('config_drive')
if any((FLAGS.libvirt_type == 'lxc', config_drive, config_drive_id)):
target_partition = None
@@ -1020,14 +1046,14 @@ class LibvirtConnection(driver.ComputeDriver):
target=basepath('disk.config'),
fname=fname,
image_id=config_drive_id,
- user_id=inst['user_id'],
- project_id=inst['project_id'],)
+ user_id=instance['user_id'],
+ project_id=instance['project_id'],)
elif config_drive:
self._create_local(basepath('disk.config'), 64, unit='M',
fs_format='msdos') # 64MB
- if inst['key_data']:
- key = str(inst['key_data'])
+ if instance['key_data']:
+ key = str(instance['key_data'])
else:
key = None
net = None
@@ -1069,22 +1095,21 @@ class LibvirtConnection(driver.ComputeDriver):
searchList=[{'interfaces': nets,
'use_ipv6': FLAGS.use_ipv6}]))
- metadata = inst.get('metadata')
+ metadata = instance.get('metadata')
if any((key, net, metadata)):
- inst_name = inst['name']
+ instance_name = instance['name']
if config_drive: # Should be True or None by now.
injection_path = basepath('disk.config')
img_id = 'config-drive'
else:
injection_path = basepath('disk')
- img_id = inst.image_ref
+ img_id = instance.image_ref
for injection in ('metadata', 'key', 'net'):
if locals()[injection]:
- LOG.info(_('instance %(inst_name)s: injecting '
- '%(injection)s into image %(img_id)s'
- % locals()))
+ LOG.info(_('Injecting %(injection)s into image %(img_id)s'
+ % locals()), instance=instance)
try:
disk.inject_data(injection_path, key, net, metadata,
partition=target_partition,
@@ -1092,8 +1117,9 @@ class LibvirtConnection(driver.ComputeDriver):
except Exception as e:
# This could be a windows image, or a vmdk format disk
- LOG.warn(_('instance %(inst_name)s: ignoring error injecting'
- ' data into image %(img_id)s (%(e)s)') % locals())
+ LOG.warn(_('Ignoring error injecting data into image '
+ '%(img_id)s (%(e)s)') % locals(),
+ instance=instance)
if FLAGS.libvirt_type == 'lxc':
self.container = disk.setup_container(basepath('disk'),
@@ -1103,9 +1129,10 @@ class LibvirtConnection(driver.ComputeDriver):
if FLAGS.libvirt_type == 'uml':
libvirt_utils.chown(basepath('disk'), 'root')
- files_to_inject = inst.get('injected_files')
+ files_to_inject = instance.get('injected_files')
if files_to_inject:
- self._inject_files(inst, files_to_inject)
+ self._inject_files(instance, files_to_inject,
+ partition=target_partition)
@staticmethod
def _volume_in_mapping(mount_device, block_device_info):
@@ -1996,6 +2023,10 @@ class LibvirtConnection(driver.ComputeDriver):
"""Sets the specified host's ability to accept new instances."""
pass
+ def manage_image_cache(self, context):
+ """Manage the local cache of images."""
+ self.image_cache_manager.verify_base_images(context)
+
class HostState(object):
"""Manages information about the compute node through libvirt"""
diff --git a/nova/virt/libvirt/firewall.py b/nova/virt/libvirt/firewall.py
index 7045b4abc..0bfd89de1 100644
--- a/nova/virt/libvirt/firewall.py
+++ b/nova/virt/libvirt/firewall.py
@@ -33,6 +33,8 @@ from nova.virt import netutils
LOG = logging.getLogger("nova.virt.libvirt.firewall")
FLAGS = flags.FLAGS
+# The default Firewall driver must be listed at position 0
+drivers = ['nova.virt.libvirt.firewall.IptablesFirewallDriver', ]
try:
import libvirt
diff --git a/nova/virt/libvirt/imagecache.py b/nova/virt/libvirt/imagecache.py
new file mode 100644
index 000000000..04b35f1ef
--- /dev/null
+++ b/nova/virt/libvirt/imagecache.py
@@ -0,0 +1,364 @@
+#!/usr/bin/python
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 Michael Still and Canonical Inc
+# 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.
+
+"""Image cache manager.
+
+The cache manager implements the specification at
+http://wiki.openstack.org/nova-image-cache-management.
+
+"""
+
+import datetime
+import hashlib
+import os
+import sys
+import time
+
+from nova import compute
+from nova import context as db_context
+from nova import db
+from nova import flags
+from nova import image
+from nova import log as logging
+from nova.openstack.common import cfg
+from nova import utils
+from nova.virt.libvirt import utils as virtutils
+
+
+LOG = logging.getLogger('nova.compute.imagecache')
+
+imagecache_opts = [
+ cfg.BoolOpt('remove_unused_base_images',
+ default=False,
+ help='Should unused base images be removed?'),
+ cfg.IntOpt('remove_unused_minimum_age_seconds',
+ default=3600,
+ help='Unused base images younger than this will not be '
+ 'removed'),
+ ]
+
+flags.DECLARE('instances_path', 'nova.compute.manager')
+FLAGS = flags.FLAGS
+FLAGS.add_options(imagecache_opts)
+
+
+def read_stored_checksum(base_file):
+ """Read the checksum which was created at image fetch time.
+
+ Returns the checksum (as hex) or None.
+ """
+ checksum_file = '%s.sha1' % base_file
+ if not os.path.exists(checksum_file):
+ return None
+
+ f = open(checksum_file, 'r')
+ stored_checksum = f.read().rstrip()
+ f.close()
+ return stored_checksum
+
+
+class ImageCacheManager(object):
+ def __init__(self):
+ self.unexplained_images = []
+
+ def _list_base_images(self, base_dir):
+ """Return a list of the images present in _base.
+
+ Note that this does not return a value. It instead populates a class
+ variable with a list of images that we need to try and explain.
+ """
+ # Determine what images we have on disk. There will be other files in
+ # this directory (for example kernels) so we only grab the ones which
+ # are the right length to be disk images.
+ self.unexplained_images = []
+ digest_size = hashlib.sha1().digestsize * 2
+ for ent in os.listdir(base_dir):
+ if len(ent) == digest_size or len(ent) == digest_size + 3:
+ entpath = os.path.join(base_dir, ent)
+ if os.path.isfile(entpath):
+ self.unexplained_images.append(entpath)
+
+ def _list_running_instances(self, context):
+ """List running instances (on all compute nodes)."""
+ self.used_images = {}
+ self.image_popularity = {}
+
+ instances = db.instance_get_all(context)
+ for instance in instances:
+ image_ref_str = str(instance['image_ref'])
+ local, remote, insts = self.used_images.get(image_ref_str,
+ (0, 0, []))
+ if instance['host'] == FLAGS.host:
+ local += 1
+ else:
+ remote += 1
+ insts.append(instance['name'])
+ self.used_images[image_ref_str] = (local, remote, insts)
+
+ self.image_popularity.setdefault(image_ref_str, 0)
+ self.image_popularity[image_ref_str] += 1
+
+ def _list_backing_images(self):
+ """List the backing images currently in use."""
+ inuse_images = []
+ for ent in os.listdir(FLAGS.instances_path):
+ if ent.startswith('instance-'):
+ disk_path = os.path.join(FLAGS.instances_path, ent, 'disk')
+ if os.path.exists(disk_path):
+ backing_file = virtutils.get_disk_backing_file(disk_path)
+ LOG.debug(_('Instance %(instance)s is backed by '
+ '%(backing)s'),
+ {'instance': ent,
+ 'backing': backing_file})
+
+ backing_path = os.path.join(FLAGS.instances_path,
+ '_base', backing_file)
+ if not backing_path in inuse_images:
+ inuse_images.append(backing_path)
+
+ if backing_path in self.unexplained_images:
+ LOG.warning(_('Instance %(instance)s is using a '
+ 'backing file %(backing)s which does '
+ 'not appear in the image service'),
+ {'instance': ent,
+ 'backing': backing_file})
+ self.unexplained_images.remove(backing_path)
+
+ return inuse_images
+
+ def _find_base_file(self, base_dir, fingerprint):
+ """Find the base file matching this fingerprint.
+
+ Yields the name of the base file, and a boolean which is True if
+ the image is "small". Note that is is possible for more than one
+ yield to result from this check.
+
+ If no base file is found, then nothing is yielded.
+ """
+ base_file = os.path.join(base_dir, fingerprint)
+ if os.path.exists(base_file):
+ yield base_file, False
+
+ base_file = os.path.join(base_dir, fingerprint + '_sm')
+ if os.path.exists(base_file):
+ yield base_file, True
+
+ def _verify_checksum(self, img, base_file):
+ """Compare the checksum stored on disk with the current file.
+
+ Note that if the checksum fails to verify this is logged, but no actual
+ action occurs. This is something sysadmins should monitor for and
+ handle manually when it occurs.
+ """
+ f = open(base_file, 'r')
+ current_checksum = utils.hash_file(f)
+ f.close()
+
+ stored_checksum = read_stored_checksum(base_file)
+
+ if stored_checksum:
+ if current_checksum != stored_checksum:
+ LOG.error(_('%(container_format)s-%(id)s '
+ '(%(base_file)s): '
+ 'image verification failed'),
+ {'container_format': img['container_format'],
+ 'id': img['id'],
+ 'base_file': base_file})
+ return False
+
+ else:
+ return True
+
+ else:
+ LOG.debug(_('%(container_format)s-%(id)s (%(base_file)s): '
+ 'image verification skipped, no hash stored'),
+ {'container_format': img['container_format'],
+ 'id': img['id'],
+ 'base_file': base_file})
+ return None
+
+ def _remove_base_file(self, base_file):
+ """Remove a single base file if it is old enough.
+
+ Returns nothing.
+ """
+ mtime = os.path.getmtime(base_file)
+ age = time.time() - mtime
+
+ if age < FLAGS.remove_unused_minimum_age_seconds:
+ LOG.info(_('Base file too young to remove: %s'),
+ base_file)
+ else:
+ LOG.info(_('Removing base file: %s'), base_file)
+ try:
+ os.remove(base_file)
+ signature = base_file + '.sha1'
+ if os.path.exists(signature):
+ os.remove(signature)
+ except OSError, e:
+ LOG.error(_('Failed to remove %(base_file)s, '
+ 'error was %(error)s'),
+ {'base_file': base_file,
+ 'error': e})
+
+ def _handle_base_image(self, img, base_file, image_small):
+ """Handle the checks for a single base image."""
+
+ # TODO(mikal): Write a unit test for this method
+ image_bad = False
+ image_in_use = False
+
+ if base_file:
+ LOG.debug(_('%(container_format)s-%(id)s (%(base_file)s): '
+ 'checking'),
+ {'container_format': img['container_format'],
+ 'id': img['id'],
+ 'base_file': base_file})
+
+ if base_file in self.unexplained_images:
+ self.unexplained_images.remove(base_file)
+ self._verify_checksum(img, base_file)
+
+ else:
+ LOG.debug(_('%(container_format)s-%(id)s (%(base_file)s): '
+ 'base file absent'),
+ {'container_format': img['container_format'],
+ 'id': img['id'],
+ 'base_file': base_file})
+ base_file = None
+
+ instances = []
+ if str(img['id']) in self.used_images:
+ local, remote, instances = self.used_images[str(img['id'])]
+ if local > 0:
+ LOG.debug(_('%(container_format)s-%(id)s (%(base_file)s): '
+ 'in use: on this node %(local)d local, '
+ '%(remote)d on other nodes'),
+ {'container_format': img['container_format'],
+ 'id': img['id'],
+ 'base_file': base_file,
+ 'local': local,
+ 'remote': remote})
+
+ image_in_use = True
+ self.active_base_files.append(base_file)
+
+ if not base_file:
+ LOG.warning(_('%(container_format)s-%(id)s '
+ '(%(base_file)s): warning -- an absent '
+ 'base file is in use! instances: '
+ '%(instance_list)s'),
+ {'container_format':
+ img['container_format'],
+ 'id': img['id'],
+ 'base_file': base_file,
+ 'instance_list': ' '.join(instances)})
+
+ else:
+ LOG.debug(_('%(container_format)s-%(id)s (%(base_file)s): '
+ 'in: on other nodes (%(remote)d on other '
+ 'nodes)'),
+ {'container_format': img['container_format'],
+ 'id': img['id'],
+ 'base_file': base_file,
+ 'remote': remote})
+ if image_bad:
+ self.corrupt_base_files.append(base_file)
+
+ if base_file:
+ if not image_in_use:
+ LOG.debug(_('%(container_format)s-%(id)s (%(base_file)s): '
+ 'image is not in use'),
+ {'container_format': img['container_format'],
+ 'id': img['id'],
+ 'base_file': base_file})
+ self.removable_base_files.append(base_file)
+
+ else:
+ LOG.debug(_('%(container_format)s-%(id)s (%(base_file)s): '
+ 'image is in use'),
+ {'container_format': img['container_format'],
+ 'id': img['id'],
+ 'base_file': base_file})
+
+ def verify_base_images(self, context):
+ """Verify that base images are in a reasonable state."""
+ # TODO(mikal): Write a unit test for this method
+
+ base_dir = os.path.join(FLAGS.instances_path, '_base')
+ if not os.path.exists(base_dir):
+ LOG.debug(_('Skipping verification, no base directory at %s'),
+ base_dir)
+ return
+
+ LOG.debug(_('Verify base images'))
+ self._list_base_images(base_dir)
+ self._list_running_instances(context)
+
+ # Determine what images are in glance
+ image_service = image.get_default_image_service()
+
+ self.active_base_files = []
+ self.corrupt_base_files = []
+ self.removable_base_files = []
+
+ # GlanceImageService.detail uses _fetch_images which handles pagination
+ # for us
+ for img in image_service.detail(context):
+ if img['container_format'] != 'ami':
+ continue
+
+ fingerprint = hashlib.sha1(str(img['id'])).hexdigest()
+ for base_file, image_small in self._find_base_file(base_dir,
+ fingerprint):
+ self._handle_base_image(img, base_file, image_small)
+
+ # Elements remaining in unexplained_images are not currently in
+ # glance. That doesn't mean that they're really not in use though
+ # (consider images which have been removed from glance but are still
+ # used by instances). So, we check the backing file for any running
+ # instances as well.
+ if self.unexplained_images:
+ inuse_backing_images = self._list_backing_images()
+ if inuse_backing_images:
+ for backing_path in inuse_backing_images:
+ self.active_base_files.append(backing_path)
+
+ # Anything left is an unknown base image
+ for img in self.unexplained_images:
+ LOG.warning(_('Unknown base file: %s'), img)
+ self.removable_base_files.append(img)
+
+ # Dump these lists
+ if self.active_base_files:
+ LOG.info(_('Active base files: %s'),
+ ' '.join(self.active_base_files))
+ if self.corrupt_base_files:
+ LOG.info(_('Corrupt base files: %s'),
+ ' '.join(self.corrupt_base_files))
+
+ if self.removable_base_files:
+ LOG.info(_('Removable base files: %s'),
+ ' '.join(self.removable_base_files))
+
+ if FLAGS.remove_unused_base_images:
+ for base_file in self.removable_base_files:
+ self._remove_base_file(base_file)
+
+ # That's it
+ LOG.debug(_('Verification complete'))
diff --git a/nova/virt/libvirt/utils.py b/nova/virt/libvirt/utils.py
index 65254936a..f96128124 100644
--- a/nova/virt/libvirt/utils.py
+++ b/nova/virt/libvirt/utils.py
@@ -23,9 +23,9 @@ import os
import random
import shutil
-from nova.common import cfg
from nova import exception
from nova import flags
+from nova.openstack.common import cfg
from nova import utils
from nova.virt.disk import api as disk
from nova.virt import images
@@ -44,6 +44,16 @@ def execute(*args, **kwargs):
return utils.execute(*args, **kwargs)
+def get_iscsi_initiator():
+ """Get iscsi initiator name for this machine"""
+ # NOTE(vish) openiscsi stores initiator name in a file that
+ # needs root permission to read.
+ contents = utils.read_file_as_root('/etc/iscsi/initiatorname.iscsi')
+ for l in contents.split('\n'):
+ if l.startswith('InitiatorName='):
+ return l[l.index('=') + 1:].strip()
+
+
def create_image(disk_format, path, size):
"""Create a disk image
diff --git a/nova/virt/libvirt/vif.py b/nova/virt/libvirt/vif.py
index 503c33d0f..344dae573 100644
--- a/nova/virt/libvirt/vif.py
+++ b/nova/virt/libvirt/vif.py
@@ -19,11 +19,11 @@
"""VIF drivers for libvirt."""
-from nova.common import cfg
from nova import exception
from nova import flags
from nova import log as logging
from nova.network import linux_net
+from nova.openstack.common import cfg
from nova import utils
from nova.virt import netutils
from nova.virt.vif import VIFDriver
@@ -82,13 +82,14 @@ class LibvirtBridgeDriver(VIFDriver):
if (not network.get('multi_host') and
mapping.get('should_create_bridge')):
if mapping.get('should_create_vlan'):
+ iface = FLAGS.vlan_interface or network['bridge_interface']
LOG.debug(_('Ensuring vlan %(vlan)s and bridge %(bridge)s'),
{'vlan': network['vlan'],
'bridge': network['bridge']})
linux_net.LinuxBridgeInterfaceDriver.ensure_vlan_bridge(
network['vlan'],
network['bridge'],
- network['bridge_interface'])
+ iface)
else:
LOG.debug(_("Ensuring bridge %s"), network['bridge'])
linux_net.LinuxBridgeInterfaceDriver.ensure_bridge(
diff --git a/nova/virt/vmwareapi/vim.py b/nova/virt/vmwareapi/vim.py
index 0ce1be645..648231087 100644
--- a/nova/virt/vmwareapi/vim.py
+++ b/nova/virt/vmwareapi/vim.py
@@ -26,8 +26,8 @@ try:
except ImportError:
suds = None
-from nova.common import cfg
from nova import flags
+from nova.openstack.common import cfg
from nova.virt.vmwareapi import error_util
RESP_NOT_XML_ERROR = 'Response is "text/html", not "text/xml"'
diff --git a/nova/virt/vmwareapi/vmops.py b/nova/virt/vmwareapi/vmops.py
index 172936def..af867dc6a 100644
--- a/nova/virt/vmwareapi/vmops.py
+++ b/nova/virt/vmwareapi/vmops.py
@@ -26,11 +26,11 @@ import urllib
import urllib2
import uuid
-from nova.common import cfg
from nova.compute import power_state
from nova import exception
from nova import flags
from nova import log as logging
+from nova.openstack.common import cfg
from nova import utils
from nova.virt.vmwareapi import vim_util
from nova.virt.vmwareapi import vm_util
diff --git a/nova/virt/vmwareapi_conn.py b/nova/virt/vmwareapi_conn.py
index d71b922c9..909969fac 100644
--- a/nova/virt/vmwareapi_conn.py
+++ b/nova/virt/vmwareapi_conn.py
@@ -36,12 +36,12 @@ import time
from eventlet import event
-from nova.common import cfg
from nova import context
from nova import db
from nova import exception
from nova import flags
from nova import log as logging
+from nova.openstack.common import cfg
from nova import utils
from nova.virt import driver
from nova.virt.vmwareapi import error_util
@@ -178,6 +178,15 @@ class VMWareESXConnection(driver.ComputeDriver):
"""Return link to instance's ajax console."""
return self._vmops.get_ajax_console(instance)
+ def get_volume_connector(self, _instance):
+ """Return volume connector information"""
+ # TODO(vish): When volume attaching is supported, return the
+ # proper initiator iqn.
+ return {
+ 'ip': FLAGS.vmwareapi_host_ip,
+ 'initiator': None
+ }
+
def attach_volume(self, connection_info, instance_name, mountpoint):
"""Attach volume storage to VM instance."""
pass
diff --git a/nova/virt/xenapi/firewall.py b/nova/virt/xenapi/firewall.py
index 823115220..dc75aa46a 100644
--- a/nova/virt/xenapi/firewall.py
+++ b/nova/virt/xenapi/firewall.py
@@ -31,6 +31,10 @@ from nova.virt.firewall import IptablesFirewallDriver
LOG = logging.getLogger("nova.virt.xenapi.firewall")
FLAGS = flags.FLAGS
+# The default Firewall driver must be listed at position 0
+drivers = ['nova.virt.firewall.IptablesFirewallDriver',
+ 'nova.virt.xenapi.firewall.Dom0IptablesFirewallDriver', ]
+
class Dom0IptablesFirewallDriver(IptablesFirewallDriver):
""" Dom0IptablesFirewallDriver class
diff --git a/nova/virt/xenapi/vif.py b/nova/virt/xenapi/vif.py
index c1b752d5a..f5b086aaa 100644
--- a/nova/virt/xenapi/vif.py
+++ b/nova/virt/xenapi/vif.py
@@ -19,9 +19,9 @@
"""VIF drivers for XenAPI."""
-from nova.common import cfg
from nova import flags
from nova import log as logging
+from nova.openstack.common import cfg
from nova.virt.vif import VIFDriver
from nova.virt.xenapi.network_utils import NetworkHelper
from nova.virt.xenapi.vm_utils import VMHelper
@@ -77,7 +77,7 @@ class XenAPIBridgeDriver(XenVIFDriver):
vlan_num = network['vlan']
bridge = network['bridge']
- bridge_interface = network['bridge_interface']
+ bridge_interface = FLAGS.vlan_interface or network['bridge_interface']
# Check whether bridge already exists
# Retrieve network whose name_label is "bridge"
network_ref = NetworkHelper.find_network_with_name_label(
diff --git a/nova/virt/xenapi/vm_utils.py b/nova/virt/xenapi/vm_utils.py
index 9ddf8b22a..638042e35 100644
--- a/nova/virt/xenapi/vm_utils.py
+++ b/nova/virt/xenapi/vm_utils.py
@@ -33,11 +33,11 @@ import uuid
from decimal import Decimal, InvalidOperation
from xml.dom import minidom
-from nova.common import cfg
from nova import exception
from nova import flags
from nova.image import glance
from nova import log as logging
+from nova.openstack.common import cfg
from nova import utils
from nova.compute import instance_types
from nova.compute import power_state
@@ -513,7 +513,7 @@ class VMHelper(HelperBase):
# NOTE(jk0): We use a FAT32 filesystem for the Windows swap
# partition because that is what parted supports.
is_windows = instance.os_type == "windows"
- fs_type = "fat32" if is_windows else "linux-swap"
+ fs_type = "vfat" if is_windows else "linux-swap"
cls._generate_disk(session, instance, vm_ref, userdevice,
'swap', swap_mb, fs_type)
diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py
index c7f713ea2..c2960b86a 100644
--- a/nova/virt/xenapi/vmops.py
+++ b/nova/virt/xenapi/vmops.py
@@ -31,7 +31,6 @@ import uuid
from eventlet import greenthread
-from nova.common import cfg
from nova.compute import api as compute
from nova.compute import power_state
from nova import context as nova_context
@@ -39,11 +38,14 @@ from nova import db
from nova import exception
from nova import flags
from nova import log as logging
+from nova.openstack.common import cfg
from nova import utils
from nova.virt import driver
-from nova.virt.xenapi import volume_utils
+from nova.virt.xenapi import firewall
from nova.virt.xenapi import network_utils
from nova.virt.xenapi import vm_utils
+from nova.virt.xenapi import volume_utils
+
VolumeHelper = volume_utils.VolumeHelper
NetworkHelper = network_utils.NetworkHelper
@@ -104,6 +106,8 @@ class VMOps(object):
self._session = session
self.poll_rescue_last_ran = None
VMHelper.XenAPI = self.XenAPI
+ if FLAGS.firewall_driver not in firewall.drivers:
+ FLAGS['firewall_driver'].SetDefault(firewall.drivers[0])
fw_class = utils.import_class(FLAGS.firewall_driver)
self.firewall_driver = fw_class(xenapi_session=self._session)
vif_impl = utils.import_class(FLAGS.xenapi_vif_driver)
@@ -418,10 +422,14 @@ class VMOps(object):
# Attach any other disks
for vdi in vdis[1:]:
- if generate_swap and vdi['vdi_type'] == 'swap':
- continue
vdi_ref = self._session.call_xenapi('VDI.get_by_uuid',
vdi['vdi_uuid'])
+
+ if generate_swap and vdi['vdi_type'] == 'swap':
+ # We won't be using it, so don't let it leak
+ VMHelper.destroy_vdi(self._session, vdi_ref)
+ continue
+
VolumeHelper.create_vbd(session=self._session, vm_ref=vm_ref,
vdi_ref=vdi_ref, userdevice=userdevice,
bootable=False)
@@ -642,7 +650,7 @@ class VMOps(object):
#TODO(sirp): Add quiesce and VSS locking support when Windows support
# is added
- logging.debug(_("Starting snapshot for VM %s"), instance)
+ logging.debug(_("Starting snapshot for VM %s"), instance['uuid'])
vm_ref = VMHelper.lookup(self._session, instance.name)
label = "%s-snapshot" % instance.name
diff --git a/nova/virt/xenapi_conn.py b/nova/virt/xenapi_conn.py
index 6fda205d0..e034cb3ca 100644
--- a/nova/virt/xenapi_conn.py
+++ b/nova/virt/xenapi_conn.py
@@ -70,13 +70,13 @@ from eventlet import queue
from eventlet import tpool
from eventlet import timeout
-from nova.common import cfg
from nova import context
from nova import db
from nova import exception
from nova import utils
from nova import flags
from nova import log as logging
+from nova.openstack.common import cfg
from nova.virt import driver
from nova.virt.xenapi import vm_utils
from nova.virt.xenapi.vmops import VMOps
@@ -179,6 +179,7 @@ class XenAPIConnection(driver.ComputeDriver):
self._host_state = None
self._product_version = self._session.get_product_version()
self._vmops = VMOps(self._session, self._product_version)
+ self._initiator = None
@property
def host_state(self):
@@ -327,13 +328,9 @@ class XenAPIConnection(driver.ComputeDriver):
for iusage in self._vmops.get_all_bw_usage(start_time, stop_time).\
values():
for macaddr, usage in iusage.iteritems():
- vi = db.virtual_interface_get_by_address(
- context.get_admin_context(),
- macaddr)
- if vi:
- bwusage.append(dict(virtual_interface=vi,
- bw_in=usage['bw_in'],
- bw_out=usage['bw_out']))
+ bwusage.append(dict(mac_address=macaddr,
+ bw_in=usage['bw_in'],
+ bw_out=usage['bw_out']))
return bwusage
def get_console_output(self, instance):
@@ -348,6 +345,20 @@ class XenAPIConnection(driver.ComputeDriver):
"""Return link to instance's ajax console"""
return self._vmops.get_vnc_console(instance)
+ def get_volume_connector(self, _instance):
+ """Return volume connector information"""
+ if not self._initiator:
+ stats = self.get_host_stats(update=True)
+ try:
+ self._initiator = stats['host_other-config']['iscsi_iqn']
+ except (TypeError, KeyError):
+ LOG.warn(_('Could not determine iscsi initiator name'))
+ self._initiator = None
+ return {
+ 'ip': self.get_host_ip_addr(),
+ 'initiator': self._initiator
+ }
+
@staticmethod
def get_host_ip_addr():
xs_url = urlparse.urlparse(FLAGS.xenapi_connection_url)
diff --git a/nova/vnc/__init__.py b/nova/vnc/__init__.py
index 0b2581203..ba7268e97 100644
--- a/nova/vnc/__init__.py
+++ b/nova/vnc/__init__.py
@@ -18,8 +18,8 @@
"""Module for VNC Proxying."""
-from nova.common import cfg
from nova import flags
+from nova.openstack.common import cfg
vnc_opts = [
diff --git a/nova/vnc/xvp_proxy.py b/nova/vnc/xvp_proxy.py
index bf9ee5975..dfaf9a47a 100644
--- a/nova/vnc/xvp_proxy.py
+++ b/nova/vnc/xvp_proxy.py
@@ -26,10 +26,10 @@ import eventlet.green
import eventlet.greenio
import eventlet.wsgi
-from nova.common import cfg
from nova import context
from nova import flags
from nova import log as logging
+from nova.openstack.common import cfg
from nova import rpc
from nova import version
from nova import wsgi
diff --git a/nova/volume/api.py b/nova/volume/api.py
index cc9cac019..d5042833e 100644
--- a/nova/volume/api.py
+++ b/nova/volume/api.py
@@ -244,22 +244,22 @@ class API(base.Base):
"args": {"volume_id": volume['id']}})
@wrap_check_policy
- def initialize_connection(self, context, volume, address):
+ def initialize_connection(self, context, volume, connector):
host = volume['host']
queue = self.db.queue_get_for(context, FLAGS.volume_topic, host)
return rpc.call(context, queue,
{"method": "initialize_connection",
"args": {"volume_id": volume['id'],
- "address": address}})
+ "connector": connector}})
@wrap_check_policy
- def terminate_connection(self, context, volume, address):
+ def terminate_connection(self, context, volume, connector):
host = volume['host']
queue = self.db.queue_get_for(context, FLAGS.volume_topic, host)
return rpc.call(context, queue,
{"method": "terminate_connection",
"args": {"volume_id": volume['id'],
- "address": address}})
+ "connector": connector}})
def _create_snapshot(self, context, volume, name, description,
force=False):
diff --git a/nova/volume/driver.py b/nova/volume/driver.py
index 0505b89b1..f00eb0800 100644
--- a/nova/volume/driver.py
+++ b/nova/volume/driver.py
@@ -24,10 +24,10 @@ import os
import time
from xml.etree import ElementTree
-from nova.common import cfg
from nova import exception
from nova import flags
from nova import log as logging
+from nova.openstack.common import cfg
from nova import utils
from nova.volume import iscsi
from nova.volume import volume_types
@@ -215,12 +215,12 @@ class VolumeDriver(object):
"""Make sure volume is exported."""
raise NotImplementedError()
- def initialize_connection(self, volume, address):
- """Allow connection to ip and return connection info."""
+ def initialize_connection(self, volume, connector):
+ """Allow connection to connector and return connection info."""
raise NotImplementedError()
- def terminate_connection(self, volume, address):
- """Disallow connection from ip"""
+ def terminate_connection(self, volume, connector):
+ """Disallow connection from connector"""
raise NotImplementedError()
def get_volume_stats(self, refresh=False):
@@ -409,7 +409,7 @@ class ISCSIDriver(VolumeDriver):
'-v', property_value)
return self._run_iscsiadm(iscsi_properties, iscsi_command)
- def initialize_connection(self, volume, address):
+ def initialize_connection(self, volume, connector):
"""Initializes the connection and returns connection info.
The iscsi driver returns a driver_volume_type of 'iscsi'.
@@ -433,7 +433,7 @@ class ISCSIDriver(VolumeDriver):
'data': iscsi_properties
}
- def terminate_connection(self, volume, address):
+ def terminate_connection(self, volume, connector):
pass
def check_for_export(self, context, volume_id):
@@ -461,13 +461,13 @@ class FakeISCSIDriver(ISCSIDriver):
"""No setup necessary in fake mode."""
pass
- def initialize_connection(self, volume, address):
+ def initialize_connection(self, volume, connector):
return {
'driver_volume_type': 'iscsi',
'data': {}
}
- def terminate_connection(self, volume, address):
+ def terminate_connection(self, volume, connector):
pass
@staticmethod
@@ -532,7 +532,7 @@ class RBDDriver(VolumeDriver):
"""Removes an export for a logical volume"""
pass
- def initialize_connection(self, volume, address):
+ def initialize_connection(self, volume, connector):
return {
'driver_volume_type': 'rbd',
'data': {
@@ -540,7 +540,7 @@ class RBDDriver(VolumeDriver):
}
}
- def terminate_connection(self, volume, address):
+ def terminate_connection(self, volume, connector):
pass
@@ -601,7 +601,7 @@ class SheepdogDriver(VolumeDriver):
"""Removes an export for a logical volume"""
pass
- def initialize_connection(self, volume, address):
+ def initialize_connection(self, volume, connector):
return {
'driver_volume_type': 'sheepdog',
'data': {
@@ -609,7 +609,7 @@ class SheepdogDriver(VolumeDriver):
}
}
- def terminate_connection(self, volume, address):
+ def terminate_connection(self, volume, connector):
pass
@@ -638,10 +638,10 @@ class LoggingVolumeDriver(VolumeDriver):
def remove_export(self, context, volume):
self.log_action('remove_export', volume)
- def initialize_connection(self, volume, address):
+ def initialize_connection(self, volume, connector):
self.log_action('initialize_connection', volume)
- def terminate_connection(self, volume, address):
+ def terminate_connection(self, volume, connector):
self.log_action('terminate_connection', volume)
def check_for_export(self, context, volume_id):
diff --git a/nova/volume/iscsi.py b/nova/volume/iscsi.py
index 66c293f15..f0934eb96 100644
--- a/nova/volume/iscsi.py
+++ b/nova/volume/iscsi.py
@@ -20,8 +20,8 @@ Helper code for the iSCSI volume driver.
"""
-from nova.common import cfg
from nova import flags
+from nova.openstack.common import cfg
from nova import utils
diff --git a/nova/volume/manager.py b/nova/volume/manager.py
index f22fcc2ca..15f26f79e 100644
--- a/nova/volume/manager.py
+++ b/nova/volume/manager.py
@@ -38,12 +38,12 @@ intact.
"""
-from nova.common import cfg
from nova import context
from nova import exception
from nova import flags
from nova import log as logging
from nova import manager
+from nova.openstack.common import cfg
from nova import rpc
from nova import utils
from nova.volume import volume_types
@@ -254,31 +254,51 @@ class VolumeManager(manager.SchedulerDependentManager):
# TODO(vish): refactor this into a more general "unreserve"
self.db.volume_detached(context, volume_id)
- def initialize_connection(self, context, volume_id, address):
- """Initialize volume to be connected from address.
+ def initialize_connection(self, context, volume_id, connector):
+ """Prepare volume for connection from host represented by connector.
This method calls the driver initialize_connection and returns
- it to the caller. The driver is responsible for doing any
- necessary security setup and returning a connection_info dictionary
- in the following format:
- {'driver_volume_type': driver_volume_type
- 'data': data}
+ it to the caller. The connector parameter is a dictionary with
+ information about the host that will connect to the volume in the
+ following format:
+ {
+ 'ip': ip,
+ 'initiator': initiator,
+ }
+
+ ip: the ip address of the connecting machine
+
+ initiator: the iscsi initiator name of the connecting machine.
+ This can be None if the connecting machine does not support iscsi
+ connections.
+
+ driver is responsible for doing any necessary security setup and
+ returning a connection_info dictionary in the following format:
+ {
+ 'driver_volume_type': driver_volume_type,
+ 'data': data,
+ }
driver_volume_type: a string to identify the type of volume. This
can be used by the calling code to determine the
strategy for connecting to the volume. This could
be 'iscsi', 'rbd', 'sheepdog', etc.
+
data: this is the data that the calling code will use to connect
to the volume. Keep in mind that this will be serialized to
json in various places, so it should not contain any non-json
data types.
"""
volume_ref = self.db.volume_get(context, volume_id)
- return self.driver.initialize_connection(volume_ref, address)
+ return self.driver.initialize_connection(volume_ref, connector)
+
+ def terminate_connection(self, context, volume_id, connector):
+ """Cleanup connection from host represented by connector.
- def terminate_connection(self, context, volume_id, address):
+ The format of connector is the same as for initialize_connection.
+ """
volume_ref = self.db.volume_get(context, volume_id)
- self.driver.terminate_connection(volume_ref, address)
+ self.driver.terminate_connection(volume_ref, connector)
def check_for_export(self, context, instance_id):
"""Make sure whether volume is exported."""
diff --git a/nova/volume/san.py b/nova/volume/san.py
index 25309768e..bc06d7e03 100644
--- a/nova/volume/san.py
+++ b/nova/volume/san.py
@@ -32,11 +32,10 @@ import string
import uuid
from xml.etree import ElementTree
-from nova.common import cfg
-
from nova import exception
from nova import flags
from nova import log as logging
+from nova.openstack.common import cfg
from nova import utils
from nova.utils import ssh_execute
from nova.volume.driver import ISCSIDriver
diff --git a/nova/volume/xensm.py b/nova/volume/xensm.py
index bf219f273..a706b10be 100644
--- a/nova/volume/xensm.py
+++ b/nova/volume/xensm.py
@@ -203,7 +203,7 @@ class XenSMDriver(VolumeDriver):
"""Safely, synchronously recreates an export for a logical volume."""
pass
- def initialize_connection(self, volume, address):
+ def initialize_connection(self, volume, connector):
try:
xensm_properties = dict(self.db.sm_volume_get(self.ctxt,
volume['id']))
@@ -236,5 +236,5 @@ class XenSMDriver(VolumeDriver):
'data': xensm_properties
}
- def terminate_connection(self, volume, address):
+ def terminate_connection(self, volume, connector):
pass
diff --git a/nova/vsa/api.py b/nova/vsa/api.py
index 9c2bc0ce2..08b9deb13 100644
--- a/nova/vsa/api.py
+++ b/nova/vsa/api.py
@@ -25,11 +25,11 @@ For assistance and guidelines pls contact
import sys
-from nova.common import cfg
from nova import compute
from nova import exception
from nova import flags
from nova import log as logging
+from nova.openstack.common import cfg
from nova import rpc
from nova import volume
from nova.compute import instance_types
diff --git a/nova/vsa/manager.py b/nova/vsa/manager.py
index 42b5b1032..4dab8e31f 100644
--- a/nova/vsa/manager.py
+++ b/nova/vsa/manager.py
@@ -22,12 +22,12 @@ Handles all processes relating to Virtual Storage Arrays (VSA).
"""
-from nova.common import cfg
from nova import compute
from nova import exception
from nova import flags
from nova import log as logging
from nova import manager
+from nova.openstack.common import cfg
from nova import volume
from nova import vsa
from nova import utils
diff --git a/po/pt_BR.po b/po/pt_BR.po
index 24fd24d55..ff44b8092 100644
--- a/po/pt_BR.po
+++ b/po/pt_BR.po
@@ -8,14 +8,14 @@ msgstr ""
"Project-Id-Version: nova\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2011-02-21 10:03-0500\n"
-"PO-Revision-Date: 2012-01-18 19:48+0000\n"
-"Last-Translator: Rafael Neri <Unknown>\n"
+"PO-Revision-Date: 2012-02-01 12:10+0000\n"
+"Last-Translator: Tiago Hillebrandt <tiagoscd@yahoo.com.br>\n"
"Language-Team: Brazilian Portuguese <pt_BR@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2012-01-19 05:06+0000\n"
-"X-Generator: Launchpad (build 14692)\n"
+"X-Launchpad-Export-Date: 2012-02-02 06:17+0000\n"
+"X-Generator: Launchpad (build 14738)\n"
#: ../nova/scheduler/chance.py:37 ../nova/scheduler/zone.py:55
#: ../nova/scheduler/simple.py:75 ../nova/scheduler/simple.py:110
@@ -56,22 +56,22 @@ msgstr "Exceção não capturada"
msgid "Quota exceeeded for %(pid)s, tried to create %(size)sG volume"
msgstr "Cota excedida para %(pid)s, tentando criar volume com %(size)sG"
-#: ../nova/volume/api.py:57
+#: ../nova/volume/api.py:87
#, python-format
msgid "Volume quota exceeded. You cannot create a volume of size %sG"
msgstr ""
"Cota excedida para o volume. Você não pode criar um volume com o tamanho %sG"
-#: ../nova/volume/api.py:102 ../nova/volume/api.py:172
-#: ../nova/volume/api.py:230
+#: ../nova/volume/api.py:134 ../nova/volume/api.py:210
+#: ../nova/volume/api.py:269
msgid "Volume status must be available"
msgstr "O status do volume parece estar disponível"
-#: ../nova/volume/api.py:174
+#: ../nova/volume/api.py:212
msgid "Volume is already attached"
msgstr "O Volume já está anexado"
-#: ../nova/volume/api.py:180
+#: ../nova/volume/api.py:218
msgid "Volume is already detached"
msgstr "O Volume já está desanexado"
@@ -92,12 +92,12 @@ msgstr "%(param)s propriedade não foi encontrada para %(_image_id)s"
msgid "No keypairs defined"
msgstr "Os keypairs não foram definidos"
-#: ../nova/api/openstack/v2/contrib/admin_actions.py:177
+#: ../nova/api/openstack/compute/contrib/admin_actions.py:185
#, python-format
msgid "Compute.api::lock %s"
msgstr "Compute.api::lock %s"
-#: ../nova/api/openstack/v2/contrib/admin_actions.py:193
+#: ../nova/api/openstack/compute/contrib/admin_actions.py:203
#, python-format
msgid "Compute.api::unlock %s"
msgstr "Compute.api::unlock %s"
@@ -107,27 +107,27 @@ msgstr "Compute.api::unlock %s"
msgid "Compute.api::get_lock %s"
msgstr "Compute.api::get_lock %s"
-#: ../nova/api/openstack/v2/contrib/admin_actions.py:145
+#: ../nova/api/openstack/compute/contrib/admin_actions.py:149
#, python-format
msgid "Compute.api::reset_network %s"
msgstr "Compute.api::reset_network %s"
-#: ../nova/api/openstack/v2/contrib/admin_actions.py:64
+#: ../nova/api/openstack/compute/contrib/admin_actions.py:58
#, python-format
msgid "Compute.api::pause %s"
msgstr "Compute.api::pause %s"
-#: ../nova/api/openstack/v2/contrib/admin_actions.py:81
+#: ../nova/api/openstack/compute/contrib/admin_actions.py:77
#, python-format
msgid "Compute.api::unpause %s"
msgstr "Compute.api::unpause %s"
-#: ../nova/api/openstack/v2/contrib/admin_actions.py:98
+#: ../nova/api/openstack/compute/contrib/admin_actions.py:96
#, python-format
msgid "compute.api::suspend %s"
msgstr "compute.api::suspend %s"
-#: ../nova/api/openstack/v2/contrib/admin_actions.py:115
+#: ../nova/api/openstack/compute/contrib/admin_actions.py:115
#, python-format
msgid "compute.api::resume %s"
msgstr "compute.api::resume %s"
@@ -191,17 +191,17 @@ msgid "Mountpoint %(mountpoint)s detached from instance %(instance_name)s"
msgstr ""
"Ponto de montagem %(mountpoint)s desanexada da instância %(instance_name)s"
-#: ../nova/compute/instance_types.py:115 ../nova/compute/instance_types.py:127
-#: ../nova/compute/instance_types.py:141 ../nova/compute/instance_types.py:152
+#: ../nova/compute/instance_types.py:122 ../nova/compute/instance_types.py:134
+#: ../nova/compute/instance_types.py:148 ../nova/compute/instance_types.py:159
#, python-format
msgid "Unknown instance type: %s"
msgstr "Tipo de instância desconhecido: %s"
-#: ../nova/crypto.py:50
+#: ../nova/crypto.py:51
msgid "Filename of root CA"
msgstr "Nome do arquivo da CA raiz"
-#: ../nova/crypto.py:53
+#: ../nova/crypto.py:54
msgid "Filename of private key"
msgstr "Nome do arquivo da chave privada"
@@ -209,25 +209,25 @@ msgstr "Nome do arquivo da chave privada"
msgid "Filename of root Certificate Revokation List"
msgstr "Nome de arquivo da Lista de Revogação de Certificados"
-#: ../nova/crypto.py:57
+#: ../nova/crypto.py:58
msgid "Where we keep our keys"
msgstr "Aonde armazenamos nossas chaves"
-#: ../nova/crypto.py:59
+#: ../nova/crypto.py:60
msgid "Where we keep our root CA"
msgstr "Onde mantemos nosso CA raiz"
-#: ../nova/crypto.py:61
+#: ../nova/crypto.py:62
msgid "Should we use a CA for each project?"
msgstr "Devemos usar um CA para cada projeto?"
-#: ../nova/crypto.py:65
+#: ../nova/crypto.py:66
#, python-format
msgid "Subject for certificate for users, %s for project, user, timestamp"
msgstr ""
"Assunto do certificado para usuários, %s para projeto, usuário, timestamp"
-#: ../nova/crypto.py:70
+#: ../nova/crypto.py:71
#, python-format
msgid "Subject for certificate for projects, %s for project, timestamp"
msgstr "Assunto do certificado para projetos, %s para projeto, timestamp"
@@ -237,7 +237,7 @@ msgstr "Assunto do certificado para projetos, %s para projeto, timestamp"
msgid "Subject for certificate for vpns, %s for project, timestamp"
msgstr "Assunto do certificado para vpns, %s para projeto, timestamp"
-#: ../nova/crypto.py:277
+#: ../nova/crypto.py:310
#, python-format
msgid "Flags path: %s"
msgstr "Localização dos sinalizadores: %s"
@@ -247,7 +247,7 @@ msgstr "Localização dos sinalizadores: %s"
msgid "Casting to %(topic)s %(host)s for %(method)s"
msgstr "Moldagem para %(topic)s %(host)s para %(method)s"
-#: ../nova/compute/manager.py:111
+#: ../nova/compute/manager.py:113
#, python-format
msgid "check_instance_lock: decorating: |%s|"
msgstr "check_instance_lock: decorating: |%s|"
@@ -259,36 +259,36 @@ msgid ""
msgstr ""
"check_instance_lock: argumentos: |%(self)s| |%(context)s| |%(instance_id)s|"
-#: ../nova/compute/manager.py:117
+#: ../nova/compute/manager.py:119
#, python-format
msgid "check_instance_lock: locked: |%s|"
msgstr "check_instance_lock: locked: |%s|"
-#: ../nova/compute/manager.py:119
+#: ../nova/compute/manager.py:121
#, python-format
msgid "check_instance_lock: admin: |%s|"
msgstr "check_instance_lock: admin: |%s|"
-#: ../nova/compute/manager.py:124
+#: ../nova/compute/manager.py:126
#, python-format
msgid "check_instance_lock: executing: |%s|"
msgstr "check_instance_lock: executando: |%s|"
-#: ../nova/compute/manager.py:128
+#: ../nova/compute/manager.py:130
#, python-format
msgid "check_instance_lock: not executing |%s|"
msgstr "check_instance_lock: not executando |%s|"
-#: ../nova/compute/manager.py:395
+#: ../nova/compute/manager.py:404
msgid "Instance has already been created"
msgstr "A instância já foi criada"
-#: ../nova/compute/manager.py:452
+#: ../nova/compute/manager.py:461
#, python-format
msgid "instance %s: starting..."
msgstr "instância %s: iniciando..."
-#: ../nova/virt/xenapi/vmops.py:233
+#: ../nova/virt/xenapi/vmops.py:234
#, python-format
msgid "instance %s: Failed to spawn"
msgstr "instância %s: falha na geração"
@@ -303,12 +303,12 @@ msgstr "Terminando a instância %s"
msgid "Deallocating address %s"
msgstr "Desalocando o endereço %s"
-#: ../nova/compute/manager.py:589
+#: ../nova/compute/manager.py:601
#, python-format
msgid "trying to destroy already destroyed instance: %s"
msgstr "tentando destruir instância já destruida: %s"
-#: ../nova/compute/manager.py:753
+#: ../nova/compute/manager.py:762
#, python-format
msgid "Rebooting instance %s"
msgstr "Reiniciando a instância %s"
@@ -322,7 +322,7 @@ msgstr ""
"tentando reiniciar uma instancia com estado diferente de running: "
"%(instance_id)s (estado: %(state)s esperado: %(running)s)"
-#: ../nova/compute/manager.py:813
+#: ../nova/compute/manager.py:826
#, python-format
msgid "instance %s: snapshotting"
msgstr "instância %s: fazendo um snapshot"
@@ -365,67 +365,67 @@ msgstr ""
msgid "instance %(nm)s: injecting file to %(plain_path)s"
msgstr "instância %(nm)s: injetando um arquivo para %(plain_path)s"
-#: ../nova/compute/manager.py:990
+#: ../nova/compute/manager.py:1005
#, python-format
msgid "instance %s: rescuing"
msgstr "instância %s: resgatando"
-#: ../nova/compute/manager.py:1013
+#: ../nova/compute/manager.py:1029
#, python-format
msgid "instance %s: unrescuing"
msgstr "instância %s: desfazendo o resgate"
-#: ../nova/compute/manager.py:1302
+#: ../nova/compute/manager.py:1324
#, python-format
msgid "instance %s: pausing"
msgstr "instância %s: pausando"
-#: ../nova/compute/manager.py:1320
+#: ../nova/compute/manager.py:1342
#, python-format
msgid "instance %s: unpausing"
msgstr "instância %s: saindo do pause"
-#: ../nova/compute/manager.py:1349
+#: ../nova/compute/manager.py:1371
#, python-format
msgid "instance %s: retrieving diagnostics"
msgstr "instância %s: recuperando os diagnósticos"
-#: ../nova/compute/manager.py:1358
+#: ../nova/compute/manager.py:1380
#, python-format
msgid "instance %s: suspending"
msgstr "instância %s: suspendendo"
-#: ../nova/compute/manager.py:1380
+#: ../nova/compute/manager.py:1402
#, python-format
msgid "instance %s: resuming"
msgstr "instância %s: resumindo"
-#: ../nova/compute/manager.py:1403
+#: ../nova/compute/manager.py:1425
#, python-format
msgid "instance %s: locking"
msgstr "instância %s: bloqueando"
-#: ../nova/compute/manager.py:1412
+#: ../nova/compute/manager.py:1434
#, python-format
msgid "instance %s: unlocking"
msgstr "instância %s: desbloqueando"
-#: ../nova/compute/manager.py:1420
+#: ../nova/compute/manager.py:1442
#, python-format
msgid "instance %s: getting locked state"
msgstr "instância %s: obtendo estado de bloqueio"
-#: ../nova/compute/manager.py:1430
+#: ../nova/compute/manager.py:1452
#, python-format
msgid "instance %s: reset network"
msgstr "instância %s: reset da rede"
-#: ../nova/compute/manager.py:1452 ../nova/api/ec2/cloud.py:823
+#: ../nova/compute/manager.py:1475 ../nova/api/ec2/cloud.py:781
#, python-format
msgid "Get console output for instance %s"
msgstr "Obter saída do console para instância %s"
-#: ../nova/compute/manager.py:1477
+#: ../nova/compute/manager.py:1500
#, python-format
msgid "instance %s: getting ajax console"
msgstr "instância %s: obtendo console ajax"
@@ -457,7 +457,7 @@ msgstr ""
"Desconectando volume %(volume_id)s do ponto de montagem %(mp)s na instância "
"%(instance_id)s"
-#: ../nova/compute/manager.py:1559
+#: ../nova/compute/manager.py:1603
#, python-format
msgid "Detaching volume from unknown instance %s"
msgstr "Desconectando volume da instância desconhecida %s"
@@ -484,55 +484,55 @@ msgstr "Todos os hosts tem muitos gigabytes"
msgid "All hosts have too many networks"
msgstr "Todos os hosts tem muitas interfaces de rede"
-#: ../nova/volume/manager.py:89
+#: ../nova/volume/manager.py:87
#, python-format
msgid "Re-exporting %s volumes"
msgstr "Re-exportando %s volumes"
-#: ../nova/volume/manager.py:94
+#: ../nova/volume/manager.py:92
#, python-format
msgid "volume %s: skipping export"
msgstr "volume %s: ignorando export"
-#: ../nova/volume/manager.py:100
+#: ../nova/volume/manager.py:98
#, python-format
msgid "volume %s: creating"
msgstr "volume %s: criando"
-#: ../nova/volume/manager.py:112
+#: ../nova/volume/manager.py:110
#, python-format
msgid "volume %(vol_name)s: creating lv of size %(vol_size)sG"
msgstr "volume %(vol_name)s: criando lv com tamanho %(vol_size)sG"
-#: ../nova/volume/manager.py:124
+#: ../nova/volume/manager.py:122
#, python-format
msgid "volume %s: creating export"
msgstr "volume %s: criando o export"
-#: ../nova/volume/manager.py:138
+#: ../nova/volume/manager.py:136
#, python-format
msgid "volume %s: created successfully"
msgstr "volume %s: criado com sucesso"
-#: ../nova/volume/manager.py:167
+#: ../nova/volume/manager.py:165
msgid "Volume is still attached"
msgstr "O volume continua atachado"
-#: ../nova/volume/manager.py:169
+#: ../nova/volume/manager.py:167
msgid "Volume is not local to this node"
msgstr "O volume não pertence à este node"
-#: ../nova/volume/manager.py:173
+#: ../nova/volume/manager.py:171
#, python-format
msgid "volume %s: removing export"
msgstr "volume %s: removendo export"
-#: ../nova/volume/manager.py:175
+#: ../nova/volume/manager.py:173
#, python-format
msgid "volume %s: deleting"
msgstr "volume %s: removendo"
-#: ../nova/volume/manager.py:190
+#: ../nova/volume/manager.py:188
#, python-format
msgid "volume %s: deleted successfully"
msgstr "volume %s: remoção realizada com sucesso"
@@ -568,8 +568,8 @@ msgid ""
"xenapi.fake does not have an implementation for %s or it has been called "
"with the wrong number of arguments"
msgstr ""
-"xenapi.fake não tem implementação para %s ou isto foi chamado com um número "
-"de argumentos inválidos"
+"xenapi.fake não tem implementação para %s ou foi chamado com um número de "
+"argumentos inválido"
#: ../nova/tests/test_cloud.py:256
msgid "Can't test instances without a real virtual env."
@@ -584,34 +584,34 @@ msgstr "É necessário assistir a instância %s até ela estar rodando..."
msgid "Failed to open connection to the hypervisor"
msgstr "Falha ao abrir a conexão com o hypervisor"
-#: ../nova/network/linux_net.py:937
+#: ../nova/network/linux_net.py:963
#, python-format
msgid "Starting VLAN inteface %s"
msgstr "Iniciando a VLAN %s"
-#: ../nova/network/linux_net.py:969
+#: ../nova/network/linux_net.py:995
#, python-format
msgid "Starting Bridge interface for %s"
msgstr "Iniciando a Bridge para %s"
#. pylint: disable=W0703
-#: ../nova/network/linux_net.py:669
+#: ../nova/network/linux_net.py:698
#, python-format
msgid "Hupping dnsmasq threw %s"
msgstr ""
-#: ../nova/network/linux_net.py:671
+#: ../nova/network/linux_net.py:700
#, python-format
msgid "Pid %d is stale, relaunching dnsmasq"
msgstr "Pid %d está ultrapassado, reiniciando dnsmasq"
#. pylint: disable=W0703
-#: ../nova/network/linux_net.py:731
+#: ../nova/network/linux_net.py:760
#, python-format
msgid "killing radvd threw %s"
msgstr ""
-#: ../nova/network/linux_net.py:733
+#: ../nova/network/linux_net.py:762
#, python-format
msgid "Pid %d is stale, relaunching radvd"
msgstr "Pid %d está ultrapassado, reiniciando radvd"
@@ -635,7 +635,7 @@ msgstr "Classe %s não pode ser encontrada"
#: ../nova/utils.py:150
#, python-format
msgid "Fetching %s"
-msgstr "Obtendo %s"
+msgstr "Buscando %s"
#: ../nova/utils.py:201
#, python-format
@@ -650,35 +650,35 @@ msgstr "Resultado foi %s"
#: ../nova/utils.py:273
#, python-format
msgid "Running cmd (SSH): %s"
-msgstr "Rodando o comando (SSH): %s"
+msgstr "Executando o comando (SSH): %s"
#: ../nova/utils.py:337
#, python-format
msgid "debug in callback: %s"
-msgstr "debug em callback: %s"
+msgstr "depuração em retorno de chamada: %s"
#: ../nova/utils.py:342
#, python-format
msgid "Running %s"
msgstr "Executando %s"
-#: ../nova/utils.py:470
+#: ../nova/utils.py:480
#, python-format
msgid "Link Local address is not found.:%s"
msgstr "Endereço para Link Local não encontrado: %s"
-#: ../nova/utils.py:473
+#: ../nova/utils.py:483
#, python-format
msgid "Couldn't get Link Local IP of %(interface)s :%(ex)s"
msgstr ""
"Não foi possível atribuir um IP para o Link Local de %(interface)s :%(ex)s"
-#: ../nova/utils.py:570
+#: ../nova/utils.py:580
#, python-format
msgid "Invalid backend: %s"
msgstr "Backend inválido: %s"
-#: ../nova/utils.py:581
+#: ../nova/utils.py:591
#, python-format
msgid "backend %s"
msgstr "backend %s"
@@ -748,12 +748,12 @@ msgstr "Não é possível desconectar o VBD %s"
msgid "Unable to destroy VBD %s"
msgstr "Não é possível destruir o VBD %s"
-#: ../nova/virt/xenapi/vmops.py:1460
+#: ../nova/virt/xenapi/vmops.py:1489
#, python-format
msgid "Creating VIF for VM %(vm_ref)s, network %(network_ref)s."
msgstr "Criando a VIF para VM %(vm_ref)s, rede %(network_ref)s."
-#: ../nova/virt/xenapi/vmops.py:1463
+#: ../nova/virt/xenapi/vmops.py:1492
#, python-format
msgid "Created VIF %(vif_ref)s for VM %(vm_ref)s, network %(network_ref)s."
msgstr "VIF %(vif_ref)s criada para VM %(vm_ref)s, rede %(network_ref)s."
@@ -799,12 +799,12 @@ msgstr "Visão geral da imagem %s"
#. We need to invoke a plugin for copying the
#. content of the VDI into the proper path.
-#: ../nova/virt/xenapi/vm_utils.py:668
+#: ../nova/virt/xenapi/vm_utils.py:689
#, python-format
msgid "Copying VDI %s to /boot/guest on dom0"
msgstr "Copiando o VDI %s de /boot/guest no dom0"
-#: ../nova/virt/xenapi/vm_utils.py:678
+#: ../nova/virt/xenapi/vm_utils.py:699
#, python-format
msgid "Kernel/Ramdisk VDI %s destroyed"
msgstr "Kernel/Ramdisk %s destruidos"
@@ -814,7 +814,7 @@ msgstr "Kernel/Ramdisk %s destruidos"
msgid "Asking xapi to fetch %(url)s as %(access)s"
msgstr "Requisitando à xapi a busca da url %(url)s como %(access)s"
-#: ../nova/virt/xenapi/vm_utils.py:756
+#: ../nova/virt/xenapi/vm_utils.py:770
#, python-format
msgid "Looking up vdi %s for PV kernel"
msgstr "Verificando o vdi %s para kernel PV"
@@ -824,17 +824,17 @@ msgstr "Verificando o vdi %s para kernel PV"
msgid "PV Kernel in VDI:%s"
msgstr "Kernel PV no VDI: %s"
-#: ../nova/virt/xenapi/vm_utils.py:1299
+#: ../nova/virt/xenapi/vm_utils.py:1313
#, python-format
msgid "Running pygrub against %s"
msgstr "Rodando pygrub novamente %s"
-#: ../nova/virt/xenapi/vm_utils.py:1306
+#: ../nova/virt/xenapi/vm_utils.py:1320
#, python-format
msgid "Found Xen kernel %s"
msgstr "Kernel Xen encontrado: %s"
-#: ../nova/virt/xenapi/vm_utils.py:1308
+#: ../nova/virt/xenapi/vm_utils.py:1322
msgid "No Xen kernel found. Booting HVM."
msgstr "Kernel Xen não encontrado. Iniciando como HVM."
@@ -843,38 +843,38 @@ msgstr "Kernel Xen não encontrado. Iniciando como HVM."
msgid "duplicate name found: %s"
msgstr "nome duplicado encontrado: %s"
-#: ../nova/virt/xenapi/vm_utils.py:816
+#: ../nova/virt/xenapi/vm_utils.py:830
#, python-format
msgid "VDI %s is still available"
msgstr "O VDI %s continua disponível"
-#: ../nova/virt/xenapi/vm_utils.py:862
+#: ../nova/virt/xenapi/vm_utils.py:876
#, python-format
msgid "(VM_UTILS) xenserver vm state -> |%s|"
msgstr "(VM_UTILS) xenserver vm state -> |%s|"
-#: ../nova/virt/xenapi/vm_utils.py:864
+#: ../nova/virt/xenapi/vm_utils.py:878
#, python-format
msgid "(VM_UTILS) xenapi power_state -> |%s|"
msgstr "(VM_UTILS) xenapi power_state -> |%s|"
-#: ../nova/virt/xenapi/vm_utils.py:1106
+#: ../nova/virt/xenapi/vm_utils.py:1120
#, python-format
msgid "VHD %(vdi_uuid)s has parent %(parent_ref)s"
msgstr "O VHD %(vdi_uuid)s tem pai %(parent_ref)s"
-#: ../nova/virt/xenapi/vm_utils.py:920
+#: ../nova/virt/xenapi/vm_utils.py:934
#, python-format
msgid "Re-scanning SR %s"
msgstr "Re-escaneando SR %s"
-#: ../nova/virt/xenapi/vm_utils.py:1157
+#: ../nova/virt/xenapi/vm_utils.py:1171
#, python-format
msgid ""
"VHD coalesce attempts exceeded (%(counter)d > %(max_attempts)d), giving up..."
msgstr ""
-#: ../nova/virt/xenapi/vm_utils.py:1164
+#: ../nova/virt/xenapi/vm_utils.py:1178
#, python-format
msgid ""
"Parent %(parent_uuid)s doesn't match original parent "
@@ -892,25 +892,25 @@ msgid "Unexpected number of VDIs (%(num_vdis)s) found for VM %(vm_ref)s"
msgstr ""
"Número de VDIs inesperado (%(num_vdis)s) encontrado para MV %(vm_ref)s"
-#: ../nova/virt/xenapi/vm_utils.py:1226
+#: ../nova/virt/xenapi/vm_utils.py:1240
#: ../plugins/xenserver/xenapi/etc/xapi.d/plugins/pluginlib_nova.py:188
#, python-format
msgid "Creating VBD for VDI %s ... "
msgstr "Criando VBD para VDI %s ... "
-#: ../nova/virt/xenapi/vm_utils.py:1228
+#: ../nova/virt/xenapi/vm_utils.py:1242
#: ../plugins/xenserver/xenapi/etc/xapi.d/plugins/pluginlib_nova.py:190
#, python-format
msgid "Creating VBD for VDI %s done."
msgstr "O VBD para VDI %s foi criado."
-#: ../nova/virt/xenapi/vm_utils.py:1230
+#: ../nova/virt/xenapi/vm_utils.py:1244
#: ../plugins/xenserver/xenapi/etc/xapi.d/plugins/pluginlib_nova.py:192
#, python-format
msgid "Plugging VBD %s ... "
msgstr "Conectando VBD %s ... "
-#: ../nova/virt/xenapi/vm_utils.py:1233
+#: ../nova/virt/xenapi/vm_utils.py:1247
#: ../plugins/xenserver/xenapi/etc/xapi.d/plugins/pluginlib_nova.py:194
#, python-format
msgid "Plugging VBD %s done."
@@ -926,40 +926,40 @@ msgstr "VBD %(vbd)s conectado como %(orig_dev)s"
msgid "VBD %(vbd)s plugged into wrong dev, remapping to %(dev)s"
msgstr "VBD %(vbd)s conectado no device errado, remapeando para %(dev)s"
-#: ../nova/virt/xenapi/vm_utils.py:1247
+#: ../nova/virt/xenapi/vm_utils.py:1261
#: ../plugins/xenserver/xenapi/etc/xapi.d/plugins/pluginlib_nova.py:197
#, python-format
msgid "Destroying VBD for VDI %s ... "
msgstr "Destruindo VBD para o VDI %s ... "
-#: ../nova/virt/xenapi/vm_utils.py:1251
+#: ../nova/virt/xenapi/vm_utils.py:1265
#: ../plugins/xenserver/xenapi/etc/xapi.d/plugins/pluginlib_nova.py:200
#, python-format
msgid "Destroying VBD for VDI %s done."
msgstr "O VBD para o VDI %s foi destruído."
-#: ../nova/virt/xenapi/vm_utils.py:1263
+#: ../nova/virt/xenapi/vm_utils.py:1277
#: ../plugins/xenserver/xenapi/etc/xapi.d/plugins/pluginlib_nova.py:211
msgid "VBD.unplug successful first time."
msgstr ""
-#: ../nova/virt/xenapi/vm_utils.py:1268
+#: ../nova/virt/xenapi/vm_utils.py:1282
#: ../plugins/xenserver/xenapi/etc/xapi.d/plugins/pluginlib_nova.py:216
msgid "VBD.unplug rejected: retrying..."
msgstr ""
-#: ../nova/virt/xenapi/vm_utils.py:1273
+#: ../nova/virt/xenapi/vm_utils.py:1287
#: ../plugins/xenserver/xenapi/etc/xapi.d/plugins/pluginlib_nova.py:220
msgid "VBD.unplug successful eventually."
msgstr ""
-#: ../nova/virt/xenapi/vm_utils.py:1276
+#: ../nova/virt/xenapi/vm_utils.py:1290
#: ../plugins/xenserver/xenapi/etc/xapi.d/plugins/pluginlib_nova.py:223
#, python-format
msgid "Ignoring XenAPI.Failure in VBD.unplug: %s"
msgstr "Ignorando XenAPI.Failure em VBD.unplug: %s"
-#: ../nova/virt/xenapi/vm_utils.py:1285
+#: ../nova/virt/xenapi/vm_utils.py:1299
#: ../plugins/xenserver/xenapi/etc/xapi.d/plugins/pluginlib_nova.py:66
#, python-format
msgid "Ignoring XenAPI.Failure %s"
@@ -971,7 +971,7 @@ msgid ""
"Writing partition table %(primary_first)d %(primary_last)d to %(dest)s..."
msgstr ""
-#: ../nova/virt/xenapi/vm_utils.py:1366
+#: ../nova/virt/xenapi/vm_utils.py:1380
#, python-format
msgid "Writing partition table %s done."
msgstr ""
@@ -991,7 +991,7 @@ msgstr ""
msgid "Received %s"
msgstr ""
-#: ../nova/db/sqlalchemy/api.py:52
+#: ../nova/db/sqlalchemy/api.py:56
msgid "Use of empty request context is deprecated"
msgstr ""
@@ -1131,26 +1131,26 @@ msgstr ""
msgid "No zone with id %(zone_id)s"
msgstr ""
-#: ../nova/compute/manager.py:221
+#: ../nova/compute/manager.py:223
#, python-format
msgid "Checking state of %s"
-msgstr ""
+msgstr "Verificando o estado de %s"
#: ../nova/virt/libvirt_conn.py:165
#, python-format
msgid "Current state of %(name)s was %(state)s."
msgstr ""
-#: ../nova/virt/libvirt/connection.py:228
+#: ../nova/virt/libvirt/connection.py:225
#, python-format
msgid "Connecting to libvirt: %s"
msgstr ""
-#: ../nova/virt/libvirt/connection.py:242
+#: ../nova/virt/libvirt/connection.py:239
msgid "Connection to libvirt broke"
msgstr ""
-#: ../nova/virt/libvirt/connection.py:403
+#: ../nova/virt/libvirt/connection.py:401
#, python-format
msgid "instance %(instance_name)s: deleting instance files %(target)s"
msgstr ""
@@ -1189,7 +1189,7 @@ msgstr ""
msgid "_wait_for_rescue failed: %s"
msgstr ""
-#: ../nova/virt/libvirt/connection.py:680
+#: ../nova/virt/libvirt/connection.py:678
#, python-format
msgid "instance %s: is running"
msgstr ""
@@ -1204,16 +1204,16 @@ msgstr ""
msgid "instance %s: failed to boot"
msgstr ""
-#: ../nova/virt/libvirt/connection.py:703
+#: ../nova/virt/libvirt/connection.py:701
#, python-format
msgid "virsh said: %r"
msgstr ""
-#: ../nova/virt/libvirt/connection.py:707
+#: ../nova/virt/libvirt/connection.py:705
msgid "cool, it's a device"
msgstr ""
-#: ../nova/virt/libvirt/connection.py:718
+#: ../nova/virt/libvirt/connection.py:716
#, python-format
msgid "data: %(data)r, fpath: %(fpath)r"
msgstr ""
@@ -1227,7 +1227,7 @@ msgstr ""
msgid "Unable to find an open port"
msgstr "Impossível localizar uma porta aberta"
-#: ../nova/virt/libvirt/connection.py:868
+#: ../nova/virt/libvirt/connection.py:865
#, python-format
msgid "instance %s: Creating image"
msgstr ""
@@ -1243,7 +1243,7 @@ msgid "instance %(inst_name)s: injecting net into image %(img_id)s"
msgstr ""
#. This could be a windows image, or a vmdk format disk
-#: ../nova/virt/libvirt/connection.py:1058
+#: ../nova/virt/libvirt/connection.py:1057
#, python-format
msgid ""
"instance %(inst_name)s: ignoring error injecting data into image %(img_id)s "
@@ -1265,12 +1265,12 @@ msgstr ""
msgid "diagnostics are not supported for libvirt"
msgstr ""
-#: ../nova/virt/libvirt/firewall.py:486 ../nova/virt/firewall.py:125
+#: ../nova/virt/firewall.py:125 ../nova/virt/libvirt/firewall.py:486
#, python-format
msgid "Attempted to unfilter instance %s which is not filtered"
msgstr ""
-#: ../nova/api/metadata/handler.py:251 ../nova/api/metadata/handler.py:258
+#: ../nova/api/metadata/handler.py:252 ../nova/api/metadata/handler.py:259
#, python-format
msgid "Failed to get metadata for ip: %s"
msgstr "Falha ao obter metadados para o ip: %s"
@@ -1284,11 +1284,11 @@ msgstr "Tentativa de instanciar singleton"
msgid "Quota exceeeded for %s, tried to allocate address"
msgstr ""
-#: ../nova/network/manager.py:302
+#: ../nova/network/manager.py:338
msgid "Address quota exceeded. You cannot allocate any more addresses"
msgstr ""
-#: ../nova/tests/test_volume.py:190
+#: ../nova/tests/test_volume.py:195
#, python-format
msgid "Target %s allocated"
msgstr ""
@@ -1298,15 +1298,15 @@ msgstr ""
msgid "Finished retreving %(url)s -- placed in %(path)s"
msgstr ""
-#: ../nova/scheduler/driver.py:169
+#: ../nova/scheduler/driver.py:190
msgid "Must implement a fallback schedule"
msgstr ""
-#: ../nova/console/manager.py:71 ../nova/console/vmrc_manager.py:64
+#: ../nova/console/manager.py:70 ../nova/console/vmrc_manager.py:64
msgid "Adding console"
-msgstr ""
+msgstr "Adicionando console"
-#: ../nova/console/manager.py:91
+#: ../nova/console/manager.py:90
#, python-format
msgid "Tried to remove non-existant console %(console_id)s."
msgstr ""
@@ -1320,19 +1320,17 @@ msgstr ""
msgid "The key_pair %s already exists"
msgstr ""
-#. TODO(vish): Do this with M2Crypto instead
-#: ../nova/api/ec2/cloud.py:237
-#: ../nova/api/openstack/v2/contrib/cloudpipe.py:82
+#: ../nova/crypto.py:112
#, python-format
msgid "Generating root CA: %s"
msgstr "Gerando CA raiz: %s"
-#: ../nova/api/ec2/cloud.py:395
+#: ../nova/api/ec2/cloud.py:368
#, python-format
msgid "Create key pair %s"
msgstr "Criar par de chaves %s"
-#: ../nova/api/ec2/cloud.py:437
+#: ../nova/api/ec2/cloud.py:395
#, python-format
msgid "Delete key pair %s"
msgstr "Remover par de chaves %s"
@@ -1346,103 +1344,103 @@ msgstr "%s não é um ipProtocol válido"
msgid "Invalid port range"
msgstr "Intervalo de porta inválido"
-#: ../nova/api/openstack/v2/contrib/security_groups.py:490
+#: ../nova/api/openstack/compute/contrib/security_groups.py:497
#, python-format
msgid "Revoke security group ingress %s"
msgstr "Revogado entrada do grupo de segurança %s"
-#: ../nova/api/openstack/v2/contrib/security_groups.py:352
+#: ../nova/api/openstack/compute/contrib/security_groups.py:358
msgid "Not enough parameters to build a valid rule."
msgstr ""
-#: ../nova/api/ec2/cloud.py:696 ../nova/api/ec2/cloud.py:752
+#: ../nova/api/ec2/cloud.py:654 ../nova/api/ec2/cloud.py:710
msgid "No rule for the specified parameters."
msgstr "Não existe regra para os parâmetros especificados"
-#: ../nova/api/openstack/v2/contrib/security_groups.py:337
+#: ../nova/api/openstack/compute/contrib/security_groups.py:343
#, python-format
msgid "Authorize security group ingress %s"
msgstr "Autorizada entrada do grupo de segurança %s"
-#: ../nova/api/openstack/v2/contrib/security_groups.py:359
+#: ../nova/api/openstack/compute/contrib/security_groups.py:365
#, python-format
msgid "This rule already exists in group %s"
msgstr "Esta regra já existe no grupo %s"
-#: ../nova/api/ec2/cloud.py:788
-#: ../nova/api/openstack/v2/contrib/security_groups.py:277
+#: ../nova/api/ec2/cloud.py:746
+#: ../nova/api/openstack/compute/contrib/security_groups.py:282
#, python-format
msgid "Create Security Group %s"
msgstr "Criar Grupo de Segurança %s"
-#: ../nova/api/ec2/cloud.py:791
+#: ../nova/api/ec2/cloud.py:749
#, python-format
msgid "group %s already exists"
msgstr "group %s já existe"
-#: ../nova/api/ec2/cloud.py:818
-#: ../nova/api/openstack/v2/contrib/security_groups.py:234
+#: ../nova/api/ec2/cloud.py:776
+#: ../nova/api/openstack/compute/contrib/security_groups.py:237
#, python-format
msgid "Delete security group %s"
msgstr "Excluir grupo de segurança %s"
-#: ../nova/api/openstack/v2/contrib/volumes.py:182
-#: ../nova/api/ec2/cloud.py:915
+#: ../nova/api/openstack/compute/contrib/volumes.py:186
+#: ../nova/api/openstack/volume/volumes.py:215 ../nova/api/ec2/cloud.py:865
#, python-format
msgid "Create volume of %s GB"
msgstr "Criar volume de %s GB"
-#: ../nova/api/ec2/cloud.py:950
+#: ../nova/api/ec2/cloud.py:899
#, python-format
msgid "Attach volume %(volume_id)s to instance %(instance_id)s at %(device)s"
msgstr ""
-#: ../nova/api/openstack/v2/contrib/volumes.py:347
-#: ../nova/api/ec2/cloud.py:964
+#: ../nova/api/openstack/compute/contrib/volumes.py:361
+#: ../nova/api/ec2/cloud.py:913
#, python-format
msgid "Detach volume %s"
msgstr "Desanexar volume %s"
-#: ../nova/api/ec2/cloud.py:1244
+#: ../nova/api/ec2/cloud.py:1190
msgid "Allocate address"
msgstr "Alocar endereço"
-#: ../nova/api/ec2/cloud.py:1256
+#: ../nova/api/ec2/cloud.py:1202
#, python-format
msgid "Release address %s"
msgstr "Liberar endereço %s"
-#: ../nova/api/ec2/cloud.py:1261
+#: ../nova/api/ec2/cloud.py:1207
#, python-format
msgid "Associate address %(public_ip)s to instance %(instance_id)s"
msgstr ""
-#: ../nova/api/ec2/cloud.py:1271
+#: ../nova/api/ec2/cloud.py:1217
#, python-format
msgid "Disassociate address %s"
msgstr "Desatribuir endereço %s"
-#: ../nova/api/ec2/cloud.py:1319
+#: ../nova/api/ec2/cloud.py:1265
msgid "Going to start terminating instances"
msgstr "Começando a terminar instâncias"
-#: ../nova/api/ec2/cloud.py:1328
+#: ../nova/api/ec2/cloud.py:1274
#, python-format
msgid "Reboot instance %r"
msgstr "Reiniciar instância %r"
-#: ../nova/api/ec2/cloud.py:1469
+#: ../nova/api/ec2/cloud.py:1415
#, python-format
msgid "De-registering image %s"
msgstr "Removendo o registro da imagem %s"
-#: ../nova/api/ec2/cloud.py:1496
+#: ../nova/api/ec2/cloud.py:1442
#, python-format
msgid "Registered image %(image_location)s with id %(image_id)s"
msgstr ""
-#: ../nova/api/ec2/cloud.py:991 ../nova/api/ec2/cloud.py:1048
-#: ../nova/api/ec2/cloud.py:1524 ../nova/api/ec2/cloud.py:1539
+#: ../nova/api/ec2/cloud.py:940 ../nova/api/ec2/cloud.py:997
+#: ../nova/api/ec2/cloud.py:1470 ../nova/api/ec2/cloud.py:1485
#, python-format
msgid "attribute not supported: %s"
msgstr "atributo não suportado: %s"
@@ -1452,19 +1450,19 @@ msgstr "atributo não suportado: %s"
msgid "invalid id: %s"
msgstr "id inválido: %s"
-#: ../nova/api/ec2/cloud.py:1542
+#: ../nova/api/ec2/cloud.py:1488
msgid "user or group not specified"
msgstr "usuário ou grupo não especificado"
-#: ../nova/api/ec2/cloud.py:1544
+#: ../nova/api/ec2/cloud.py:1490
msgid "only group \"all\" is supported"
msgstr "apenas o grupo \"all\" é suportado"
-#: ../nova/api/ec2/cloud.py:1546
+#: ../nova/api/ec2/cloud.py:1492
msgid "operation_type must be add or remove"
msgstr "operation_type deve ser add ou remove"
-#: ../nova/api/ec2/cloud.py:1547
+#: ../nova/api/ec2/cloud.py:1493
#, python-format
msgid "Updating image %s publicity"
msgstr "Atualizando publicidade da imagem %s"
@@ -1550,12 +1548,12 @@ msgstr ""
msgid "instance %(name)s: not enough free memory"
msgstr ""
-#: ../nova/virt/xenapi/vmops.py:441
+#: ../nova/virt/xenapi/vmops.py:449
#, python-format
msgid "Starting VM %s..."
msgstr ""
-#: ../nova/virt/xenapi/vmops.py:444
+#: ../nova/virt/xenapi/vmops.py:452
#, python-format
msgid "Spawning VM %(instance_name)s created %(vm_ref)s."
msgstr ""
@@ -1565,7 +1563,7 @@ msgstr ""
msgid "Invalid value for onset_files: '%s'"
msgstr ""
-#: ../nova/virt/xenapi/vmops.py:418
+#: ../nova/virt/xenapi/vmops.py:426
#, python-format
msgid "Injecting file path: '%s'"
msgstr ""
@@ -1582,17 +1580,17 @@ msgstr ""
#. TODO(sirp): Add quiesce and VSS locking support when Windows support
#. is added
-#: ../nova/virt/xenapi/vmops.py:614
+#: ../nova/virt/xenapi/vmops.py:622
#, python-format
msgid "Starting snapshot for VM %s"
msgstr ""
-#: ../nova/virt/xenapi/vmops.py:623
+#: ../nova/virt/xenapi/vmops.py:631
#, python-format
msgid "Unable to Snapshot %(vm_ref)s: %(exc)s"
msgstr ""
-#: ../nova/virt/xenapi/vmops.py:608
+#: ../nova/virt/xenapi/vmops.py:616
#, python-format
msgid "Finished snapshot and upload for VM %s"
msgstr ""
@@ -1606,7 +1604,7 @@ msgstr ""
msgid "Removing kernel/ramdisk files"
msgstr ""
-#: ../nova/virt/xenapi/vmops.py:1091
+#: ../nova/virt/xenapi/vmops.py:1109
msgid "kernel/ramdisk files removed"
msgstr ""
@@ -1631,17 +1629,17 @@ msgid ""
"args=%(strargs)s"
msgstr ""
-#: ../nova/virt/xenapi/vmops.py:1788
+#: ../nova/virt/xenapi/vmops.py:1817
#, python-format
msgid "OpenSSL error: %s"
-msgstr ""
+msgstr "Erro de OpenSSL: %s"
-#: ../nova/tests/test_compute.py:335 ../nova/tests/test_compute.py:1307
+#: ../nova/tests/test_compute.py:339 ../nova/tests/test_compute.py:1368
#, python-format
msgid "Running instances: %s"
msgstr ""
-#: ../nova/tests/test_compute.py:341
+#: ../nova/tests/test_compute.py:345
#, python-format
msgid "After terminating instances: %s"
msgstr ""
@@ -1672,69 +1670,69 @@ msgstr ""
msgid "Image %s could not be found"
msgstr ""
-#: ../nova/api/ec2/__init__.py:134
+#: ../nova/api/ec2/__init__.py:140
msgid "Too many failed authentications."
msgstr "Muitas falhas de autenticação."
-#: ../nova/api/ec2/__init__.py:144
+#: ../nova/api/ec2/__init__.py:150
#, python-format
msgid ""
"Access key %(access_key)s has had %(failures)d failed authentications and "
"will be locked out for %(lock_mins)d minutes."
msgstr ""
-#: ../nova/api/ec2/__init__.py:204
+#: ../nova/api/ec2/__init__.py:267
#, python-format
msgid "Authentication Failure: %s"
msgstr "Falha de Autenticação: %s"
-#: ../nova/api/ec2/__init__.py:220
+#: ../nova/api/ec2/__init__.py:283
#, python-format
msgid "Authenticated Request For %(uname)s:%(pname)s)"
msgstr ""
-#: ../nova/api/ec2/__init__.py:251
+#: ../nova/api/ec2/__init__.py:314
#, python-format
msgid "action: %s"
msgstr "ação: %s"
-#: ../nova/api/ec2/__init__.py:253
+#: ../nova/api/ec2/__init__.py:316
#, python-format
msgid "arg: %(key)s\t\tval: %(value)s"
msgstr ""
-#: ../nova/api/ec2/__init__.py:328
+#: ../nova/api/ec2/__init__.py:391
#, python-format
msgid ""
"Unauthorized request for controller=%(controller)s and action=%(action)s"
msgstr ""
-#: ../nova/api/ec2/__init__.py:359
+#: ../nova/api/ec2/__init__.py:462
#, python-format
msgid "InstanceNotFound raised: %s"
msgstr ""
-#: ../nova/api/ec2/__init__.py:365
+#: ../nova/api/ec2/__init__.py:468
#, python-format
msgid "VolumeNotFound raised: %s"
msgstr ""
-#: ../nova/api/ec2/__init__.py:377
+#: ../nova/api/ec2/__init__.py:480
#, python-format
msgid "NotFound raised: %s"
msgstr "NotFound lançado: %s"
-#: ../nova/api/ec2/__init__.py:380
+#: ../nova/api/ec2/__init__.py:483
#, python-format
msgid "ApiError raised: %s"
msgstr "ApiError lançado: %s"
-#: ../nova/api/ec2/__init__.py:409
+#: ../nova/api/ec2/__init__.py:512
#, python-format
msgid "Unexpected error raised: %s"
msgstr "Erro inexperado lançado: %s"
-#: ../nova/api/metadata/handler.py:253 ../nova/api/ec2/__init__.py:414
+#: ../nova/api/metadata/handler.py:254 ../nova/api/ec2/__init__.py:517
msgid "An unknown error has occurred. Please try your request again."
msgstr ""
"Ocorreu um erro desconhecido. Por favor tente sua requisição novamente."
@@ -1780,17 +1778,17 @@ msgid ""
"and xenapi_connection_password to use connection_type=xenapi"
msgstr ""
-#: ../nova/virt/xenapi_conn.py:560
+#: ../nova/virt/xenapi_conn.py:569
#, python-format
msgid "Task [%(name)s] %(task)s status: success %(result)s"
msgstr ""
-#: ../nova/virt/xenapi_conn.py:569
+#: ../nova/virt/xenapi_conn.py:578
#, python-format
msgid "Task [%(name)s] %(task)s status: %(status)s %(error_info)s"
msgstr ""
-#: ../nova/virt/xenapi_conn.py:595 ../nova/virt/xenapi_conn.py:608
+#: ../nova/virt/xenapi_conn.py:604 ../nova/virt/xenapi_conn.py:617
#, python-format
msgid "Got exception: %s"
msgstr ""
@@ -1806,7 +1804,7 @@ msgid ""
"Unsupported API request: controller = %(controller)s, action = %(action)s"
msgstr ""
-#: ../nova/api/openstack/v2/__init__.py:61
+#: ../nova/api/openstack/__init__.py:43
#, python-format
msgid "Caught error: %s"
msgstr "Capturado o erro: %s"
@@ -1815,33 +1813,33 @@ msgstr "Capturado o erro: %s"
msgid "Including admin operations in API."
msgstr "Incluindo operações administrativas na API."
-#: ../nova/console/xvp.py:93
+#: ../nova/console/xvp.py:92
msgid "Rebuilding xvp conf"
msgstr ""
-#: ../nova/console/xvp.py:111
+#: ../nova/console/xvp.py:110
#, python-format
msgid "Re-wrote %s"
msgstr ""
-#: ../nova/console/xvp.py:116
+#: ../nova/console/xvp.py:115
msgid "Stopping xvp"
msgstr ""
-#: ../nova/console/xvp.py:129
+#: ../nova/console/xvp.py:128
msgid "Starting xvp"
msgstr ""
-#: ../nova/console/xvp.py:136
+#: ../nova/console/xvp.py:135
#, python-format
msgid "Error starting xvp: %s"
msgstr ""
-#: ../nova/console/xvp.py:139
+#: ../nova/console/xvp.py:138
msgid "Restarting xvp"
msgstr ""
-#: ../nova/console/xvp.py:141
+#: ../nova/console/xvp.py:140
msgid "xvp not running..."
msgstr ""
@@ -1867,11 +1865,11 @@ msgid ""
"Please create a database by running a nova-api server on this host."
msgstr ""
-#: ../bin/nova-manage.py:640
+#: ../bin/nova-manage.py:645
msgid "network"
msgstr ""
-#: ../bin/nova-manage.py:641
+#: ../bin/nova-manage.py:646
msgid "IP address"
msgstr ""
@@ -1879,12 +1877,12 @@ msgstr ""
msgid "MAC address"
msgstr ""
-#: ../bin/nova-manage.py:643
+#: ../bin/nova-manage.py:647
msgid "hostname"
msgstr ""
-#: ../bin/nova-manage.py:644 ../bin/nova-manage.py:1181
-#: ../bin/nova-manage.py:1297 ../bin/nova-manage.py:1329
+#: ../bin/nova-manage.py:648 ../bin/nova-manage.py:1166
+#: ../bin/nova-manage.py:1282 ../bin/nova-manage.py:1314
msgid "host"
msgstr ""
@@ -1892,7 +1890,7 @@ msgstr ""
msgid "netmask"
msgstr ""
-#: ../bin/nova-manage.py:852 ../nova/tests/test_nova_manage.py:183
+#: ../bin/nova-manage.py:857 ../nova/tests/test_nova_manage.py:181
msgid "start address"
msgstr ""
@@ -1901,7 +1899,7 @@ msgstr ""
msgid "Failed to load partition: %s"
msgstr ""
-#: ../nova/virt/disk/api.py:222 ../nova/virt/disk/guestfs.py:64
+#: ../nova/virt/disk/api.py:223 ../nova/virt/disk/guestfs.py:64
#: ../nova/virt/disk/guestfs.py:78 ../nova/virt/disk/mount.py:112
#, python-format
msgid "Failed to mount filesystem: %s"
@@ -1922,7 +1920,7 @@ msgstr ""
msgid "No free nbd devices"
msgstr ""
-#: ../doc/ext/nova_todo.py:46
+#: ../doc/ext/nova_todo.py:45
#, python-format
msgid "%(filename)s, line %(line_info)d"
msgstr ""
@@ -2078,17 +2076,17 @@ msgstr ""
msgid "Quota exceeeded for %(pid)s, tried to run %(min_count)s instances"
msgstr ""
-#: ../nova/compute/api.py:219
+#: ../nova/compute/api.py:215
#, python-format
msgid ""
"Instance quota exceeded. You can only run %s more instances of this type."
msgstr ""
-#: ../nova/compute/api.py:268
+#: ../nova/compute/api.py:264
msgid "Creating a raw instance"
msgstr ""
-#: ../nova/compute/api.py:323
+#: ../nova/compute/api.py:336
#, python-format
msgid "Going to run %s instances..."
msgstr ""
@@ -2098,7 +2096,7 @@ msgstr ""
msgid "Casting to scheduler for %(pid)s/%(uid)s's instance %(instance_id)s"
msgstr ""
-#: ../nova/compute/api.py:852
+#: ../nova/compute/api.py:872
#, python-format
msgid "Going to try to terminate %s"
msgstr ""
@@ -2113,7 +2111,7 @@ msgstr ""
msgid "Instance %d is already being terminated"
msgstr ""
-#: ../nova/compute/api.py:1644
+#: ../nova/compute/api.py:1643
#, python-format
msgid "Invalid device specified: %s. Example device: /dev/vdb"
msgstr ""
@@ -2135,7 +2133,7 @@ msgid "Unable to connect to AMQP server after %d tries. Shutting down."
msgstr ""
"Não foi possível conectar ao servidor AMQP após %d tentativas. Desligando."
-#: ../nova/rpc/impl_carrot.py:221
+#: ../nova/rpc/impl_carrot.py:222
msgid "Reconnected to queue"
msgstr "Reconectado à fila"
@@ -2143,12 +2141,12 @@ msgstr "Reconectado à fila"
msgid "Failed to fetch message from queue"
msgstr "Falha ao obter mensagem da fila"
-#: ../nova/rpc/impl_carrot.py:236
+#: ../nova/rpc/impl_carrot.py:237
#, python-format
msgid "Initing the Adapter Consumer for %s"
msgstr "Iniciando o Adaptador Consumidor para %s"
-#: ../nova/rpc/impl_kombu.py:629 ../nova/rpc/impl_carrot.py:256
+#: ../nova/rpc/amqp.py:224 ../nova/rpc/impl_carrot.py:261
#, python-format
msgid "received %s"
msgstr "recebido %s"
@@ -2157,22 +2155,22 @@ msgstr "recebido %s"
#. messages stay in the queue indefinitely, so for now
#. we just log the message and send an error string
#. back to the caller
-#: ../nova/rpc/impl_kombu.py:634 ../nova/rpc/impl_carrot.py:269
+#: ../nova/rpc/amqp.py:229 ../nova/rpc/impl_carrot.py:274
#, python-format
msgid "no method for message: %s"
msgstr "sem método para mensagem: %s"
-#: ../nova/rpc/impl_kombu.py:635 ../nova/rpc/impl_carrot.py:271
+#: ../nova/rpc/amqp.py:230 ../nova/rpc/impl_carrot.py:276
#, python-format
msgid "No method for message: %s"
msgstr "Sem método para mensagem: %s"
-#: ../nova/rpc/impl_kombu.py:816 ../nova/rpc/impl_carrot.py:455
+#: ../nova/rpc/amqp.py:141 ../nova/rpc/impl_carrot.py:460
#, python-format
msgid "Returning exception %s to caller"
msgstr "Retornando exceção %s ao método de origem"
-#: ../nova/rpc/impl_kombu.py:675 ../nova/rpc/impl_carrot.py:488
+#: ../nova/rpc/amqp.py:182 ../nova/rpc/impl_carrot.py:494
#, python-format
msgid "unpacked context: %s"
msgstr "conteúdo descompactado: %s"
@@ -2181,7 +2179,7 @@ msgstr "conteúdo descompactado: %s"
msgid "Making asynchronous call..."
msgstr "Fazendo chamada assíncrona..."
-#: ../nova/rpc/impl_kombu.py:762 ../nova/rpc/impl_carrot.py:524
+#: ../nova/rpc/amqp.py:314 ../nova/rpc/impl_carrot.py:530
#, python-format
msgid "MSG_ID is %s"
msgstr "MSG_ID é %s"
@@ -2190,17 +2188,17 @@ msgstr "MSG_ID é %s"
msgid "Making asynchronous cast..."
msgstr ""
-#: ../nova/rpc/impl_carrot.py:634
+#: ../nova/rpc/impl_carrot.py:640
#, python-format
msgid "response %s"
msgstr "resposta %s"
-#: ../nova/rpc/impl_carrot.py:643
+#: ../nova/rpc/impl_carrot.py:649
#, python-format
msgid "topic is %s"
msgstr "topico é %s"
-#: ../nova/rpc/impl_carrot.py:644
+#: ../nova/rpc/impl_carrot.py:650
#, python-format
msgid "message %s"
msgstr "mensagem %s"
@@ -2253,7 +2251,7 @@ msgstr ""
msgid "Starting %(arg0)s on %(host)s:%(port)s"
msgstr ""
-#: ../nova/wsgi.py:204
+#: ../nova/wsgi.py:207
msgid "You must implement __call__"
msgstr ""
@@ -2286,7 +2284,7 @@ msgstr ""
msgid "Dissassociated %s stale fixed ip(s)"
msgstr ""
-#: ../nova/network/manager.py:564
+#: ../nova/network/manager.py:705
msgid "setting network host"
msgstr ""
@@ -2325,12 +2323,12 @@ msgstr ""
msgid "IP %(address)s released from bad mac %(inst_addr)s vs %(mac)s"
msgstr ""
-#: ../nova/network/manager.py:1063
+#: ../nova/network/manager.py:1243
#, python-format
msgid "IP %s released that was not leased"
msgstr ""
-#: ../nova/network/manager.py:1490
+#: ../nova/network/manager.py:1692
msgid ""
"The sum between the number of networks and the vlan start cannot be greater "
"than 4094"
@@ -2339,7 +2337,7 @@ msgstr ""
#: ../nova/virt/xenapi/volume_utils.py:157
#, python-format
msgid "Introducing %s..."
-msgstr ""
+msgstr "Introduzindo %s..."
#: ../nova/virt/xenapi/volume_utils.py:103
#: ../nova/virt/xenapi/volume_utils.py:170
@@ -2406,19 +2404,19 @@ msgstr ""
#: ../nova/virt/xenapi/volume_utils.py:356
#, python-format
msgid "Mountpoint cannot be translated: %s"
-msgstr ""
+msgstr "Ponto de montagem não pode ser traduzido: %s"
-#: ../nova/image/s3.py:365
+#: ../nova/image/s3.py:361
#, python-format
msgid "Failed to decrypt private key: %s"
msgstr ""
-#: ../nova/image/s3.py:374
+#: ../nova/image/s3.py:369
#, python-format
msgid "Failed to decrypt initialization vector: %s"
msgstr ""
-#: ../nova/image/s3.py:385
+#: ../nova/image/s3.py:380
#, python-format
msgid "Failed to decrypt image file %(image_file)s: %(err)s"
msgstr ""
@@ -2532,12 +2530,12 @@ msgstr ""
msgid "Deleted image: %s"
msgstr ""
-#: ../nova/auth/manager.py:277
+#: ../nova/auth/manager.py:280
#, python-format
msgid "Looking up user: %r"
msgstr "Procurando usuário: %r"
-#: ../nova/auth/manager.py:281
+#: ../nova/auth/manager.py:284
#, python-format
msgid "Failed authorization for access key %s"
msgstr "Falha de autorização para chave de acesso %s"
@@ -2547,12 +2545,12 @@ msgstr "Falha de autorização para chave de acesso %s"
msgid "No user found for access key %s"
msgstr "Nenhum usuário encontrado para chave de acesso %s"
-#: ../nova/auth/manager.py:287
+#: ../nova/auth/manager.py:290
#, python-format
msgid "Using project name = user name (%s)"
msgstr "Usando nome do projeto = nome do usuário (%s)"
-#: ../nova/auth/manager.py:294
+#: ../nova/auth/manager.py:297
#, python-format
msgid "failed authorization: no project named %(pjid)s (user=%(uname)s)"
msgstr ""
@@ -2562,7 +2560,7 @@ msgstr ""
msgid "No project called %s could be found"
msgstr "Nenhum projeto chamado %s pode ser encontrado."
-#: ../nova/auth/manager.py:303
+#: ../nova/auth/manager.py:306
#, python-format
msgid ""
"Failed authorization: user %(uname)s not admin and not member of project "
@@ -2574,7 +2572,7 @@ msgstr ""
msgid "User %(uid)s is not a member of project %(pjid)s"
msgstr ""
-#: ../nova/auth/manager.py:314 ../nova/auth/manager.py:336
+#: ../nova/auth/manager.py:317 ../nova/auth/manager.py:339
#, python-format
msgid "Invalid signature for user %s"
msgstr "Assinatura inválida para usuário %s"
@@ -2583,7 +2581,7 @@ msgstr "Assinatura inválida para usuário %s"
msgid "Signature does not match"
msgstr "Assinatura não confere"
-#: ../nova/auth/manager.py:428
+#: ../nova/auth/manager.py:431
msgid "Must specify project"
msgstr "Deve especificar projeto"
@@ -2597,99 +2595,99 @@ msgstr "O papel %s não foi encontrado"
msgid "The %s role is global only"
msgstr "O papel %s é apenas global"
-#: ../nova/auth/manager.py:469
+#: ../nova/auth/manager.py:472
#, python-format
msgid "Adding role %(role)s to user %(uid)s in project %(pid)s"
msgstr ""
-#: ../nova/auth/manager.py:472
+#: ../nova/auth/manager.py:475
#, python-format
msgid "Adding sitewide role %(role)s to user %(uid)s"
msgstr ""
-#: ../nova/auth/manager.py:498
+#: ../nova/auth/manager.py:501
#, python-format
msgid "Removing role %(role)s from user %(uid)s on project %(pid)s"
msgstr ""
-#: ../nova/auth/manager.py:501
+#: ../nova/auth/manager.py:504
#, python-format
msgid "Removing sitewide role %(role)s from user %(uid)s"
msgstr ""
-#: ../nova/auth/manager.py:574
+#: ../nova/auth/manager.py:577
#, python-format
msgid "Created project %(name)s with manager %(manager_user)s"
msgstr ""
-#: ../nova/auth/manager.py:592
+#: ../nova/auth/manager.py:595
#, python-format
msgid "modifying project %s"
msgstr "modificando projeto %s"
-#: ../nova/auth/manager.py:604
+#: ../nova/auth/manager.py:607
#, python-format
msgid "Adding user %(uid)s to project %(pid)s"
-msgstr ""
+msgstr "Adicionando usuário %(uid)s ao projeto %(pid)s"
-#: ../nova/auth/manager.py:625
+#: ../nova/auth/manager.py:628
#, python-format
msgid "Remove user %(uid)s from project %(pid)s"
-msgstr ""
+msgstr "Remover usuário %(uid)s do projeto %(pid)s"
-#: ../nova/auth/manager.py:655
+#: ../nova/auth/manager.py:658
#, python-format
msgid "Deleting project %s"
msgstr "Excluindo projeto %s"
-#: ../nova/auth/manager.py:713
+#: ../nova/auth/manager.py:716
#, python-format
msgid "Created user %(rvname)s (admin: %(rvadmin)r)"
msgstr ""
-#: ../nova/auth/manager.py:722
+#: ../nova/auth/manager.py:725
#, python-format
msgid "Deleting user %s"
msgstr "Apagando usuário %s"
-#: ../nova/auth/manager.py:732
+#: ../nova/auth/manager.py:735
#, python-format
msgid "Access Key change for user %s"
msgstr ""
-#: ../nova/auth/manager.py:734
+#: ../nova/auth/manager.py:737
#, python-format
msgid "Secret Key change for user %s"
msgstr ""
-#: ../nova/auth/manager.py:736
+#: ../nova/auth/manager.py:739
#, python-format
msgid "Admin status set to %(admin)r for user %(uid)s"
msgstr ""
-#: ../nova/auth/manager.py:781
+#: ../nova/auth/manager.py:784
#, python-format
msgid "No vpn data for project %s"
msgstr ""
-#: ../nova/service.py:141
+#: ../nova/service.py:146
#, python-format
msgid "Starting %(topic)s node (version %(vcs_string)s)"
msgstr ""
-#: ../nova/service.py:232
+#: ../nova/service.py:237
msgid "Service killed that has no database entry"
msgstr "Encerrado serviço que não tem entrada na base de dados"
-#: ../nova/service.py:269
+#: ../nova/service.py:274
msgid "The service database object disappeared, Recreating it."
msgstr "O objeto da base de dados do serviço desapareceu, Recriando."
-#: ../nova/service.py:284
+#: ../nova/service.py:289
msgid "Recovered model server connection!"
msgstr "Recuperada conexão servidor de modelo."
-#: ../nova/service.py:290
+#: ../nova/service.py:295
msgid "model server went away"
msgstr "servidor de modelo perdido"
@@ -2735,7 +2733,7 @@ msgstr ""
msgid "The group at dn %s doesn't exist"
msgstr "O grupo no dn %s não existe"
-#: ../nova/exception.py:801
+#: ../nova/exception.py:817
#, python-format
msgid "User %(uid)s is already a member of the group %(group_dn)s"
msgstr "Usuário %(uid)s já é um membro do grupo %(group_dn)s"