nova-2014.1.1 added

This commit is contained in:
Kolan Sh 2014-06-20 13:08:47 +04:00
parent 08a4cd6547
commit 5f1a154968
29 changed files with 2 additions and 3132 deletions

View File

@ -1 +0,0 @@
DIST quantum-2013.1.3.tar.gz 1174471 SHA256 79e60ec1aef800da3a4e1841909cdd8b2cf645979d08f27bc481957c7944e93d SHA512 cba87ff6b6695bc6d09b60bea86e9fb42fcc9d5358dd3c06d1a6880f9654d9155d881485b49cec05aaae9428fdafa7d2d4061b15b9c02a69de49475b0cc064b8 WHIRLPOOL deaf4a9ae8df78580a7418d65a00850c57f34cedbe40e38f4832849d2e8ae8f4eadb06d37be039c1c2a16e8893f891763888d72e3e174dac96df56e733ad8bb7

View File

@ -1,2 +0,0 @@
#Don't touch this unless you know what you are doing
PID_PATH=/run/quantum

View File

@ -1,60 +0,0 @@
#!/sbin/runscript
# Copyright 1999-2013 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
depend() {
need net
}
BASENAME=$(echo $SVCNAME | cut -d '-' -f 1)
SERVERNAME=$(echo $SVCNAME | cut -d '-' -f 2)
checkconfig() {
if [ ! -r /etc/conf.d/$BASENAME ]; then
eerror "No quantum conf.d file found: /etc/conf.d/$BASENAME)"
return 1
fi
return 0
}
start() {
checkconfig || return $?
. /etc/conf.d/$BASENAME
ebegin "Starting ${SVCNAME}"
if [ ! -d ${PID_PATH} ]; then
mkdir ${PID_PATH}
fi
start-stop-daemon --start \
--user quantum:quantum \
--quiet \
--pidfile "${PID_PATH}/${SVCNAME}.pid" \
--make-pidfile \
--background \
--exec /usr/bin/${SVCNAME} -- \
--config-file /etc/quantum/quantum.conf \
--config-file /etc/quantum/plugins/openvswitch/ovs_quantum_plugin.ini \
--log-file /var/log/quantum/server.log
eend $? "Failed to start ${SVCNAME}"
}
stop() {
checkconfig || return $?
. /etc/conf.d/$BASENAME
ebegin "Stopping ${SVCNAME}"
start-stop-daemon --stop --user quantum --quiet --pidfile "${PID_PATH}/${SVCNAME}.pid" \
--exec /usr/bin/${SVCNAME} -- \
--config-file /etc/quantum/quantum.conf \
--config-file /etc/quantum/plugins/openvswitch/ovs_quantum_plugin.ini \
--log-file /var/log/quantum/server.log
eend $? "Failed to stop ${SVCNAME}"
}
#restart() {
#
#}

View File

@ -1,4 +0,0 @@
Defaults:neutron !requiretty
neutron ALL = (root) NOPASSWD: /usr/bin/quantum-rootwrap

View File

@ -1,108 +0,0 @@
# Copyright 1999-2013 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Header: /var/cvsroot/gentoo-x86/sys-cluster/neutron/neutron-2013.1.3-r1.ebuild,v 1.1 2013/09/05 21:46:49 prometheanfire Exp $
EAPI=5
PYTHON_COMPAT=( python2_7 )
inherit distutils-r1
#restricted due to packages missing and bad depends in the test ==webob-1.0.8
RESTRICT="test"
DESCRIPTION="Quantum is a virtual network service for Openstack."
HOMEPAGE="https://launchpad.net/neutron"
SRC_URI="http://launchpad.net/${PN}/grizzly/${PV}/+download/quantum-${PV}.tar.gz"
S="${WORKDIR}/quantum-${PV}"
LICENSE="Apache-2.0"
SLOT="0"
KEYWORDS="~amd64 ~x86"
IUSE="+dhcp +l3 +metadata +openvswitch +server test"
#the cliff dep is as below because it depends on pyparsing, which only has 2.7 OR 3.2, not both
DEPEND="dev-python/setuptools[${PYTHON_USEDEP}]
app-admin/sudo
test? ( dev-python/cliff[python_targets_python2_7]
dev-python/configobj[${PYTHON_USEDEP}] )
dev-python/coverage[${PYTHON_USEDEP}]
>=dev-python/mock-1.0[${PYTHON_USEDEP}]
~dev-python/mox-0.5.3[${PYTHON_USEDEP}]
dev-python/nose[${PYTHON_USEDEP}]
dev-python/nosehtmloutput[${PYTHON_USEDEP}]
dev-python/nosexcover
dev-python/openstack-nose-plugin[${PYTHON_USEDEP}]
~dev-python/pep8-1.3.3
>=dev-python/sphinx-1.1.2[${PYTHON_USEDEP}]
~dev-python/webtest-1.3.3
virtual/python-unittest2[${PYTHON_USEDEP}]"
RDEPEND=">=dev-python/pastedeploy-1.5.0-r1[${PYTHON_USEDEP}]
>=dev-python/alembic-0.4.1[${PYTHON_USEDEP}]
dev-python/paste[${PYTHON_USEDEP}]
>=dev-python/routes-1.12.3[${PYTHON_USEDEP}]
>=dev-python/amqplib-0.6.1-r1[${PYTHON_USEDEP}]
>=dev-python/anyjson-0.2.4[${PYTHON_USEDEP}]
>=dev-python/eventlet-0.9.17[${PYTHON_USEDEP}]
>=dev-python/greenlet-0.3.1[${PYTHON_USEDEP}]
dev-python/httplib2[${PYTHON_USEDEP}]
>=dev-python/iso8601-0.1.4[${PYTHON_USEDEP}]
>=dev-python/kombu-1.0.4-r1[${PYTHON_USEDEP}]
dev-python/netaddr[${PYTHON_USEDEP}]
>=dev-python/pyparsing-1.5.7[${PYTHON_USEDEP}]
>=dev-python/python-keystoneclient-0.2.0[${PYTHON_USEDEP}]
dev-python/python-novaclient[${PYTHON_USEDEP}]
>=dev-python/python-quantumclient-2.2.0[${PYTHON_USEDEP}]
<=dev-python/python-quantumclient-3.0.0[${PYTHON_USEDEP}]
dev-python/pyudev[${PYTHON_USEDEP}]
>dev-python/sqlalchemy-0.7.8
<=dev-python/sqlalchemy-0.7.99
>=dev-python/webob-1.2[${PYTHON_USEDEP}]
>=dev-python/oslo-config-1.1.0[${PYTHON_USEDEP}]
virtual/python-argparse[${PYTHON_USEDEP}]
net-misc/openvswitch
dhcp? ( net-dns/dnsmasq )"
pkg_setup() {
enewgroup neutron
enewuser neutron -1 -1 /var/lib/neutron neutron
}
python_install() {
distutils-r1_python_install
newconfd "${FILESDIR}/neutron-confd" "quantum"
newinitd "${FILESDIR}/neutron-initd" "quantum"
use server && dosym /etc/init.d/quantum /etc/init.d/quantum-server
use dhcp && dosym /etc/init.d/quantum /etc/init.d/quantum-dhcp-agent
use l3 && dosym /etc/init.d/quantum /etc/init.d/quantum-l3-agent
use metadata && dosym /etc/init.d/quantum /etc/init.d/quantum-metadata-agent
use openvswitch && dosym /etc/init.d/quantum /etc/init.d/quantum-openvswitch-agent
dodir /var/log/neutron
fowners neutron:neutron /var/log/neutron
keepdir /etc/quantum
insinto /etc/quantum
doins "etc/api-paste.ini"
doins "etc/dhcp_agent.ini"
doins "etc/l3_agent.ini"
doins "etc/policy.json"
doins "etc/quantum.conf"
doins "etc/rootwrap.conf"
insinto /etc
doins -r "etc/quantum/"
#remove the etc stuff from usr...
rm -R "${D}/usr/etc/"
insinto "/usr/lib64/python2.7/site-packages/quantum/db/migration/alembic_migrations/"
doins -r "quantum/db/migration/alembic_migrations/versions"
#add sudoers definitions for user neutron
insinto /etc/sudoers.d/
doins "${FILESDIR}/neutron-sudoers"
}
pkg_config() {
fperms 0700 /var/log/neutron
fowners neutron:neutron /var/log neutron
}

View File

@ -1,3 +1 @@
DIST nova-2013.1.3.tar.gz 5780115 SHA256 f7c25186920daccb16867c5fd272318beb8cc076e5a55f79b5906618ef2724f4 SHA512 3de29f1cf0789285c7600796588058f056d4196138584bb5ec13a0ea034bbc0569d116a668db67022e302b29995af5960093af1103996269d73dccd62a5dd238 WHIRLPOOL ebb06733a710764004f99da2a69d5479cdd50e35da6d0992233ab9ca0a7a5854a678c5d184d40f97a66fa3abd052b1e6de4629963dd58292f677707997e56239
DIST nova-2013.2.tar.gz 8909222 SHA256 55a51f8d8b6c7b0ba6f8ff9c48604bb82a90bdc3f21460ed325d1cee2dfea95a SHA512 655d6f5a4ab9ddfb741a920417061808bf22521c967d324f0fa1856c801795969df6f4982362bce26836975c09e7f41e25575309cde5c6788ed32e69304381ea WHIRLPOOL d88272c8101426ed4930a924b254d045a5c965f867573039b72b51f7aa5ba2daa47f54332f63e09e781dd22ca55c142acdb432dc92ad366e13b56138ff8f3186
DIST nova-2014.1.tar.gz 7951303 SHA256 c8fc0e03a826b2b659c77e24737b267588f2c71e3bea9527c71e55a2c76a54d9 SHA512 0893d1ebbf91798cc737e8df97dd2d44fffe4a6163c99f5e63d0f3f6a9ba1c3d1c9ef38e217b74e8da62dd8d5cd91f3be32da2ec062c642d192e32fd96cdf650 WHIRLPOOL c5fcc88912e5eb21aaa9908759324dd37c3670e37edca8562ba1301431fdf8cc40699152fe3ee3a48a495922f4b11846a804ee990d13d3d037726aa520cc0af0
DIST nova-2014.1.1.tar.gz 7979809 SHA256 3cb3b48c72c39e7637d6016039d353ad33de69bcd6ed04dbfdb0db9313eb9a5b SHA512 6f7b449e09e796c483d93399af24c2cd77042776e1c4d36c3bcd34814b42a252151542b684785ba6c1b28bc0b302cc15f5057da7f90884c73ff6b11ec748323e WHIRLPOOL 0d959b4655d6010825b0ef73b6ce983cd6a0679f5aa5d41ebfbddce26e74d402d9d571c65d26f71e60bb627fc9d4d924d1e4622c1d96d73e3b484f1c68502df7

View File

@ -1,327 +0,0 @@
From f7aaf1fa04331522aee2158e372940df92f45cb0 Mon Sep 17 00:00:00 2001
From: Russell Bryant <rbryant@redhat.com>
Date: Thu, 27 Jun 2013 21:00:05 +0000
Subject: [PATCH] Make flavors is_public option actually work
When you create a flavor, you can set an is_public flag to be True or
False. It is True by default. When False, the intention is that the
flavor is only accessible by an admin, unless you use the flavor_access
API extension to grant access to specific tenants.
Unfortunately, the only place in the code where this was being enforced
was when listing flavors through the API. It would filter out the
non-public ones for a non-admin. Otherwise, the flavor was accessible.
You could get the details, and you could boot an instance with it, if
you figured out a valid flavor ID.
This patch adds enforcement down in the db layer. It also fixes one
place in the API where the context wasn't passed down to enable the
enforcement to happen.
Fix bug 1194093.
master -> grizzly
(cherry picked from commit b65d506a5f9d9b2b20777a9aceb44a8ffed6a5de)
Conflicts:
nova/api/openstack/compute/contrib/flavor_access.py
nova/api/openstack/compute/contrib/flavormanage.py
nova/api/openstack/compute/flavors.py
nova/compute/api.py
nova/db/sqlalchemy/api.py
nova/tests/api/openstack/compute/contrib/test_flavor_access.py
nova/tests/api/openstack/compute/contrib/test_flavor_disabled.py
nova/tests/api/openstack/compute/contrib/test_flavor_manage.py
nova/tests/api/openstack/compute/contrib/test_flavor_rxtx.py
nova/tests/api/openstack/compute/contrib/test_flavor_swap.py
nova/tests/api/openstack/compute/contrib/test_flavorextradata.py
nova/tests/api/openstack/compute/test_flavors.py
nova/tests/db/test_db_api.py
grizzly -> folsom
(cherry picked from commit 6df1b7a2a1413a98bffc8b8e0b947f3c90e3bbf5)
Conflicts:
nova/db/sqlalchemy/api.py
nova/tests/api/openstack/compute/test_flavors.py
Change-Id: I5b37fa0bb19683fe1642fd81222547d4a317054e
---
.../api/openstack/compute/contrib/flavor_access.py | 3 ++-
nova/api/openstack/compute/contrib/flavormanage.py | 2 +-
nova/api/openstack/compute/flavors.py | 4 +++-
nova/compute/api.py | 2 +-
nova/compute/instance_types.py | 2 +-
nova/db/api.py | 4 ++--
nova/db/sqlalchemy/api.py | 26 +++++++++++++++-------
.../compute/contrib/test_flavor_access.py | 2 +-
.../compute/contrib/test_flavor_disabled.py | 2 +-
.../compute/contrib/test_flavor_manage.py | 3 ++-
.../openstack/compute/contrib/test_flavor_rxtx.py | 2 +-
.../openstack/compute/contrib/test_flavor_swap.py | 2 +-
.../compute/contrib/test_flavorextradata.py | 2 +-
nova/tests/api/openstack/compute/test_flavors.py | 4 ++--
14 files changed, 37 insertions(+), 23 deletions(-)
diff --git a/nova/api/openstack/compute/contrib/flavor_access.py b/nova/api/openstack/compute/contrib/flavor_access.py
index 9991408..26cd77f 100644
--- a/nova/api/openstack/compute/contrib/flavor_access.py
+++ b/nova/api/openstack/compute/contrib/flavor_access.py
@@ -99,7 +99,8 @@ class FlavorAccessController(object):
authorize(context)
try:
- flavor = instance_types.get_instance_type_by_flavor_id(flavor_id)
+ flavor = instance_types.get_instance_type_by_flavor_id(flavor_id,
+ ctxt=context)
except exception.FlavorNotFound:
explanation = _("Flavor not found.")
raise webob.exc.HTTPNotFound(explanation=explanation)
diff --git a/nova/api/openstack/compute/contrib/flavormanage.py b/nova/api/openstack/compute/contrib/flavormanage.py
index e7731cc..79551b1 100644
--- a/nova/api/openstack/compute/contrib/flavormanage.py
+++ b/nova/api/openstack/compute/contrib/flavormanage.py
@@ -43,7 +43,7 @@ class FlavorManageController(wsgi.Controller):
try:
flavor = instance_types.get_instance_type_by_flavor_id(
- id, read_deleted="no")
+ id, ctxt=context, read_deleted="no")
except exception.NotFound, e:
raise webob.exc.HTTPNotFound(explanation=e.format_message())
diff --git a/nova/api/openstack/compute/flavors.py b/nova/api/openstack/compute/flavors.py
index 8aa57a2..d51b48a 100644
--- a/nova/api/openstack/compute/flavors.py
+++ b/nova/api/openstack/compute/flavors.py
@@ -84,7 +84,9 @@ class Controller(wsgi.Controller):
def show(self, req, id):
"""Return data about the given flavor id."""
try:
- flavor = instance_types.get_instance_type_by_flavor_id(id)
+ context = req.environ['nova.context']
+ flavor = instance_types.get_instance_type_by_flavor_id(id,
+ ctxt=context)
req.cache_db_flavor(flavor)
except exception.NotFound:
raise webob.exc.HTTPNotFound()
diff --git a/nova/compute/api.py b/nova/compute/api.py
index 5319d04..ca78830 100644
--- a/nova/compute/api.py
+++ b/nova/compute/api.py
@@ -1080,7 +1080,7 @@ class API(base.Base):
#NOTE(bcwaldon): this doesn't really belong in this class
def get_instance_type(self, context, instance_type_id):
"""Get an instance type by instance type id."""
- return instance_types.get_instance_type(instance_type_id)
+ return instance_types.get_instance_type(instance_type_id, ctxt=context)
def get(self, context, instance_id):
"""Get a single instance with the given instance_id."""
diff --git a/nova/compute/instance_types.py b/nova/compute/instance_types.py
index 6869672..5be97c1 100644
--- a/nova/compute/instance_types.py
+++ b/nova/compute/instance_types.py
@@ -163,7 +163,7 @@ def get_instance_type_by_flavor_id(flavorid, ctxt=None, read_deleted="yes"):
if ctxt is None:
ctxt = context.get_admin_context(read_deleted=read_deleted)
- return db.instance_type_get_by_flavor_id(ctxt, flavorid)
+ return db.instance_type_get_by_flavor_id(ctxt, flavorid, read_deleted)
def get_instance_type_access_by_flavor_id(flavorid, ctxt=None):
diff --git a/nova/db/api.py b/nova/db/api.py
index 9f2ff73..40db686 100644
--- a/nova/db/api.py
+++ b/nova/db/api.py
@@ -1460,9 +1460,9 @@ def instance_type_get_by_name(context, name):
return IMPL.instance_type_get_by_name(context, name)
-def instance_type_get_by_flavor_id(context, id):
+def instance_type_get_by_flavor_id(context, id, read_deleted=None):
"""Get instance type by flavor id."""
- return IMPL.instance_type_get_by_flavor_id(context, id)
+ return IMPL.instance_type_get_by_flavor_id(context, id, read_deleted)
def instance_type_destroy(context, name):
diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py
index 7fcc4f8..ea32168 100644
--- a/nova/db/sqlalchemy/api.py
+++ b/nova/db/sqlalchemy/api.py
@@ -3910,7 +3910,7 @@ def instance_type_create(context, values):
pass
try:
instance_type_get_by_flavor_id(context, values['flavorid'],
- session)
+ read_deleted='no', session=session)
raise exception.InstanceTypeExists(name=values['name'])
except exception.FlavorNotFound:
pass
@@ -3952,9 +3952,16 @@ def _dict_with_extra_specs(inst_type_query):
def _instance_type_get_query(context, session=None, read_deleted=None):
- return model_query(context, models.InstanceTypes, session=session,
+ query = model_query(context, models.InstanceTypes, session=session,
read_deleted=read_deleted).\
- options(joinedload('extra_specs'))
+ options(joinedload('extra_specs'))
+ if not context.is_admin:
+ the_filter = [models.InstanceTypes.is_public == True]
+ the_filter.extend([
+ models.InstanceTypes.projects.any(project_id=context.project_id)
+ ])
+ query = query.filter(or_(*the_filter))
+ return query
@require_context
@@ -4029,9 +4036,11 @@ def instance_type_get_by_name(context, name, session=None):
@require_context
-def instance_type_get_by_flavor_id(context, flavor_id, session=None):
+def instance_type_get_by_flavor_id(context, flavor_id, read_deleted,
+ session=None):
"""Returns a dict describing specific flavor_id"""
- result = _instance_type_get_query(context, session=session).\
+ result = _instance_type_get_query(context, read_deleted=read_deleted,
+ session=session).\
filter_by(flavorid=flavor_id).\
first()
@@ -4083,7 +4092,7 @@ def instance_type_access_add(context, flavor_id, project_id):
session = get_session()
with session.begin():
instance_type_ref = instance_type_get_by_flavor_id(context, flavor_id,
- session=session)
+ read_deleted='no', session=session)
instance_type_id = instance_type_ref['id']
access_ref = _instance_type_access_query(context, session=session).\
filter_by(instance_type_id=instance_type_id).\
@@ -4111,7 +4120,7 @@ def instance_type_access_remove(context, flavor_id, project_id):
session = get_session()
with session.begin():
instance_type_ref = instance_type_get_by_flavor_id(context, flavor_id,
- session=session)
+ read_deleted='no', session=session)
instance_type_id = instance_type_ref['id']
access_ref = _instance_type_access_query(context, session=session).\
filter_by(instance_type_id=instance_type_id).\
@@ -4447,7 +4456,8 @@ def instance_type_extra_specs_update_or_create(context, flavor_id,
specs):
session = get_session()
spec_ref = None
- instance_type = instance_type_get_by_flavor_id(context, flavor_id)
+ instance_type = instance_type_get_by_flavor_id(context, flavor_id,
+ read_deleted='no')
for key, value in specs.iteritems():
try:
spec_ref = instance_type_extra_specs_get_item(
diff --git a/nova/tests/api/openstack/compute/contrib/test_flavor_access.py b/nova/tests/api/openstack/compute/contrib/test_flavor_access.py
index 0bf1f1b..075810b 100644
--- a/nova/tests/api/openstack/compute/contrib/test_flavor_access.py
+++ b/nova/tests/api/openstack/compute/contrib/test_flavor_access.py
@@ -68,7 +68,7 @@ def fake_get_instance_type_access_by_flavor_id(flavorid):
return res
-def fake_get_instance_type_by_flavor_id(flavorid):
+def fake_get_instance_type_by_flavor_id(flavorid, ctxt=None):
return INSTANCE_TYPES[flavorid]
diff --git a/nova/tests/api/openstack/compute/contrib/test_flavor_disabled.py b/nova/tests/api/openstack/compute/contrib/test_flavor_disabled.py
index 1225b56..933178a 100644
--- a/nova/tests/api/openstack/compute/contrib/test_flavor_disabled.py
+++ b/nova/tests/api/openstack/compute/contrib/test_flavor_disabled.py
@@ -44,7 +44,7 @@ FAKE_FLAVORS = {
}
-def fake_instance_type_get_by_flavor_id(flavorid):
+def fake_instance_type_get_by_flavor_id(flavorid, ctxt=None):
return FAKE_FLAVORS['flavor %s' % flavorid]
diff --git a/nova/tests/api/openstack/compute/contrib/test_flavor_manage.py b/nova/tests/api/openstack/compute/contrib/test_flavor_manage.py
index 70fd5e4..7174ed2 100644
--- a/nova/tests/api/openstack/compute/contrib/test_flavor_manage.py
+++ b/nova/tests/api/openstack/compute/contrib/test_flavor_manage.py
@@ -25,7 +25,8 @@ from nova import test
from nova.tests.api.openstack import fakes
-def fake_get_instance_type_by_flavor_id(flavorid, read_deleted='yes'):
+def fake_get_instance_type_by_flavor_id(flavorid, ctxt=None,
+ read_deleted='yes'):
if flavorid == 'failtest':
raise exception.NotFound("Not found sucka!")
elif not str(flavorid) == '1234':
diff --git a/nova/tests/api/openstack/compute/contrib/test_flavor_rxtx.py b/nova/tests/api/openstack/compute/contrib/test_flavor_rxtx.py
index 52163c7..afa2259 100644
--- a/nova/tests/api/openstack/compute/contrib/test_flavor_rxtx.py
+++ b/nova/tests/api/openstack/compute/contrib/test_flavor_rxtx.py
@@ -43,7 +43,7 @@ FAKE_FLAVORS = {
}
-def fake_instance_type_get_by_flavor_id(flavorid):
+def fake_instance_type_get_by_flavor_id(flavorid, ctxt=None):
return FAKE_FLAVORS['flavor %s' % flavorid]
diff --git a/nova/tests/api/openstack/compute/contrib/test_flavor_swap.py b/nova/tests/api/openstack/compute/contrib/test_flavor_swap.py
index 75e9cd7..3fd1ae9 100644
--- a/nova/tests/api/openstack/compute/contrib/test_flavor_swap.py
+++ b/nova/tests/api/openstack/compute/contrib/test_flavor_swap.py
@@ -43,7 +43,7 @@ FAKE_FLAVORS = {
}
-def fake_instance_type_get_by_flavor_id(flavorid):
+def fake_instance_type_get_by_flavor_id(flavorid, ctxt=None):
return FAKE_FLAVORS['flavor %s' % flavorid]
diff --git a/nova/tests/api/openstack/compute/contrib/test_flavorextradata.py b/nova/tests/api/openstack/compute/contrib/test_flavorextradata.py
index 8f5301a..9654605 100644
--- a/nova/tests/api/openstack/compute/contrib/test_flavorextradata.py
+++ b/nova/tests/api/openstack/compute/contrib/test_flavorextradata.py
@@ -23,7 +23,7 @@ from nova import test
from nova.tests.api.openstack import fakes
-def fake_get_instance_type_by_flavor_id(flavorid):
+def fake_get_instance_type_by_flavor_id(flavorid, ctxt=None):
return {
'id': flavorid,
'flavorid': str(flavorid),
diff --git a/nova/tests/api/openstack/compute/test_flavors.py b/nova/tests/api/openstack/compute/test_flavors.py
index 77d40df..cfa3429 100644
--- a/nova/tests/api/openstack/compute/test_flavors.py
+++ b/nova/tests/api/openstack/compute/test_flavors.py
@@ -54,7 +54,7 @@ FAKE_FLAVORS = {
}
-def fake_instance_type_get_by_flavor_id(flavorid):
+def fake_instance_type_get_by_flavor_id(flavorid, ctxt=None):
return FAKE_FLAVORS['flavor %s' % flavorid]
@@ -80,7 +80,7 @@ def empty_instance_type_get_all(inactive=False, filters=None):
return {}
-def return_instance_type_not_found(flavor_id):
+def return_instance_type_not_found(flavor_id, ctxt=None):
raise exception.InstanceTypeNotFound(flavor_id=flavor_id)
--
1.8.1.5

View File

@ -1,101 +0,0 @@
From d4ee081c5c0a5132781235177c430ebcf72b0b0b Mon Sep 17 00:00:00 2001
From: Vishvananda Ishaya <vishvananda@gmail.com>
Date: Fri, 19 Jul 2013 10:23:59 -0700
Subject: [PATCH] Use cached nwinfo for secgroup rules
This stops a potential DOS with source security groups by using the
db cached version of the network info instead of calling out to
the network api multiple times.
Fixes bug 1184041
Change-Id: Id5f24ecf0e8cce60c27a9aecbc6e606c4c44d6b6
(cherry picked from commit 85aac04704350566d6b06aa7a3b99649946c672c)
---
nova/db/sqlalchemy/api.py | 2 ++
nova/tests/test_libvirt.py | 4 +++-
nova/tests/test_xenapi.py | 5 +++--
nova/virt/firewall.py | 12 +++---------
4 files changed, 11 insertions(+), 12 deletions(-)
diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py
index 7fcc4f8..6d3b139 100644
--- a/nova/db/sqlalchemy/api.py
+++ b/nova/db/sqlalchemy/api.py
@@ -3649,6 +3649,8 @@ def security_group_rule_get_by_security_group(context, security_group_id,
return _security_group_rule_get_query(context, session=session).\
filter_by(parent_group_id=security_group_id).\
options(joinedload_all('grantee_group.instances.instance_type')).\
+ options(joinedload('grantee_group.instances.'
+ 'info_cache')).\
all()
diff --git a/nova/tests/test_libvirt.py b/nova/tests/test_libvirt.py
index b26a006..e956eb0 100644
--- a/nova/tests/test_libvirt.py
+++ b/nova/tests/test_libvirt.py
@@ -3240,7 +3240,9 @@ class IptablesFirewallTestCase(test.TestCase):
from nova.network import linux_net
linux_net.iptables_manager.execute = fake_iptables_execute
- _fake_stub_out_get_nw_info(self.stubs, lambda *a, **kw: network_model)
+ from nova.compute import utils as compute_utils
+ self.stubs.Set(compute_utils, 'get_nw_info_for_instance',
+ lambda instance: network_model)
network_info = network_model.legacy()
self.fw.prepare_instance_filter(instance_ref, network_info)
diff --git a/nova/tests/test_xenapi.py b/nova/tests/test_xenapi.py
index 0cf69d6..7a8f9b4 100644
--- a/nova/tests/test_xenapi.py
+++ b/nova/tests/test_xenapi.py
@@ -1690,8 +1690,9 @@ class XenAPIDom0IptablesFirewallTestCase(stubs.XenAPITestBase):
network_model = fake_network.fake_get_instance_nw_info(self.stubs,
1, spectacular=True)
- fake_network.stub_out_nw_api_get_instance_nw_info(self.stubs,
- lambda *a, **kw: network_model)
+ from nova.compute import utils as compute_utils
+ self.stubs.Set(compute_utils, 'get_nw_info_for_instance',
+ lambda instance: network_model)
network_info = network_model.legacy()
self.fw.prepare_instance_filter(instance_ref, network_info)
diff --git a/nova/virt/firewall.py b/nova/virt/firewall.py
index a093a35..7c22c86 100644
--- a/nova/virt/firewall.py
+++ b/nova/virt/firewall.py
@@ -17,10 +17,10 @@
# License for the specific language governing permissions and limitations
# under the License.
+from nova.compute import utils as compute_utils
from nova import context
from nova import db
from nova import flags
-from nova import network
from nova.network import linux_net
from nova.openstack.common import cfg
from nova.openstack.common import importutils
@@ -405,15 +405,9 @@ class IptablesFirewallDriver(FirewallDriver):
fw_rules += [' '.join(args)]
else:
if rule['grantee_group']:
- # FIXME(jkoelker) This needs to be ported up into
- # the compute manager which already
- # has access to a nw_api handle,
- # and should be the only one making
- # making rpc calls.
- nw_api = network.API()
for instance in rule['grantee_group']['instances']:
- nw_info = nw_api.get_instance_nw_info(ctxt,
- instance)
+ nw_info = compute_utils.get_nw_info_for_instance(
+ instance)
ips = [ip['address']
for ip in nw_info.fixed_ips()
--
1.8.1.5

View File

@ -1,114 +0,0 @@
From ef5730a4620b409a3b46e46966e3bc6f3a306464 Mon Sep 17 00:00:00 2001
From: Ben Nemec <bnemec@us.ibm.com>
Date: Thu, 9 May 2013 19:06:45 +0000
Subject: [PATCH] Fix problem with long messages in Qpid (from oslo)
This is commit 478ac3a3e in oslo-incubator
Qpid has a limitation where it cannot serialize a dict containing a
string greater than 65535 characters. This change alters the Qpid
implementation to JSON encode the dict before sending it, but only if
Qpid would fail to serialize it. This maintains as much backward
compatibility as possible, though long messages will still fail if they
are sent to an older receiver.
Even though this change will modify the message format, it will only do
it when messages are longer than 65K which would be broken anyway and
could cause serious bugs like the one linked below.
Fixes bug 1215091
Change-Id: I2f0e88435748bab631d969573d3a598d9e1f7fef
---
nova/openstack/common/rpc/impl_qpid.py | 47 ++++++++++++++++++++++++++++++++++
1 file changed, 47 insertions(+)
diff --git a/nova/openstack/common/rpc/impl_qpid.py b/nova/openstack/common/rpc/impl_qpid.py
index e579316..67388fd 100644
--- a/nova/openstack/common/rpc/impl_qpid.py
+++ b/nova/openstack/common/rpc/impl_qpid.py
@@ -23,6 +23,7 @@ import uuid
import eventlet
import greenlet
+import qpid.codec010 as qpid_codec
import qpid.messaging
import qpid.messaging.exceptions
@@ -63,6 +64,8 @@ qpid_opts = [
cfg.CONF.register_opts(qpid_opts)
+JSON_CONTENT_TYPE = 'application/json; charset=utf8'
+
class ConsumerBase(object):
"""Consumer base class."""
@@ -117,10 +120,27 @@ class ConsumerBase(object):
self.receiver = session.receiver(self.address)
self.receiver.capacity = 1
+ def _unpack_json_msg(self, msg):
+ """Load the JSON data in msg if msg.content_type indicates that it
+ is necessary. Put the loaded data back into msg.content and
+ update msg.content_type appropriately.
+
+ A Qpid Message containing a dict will have a content_type of
+ 'amqp/map', whereas one containing a string that needs to be converted
+ back from JSON will have a content_type of JSON_CONTENT_TYPE.
+
+ :param msg: a Qpid Message object
+ :returns: None
+ """
+ if msg.content_type == JSON_CONTENT_TYPE:
+ msg.content = jsonutils.loads(msg.content)
+ msg.content_type = 'amqp/map'
+
def consume(self):
"""Fetch the message and pass it to the callback object"""
message = self.receiver.fetch()
try:
+ self._unpack_json_msg(message)
self.callback(message.content)
except Exception:
LOG.exception(_("Failed to process message... skipping it."))
@@ -220,8 +240,35 @@ class Publisher(object):
"""Re-establish the Sender after a reconnection"""
self.sender = session.sender(self.address)
+ def _pack_json_msg(self, msg):
+ """Qpid cannot serialize dicts containing strings longer than 65535
+ characters. This function dumps the message content to a JSON
+ string, which Qpid is able to handle.
+
+ :param msg: May be either a Qpid Message object or a bare dict.
+ :returns: A Qpid Message with its content field JSON encoded.
+ """
+ try:
+ msg.content = jsonutils.dumps(msg.content)
+ except AttributeError:
+ # Need to have a Qpid message so we can set the content_type.
+ msg = qpid.messaging.Message(jsonutils.dumps(msg))
+ msg.content_type = JSON_CONTENT_TYPE
+ return msg
+
def send(self, msg):
"""Send a message"""
+ try:
+ # Check if Qpid can encode the message
+ check_msg = msg
+ if not hasattr(check_msg, 'content_type'):
+ check_msg = qpid.messaging.Message(msg)
+ content_type = check_msg.content_type
+ enc, dec = qpid.messaging.message.get_codec(content_type)
+ enc(check_msg.content)
+ except qpid_codec.CodecException:
+ # This means the message couldn't be serialized as a dict.
+ msg = self._pack_json_msg(msg)
self.sender.send(msg)
--
1.8.1.2

View File

@ -1,95 +0,0 @@
From 6825959560e06725d26625fd21f5c0b78b305492 Mon Sep 17 00:00:00 2001
From: Russell Bryant <rbryant@redhat.com>
Date: Tue, 20 Aug 2013 11:06:12 -0400
Subject: [PATCH] Enforce flavor access during instance boot
The code in the servers API did not pass the context when retrieving
flavor details. That means it would use an admin context instead,
bypassing all flavor access control checks.
This patch includes the fix, and the corresponding unit test for the v2
API.
Closes-bug: #1212179
(cherry picked from commit 4054cc4a22a1fea997dec76afb5646fd6c6ea6b9)
Conflicts:
nova/api/openstack/compute/plugins/v3/servers.py
nova/api/openstack/compute/servers.py
nova/tests/api/openstack/compute/plugins/v3/test_servers.py
nova/tests/api/openstack/compute/test_servers.py
Change-Id: I681ae9965e19767df22fa74c3315e4e03a459d3b
---
nova/api/openstack/compute/servers.py | 3 ++-
nova/tests/api/openstack/compute/test_servers.py | 23 +++++++++++++++++++++--
2 files changed, 23 insertions(+), 3 deletions(-)
diff --git a/nova/api/openstack/compute/servers.py b/nova/api/openstack/compute/servers.py
index 6908262..ab06595 100644
--- a/nova/api/openstack/compute/servers.py
+++ b/nova/api/openstack/compute/servers.py
@@ -844,7 +844,8 @@ class Controller(wsgi.Controller):
try:
_get_inst_type = instance_types.get_instance_type_by_flavor_id
- inst_type = _get_inst_type(flavor_id, read_deleted="no")
+ inst_type = _get_inst_type(flavor_id, ctxt=context,
+ read_deleted="no")
(instances, resv_id) = self.compute_api.create(context,
inst_type,
diff --git a/nova/tests/api/openstack/compute/test_servers.py b/nova/tests/api/openstack/compute/test_servers.py
index cd88a2a..5cb26bd 100644
--- a/nova/tests/api/openstack/compute/test_servers.py
+++ b/nova/tests/api/openstack/compute/test_servers.py
@@ -34,6 +34,7 @@ import nova.compute.api
from nova.compute import instance_types
from nova.compute import task_states
from nova.compute import vm_states
+import nova.context
import nova.db
from nova.db.sqlalchemy import models
from nova import flags
@@ -1703,10 +1704,10 @@ class ServersControllerCreateTest(test.TestCase):
"""
self.assertTrue("adminPass" not in server_dict)
- def _test_create_instance(self):
+ def _test_create_instance(self, flavor=2):
image_uuid = 'c905cedb-7281-47e4-8a62-f26bc5fc4c77'
body = dict(server=dict(
- name='server_test', imageRef=image_uuid, flavorRef=2,
+ name='server_test', imageRef=image_uuid, flavorRef=flavor,
metadata={'hello': 'world', 'open': 'stack'},
personality={}))
req = fakes.HTTPRequest.blank('/v2/fake/servers')
@@ -1718,6 +1719,24 @@ class ServersControllerCreateTest(test.TestCase):
self._check_admin_pass_len(server)
self.assertEqual(FAKE_UUID, server['id'])
+ def test_create_instance_private_flavor(self):
+ values = {
+ 'name': 'fake_name',
+ 'memory_mb': 512,
+ 'vcpus': 1,
+ 'root_gb': 10,
+ 'ephemeral_gb': 10,
+ 'flavorid': '1324',
+ 'swap': 0,
+ 'rxtx_factor': 0.5,
+ 'vcpu_weight': 1,
+ 'disabled': False,
+ 'is_public': False,
+ }
+ nova.db.instance_type_create(nova.context.get_admin_context(), values)
+ self.assertRaises(webob.exc.HTTPBadRequest, self._test_create_instance,
+ flavor=1324)
+
def test_create_server_bad_image_href(self):
image_href = 1
flavor_ref = 'http://localhost/123/flavors/3'
--
1.8.1.5

View File

@ -1,79 +0,0 @@
From 2d949c415b97ed9649e78c880ab149d0d39c1152 Mon Sep 17 00:00:00 2001
From: Xavier Queralt <xqueralt@redhat.com>
Date: Thu, 5 Sep 2013 10:08:29 +0200
Subject: [PATCH] Fix Qpid when sending long messages (from oslo)
This is commit 4f97479ad in oslo-incubator
Qpid has a limitation where it cannot serialize a dict containing a
string greater than 65535 characters. This change alters the Qpid
implementation to JSON encode the dict before sending it, but only if
Qpid would fail to serialize it. This maintains as much backward
compatibility as possible, though long messages will still fail if they
are sent to an older receiver.
The first part of this fix was ported to Grizzly in Ib52e9458a to allow
receiving messages from Havana using the new format. Even though this
change will modify the message format, it will only do it when messages
are longer than 65K which would be broken anyway and could cause serious
bugs like the one linked below.
Fixes bug 1215091
Change-Id: I505b648c3d0e1176ec7a3fc7d1646fa5a5232261
---
nova/openstack/common/rpc/impl_qpid.py | 28 ++++++++++++++++++++++++++++
1 file changed, 28 insertions(+)
diff --git a/nova/openstack/common/rpc/impl_qpid.py b/nova/openstack/common/rpc/impl_qpid.py
index 0044088..a7aebc1 100644
--- a/nova/openstack/common/rpc/impl_qpid.py
+++ b/nova/openstack/common/rpc/impl_qpid.py
@@ -31,6 +31,7 @@ from nova.openstack.common import log as logging
from nova.openstack.common.rpc import amqp as rpc_amqp
from nova.openstack.common.rpc import common as rpc_common
+qpid_codec = importutils.try_import("qpid.codec010")
qpid_messaging = importutils.try_import("qpid.messaging")
qpid_exceptions = importutils.try_import("qpid.messaging.exceptions")
@@ -247,8 +248,35 @@ class Publisher(object):
"""Re-establish the Sender after a reconnection"""
self.sender = session.sender(self.address)
+ def _pack_json_msg(self, msg):
+ """Qpid cannot serialize dicts containing strings longer than 65535
+ characters. This function dumps the message content to a JSON
+ string, which Qpid is able to handle.
+
+ :param msg: May be either a Qpid Message object or a bare dict.
+ :returns: A Qpid Message with its content field JSON encoded.
+ """
+ try:
+ msg.content = jsonutils.dumps(msg.content)
+ except AttributeError:
+ # Need to have a Qpid message so we can set the content_type.
+ msg = qpid_messaging.Message(jsonutils.dumps(msg))
+ msg.content_type = JSON_CONTENT_TYPE
+ return msg
+
def send(self, msg):
"""Send a message"""
+ try:
+ # Check if Qpid can encode the message
+ check_msg = msg
+ if not hasattr(check_msg, 'content_type'):
+ check_msg = qpid_messaging.Message(msg)
+ content_type = check_msg.content_type
+ enc, dec = qpid_messaging.message.get_codec(content_type)
+ enc(check_msg.content)
+ except qpid_codec.CodecException:
+ # This means the message couldn't be serialized as a dict.
+ msg = self._pack_json_msg(msg)
self.sender.send(msg)
--
1.8.1.2

View File

@ -1,87 +0,0 @@
From 8b686195afe7e6dfb46c56c1ef2fe9c993d8e495 Mon Sep 17 00:00:00 2001
From: Russell Bryant <rbryant@redhat.com>
Date: Tue, 20 Aug 2013 11:06:12 -0400
Subject: [PATCH] Enforce flavor access during instance boot
The code in the servers API did not pass the context when retrieving
flavor details. That means it would use an admin context instead,
bypassing all flavor access control checks.
This patch includes the fix, and the corresponding unit test for the v2
API.
Closes-bug: #1212179
(cherry picked from commit 4054cc4a22a1fea997dec76afb5646fd6c6ea6b9)
Conflicts:
nova/api/openstack/compute/plugins/v3/servers.py
nova/api/openstack/compute/servers.py
nova/tests/api/openstack/compute/plugins/v3/test_servers.py
nova/tests/api/openstack/compute/test_servers.py
Change-Id: I681ae9965e19767df22fa74c3315e4e03a459d3b
---
nova/api/openstack/compute/servers.py | 3 ++-
nova/tests/api/openstack/compute/test_servers.py | 22 ++++++++++++++++++++--
2 files changed, 22 insertions(+), 3 deletions(-)
diff --git a/nova/api/openstack/compute/servers.py b/nova/api/openstack/compute/servers.py
index 85ef080..6c38219 100644
--- a/nova/api/openstack/compute/servers.py
+++ b/nova/api/openstack/compute/servers.py
@@ -873,7 +873,8 @@ class Controller(wsgi.Controller):
try:
_get_inst_type = instance_types.get_instance_type_by_flavor_id
- inst_type = _get_inst_type(flavor_id, read_deleted="no")
+ inst_type = _get_inst_type(flavor_id, ctxt=context,
+ read_deleted="no")
(instances, resv_id) = self.compute_api.create(context,
inst_type,
diff --git a/nova/tests/api/openstack/compute/test_servers.py b/nova/tests/api/openstack/compute/test_servers.py
index 7748c2e..89d0f8a 100644
--- a/nova/tests/api/openstack/compute/test_servers.py
+++ b/nova/tests/api/openstack/compute/test_servers.py
@@ -1822,10 +1822,10 @@ class ServersControllerCreateTest(test.TestCase):
"""utility function - check server_dict for absence of adminPass."""
self.assertTrue("adminPass" not in server_dict)
- def _test_create_instance(self):
+ def _test_create_instance(self, flavor=2):
image_uuid = 'c905cedb-7281-47e4-8a62-f26bc5fc4c77'
body = dict(server=dict(
- name='server_test', imageRef=image_uuid, flavorRef=2,
+ name='server_test', imageRef=image_uuid, flavorRef=flavor,
metadata={'hello': 'world', 'open': 'stack'},
personality={}))
req = fakes.HTTPRequest.blank('/v2/fake/servers')
@@ -1837,6 +1837,24 @@ class ServersControllerCreateTest(test.TestCase):
self._check_admin_pass_len(server)
self.assertEqual(FAKE_UUID, server['id'])
+ def test_create_instance_private_flavor(self):
+ values = {
+ 'name': 'fake_name',
+ 'memory_mb': 512,
+ 'vcpus': 1,
+ 'root_gb': 10,
+ 'ephemeral_gb': 10,
+ 'flavorid': '1324',
+ 'swap': 0,
+ 'rxtx_factor': 0.5,
+ 'vcpu_weight': 1,
+ 'disabled': False,
+ 'is_public': False,
+ }
+ db.instance_type_create(context.get_admin_context(), values)
+ self.assertRaises(webob.exc.HTTPBadRequest, self._test_create_instance,
+ flavor=1324)
+
def test_create_server_bad_image_href(self):
image_href = 1
flavor_ref = 'http://localhost/123/flavors/3'
--
1.8.1.5

View File

@ -1,103 +0,0 @@
From fb030283bed9e41a0343581fa21b81b2ebb07f15 Mon Sep 17 00:00:00 2001
From: Xiaoyan Ding <xyding@cn.ibm.com>
Date: Mon, 24 Feb 2014 16:17:46 +0800
Subject: [PATCH] VMWare: add power off vm before detach disk during unrescue
Non Hot Plug type disk like IDE can only be detached when the VM is power off.
Change-Id: Ib1f387a41abe2b52357854e90c2535ebb7b43f18
Close-bug: #1279199
(cherry picked from commit 1e1915aaaca38b5691794e0e052a42b9d95dd3c2)
---
nova/tests/virt/vmwareapi/test_driver_api.py | 27 ++++++++++++++++++++++-----
nova/virt/vmwareapi/vmops.py | 21 ++++++++++++++++-----
2 files changed, 38 insertions(+), 10 deletions(-)
diff --git a/nova/tests/virt/vmwareapi/test_driver_api.py b/nova/tests/virt/vmwareapi/test_driver_api.py
index fb60335..c1481aa 100644
--- a/nova/tests/virt/vmwareapi/test_driver_api.py
+++ b/nova/tests/virt/vmwareapi/test_driver_api.py
@@ -1273,14 +1273,31 @@ def test_rescue_with_config_drive(self):
def test_unrescue(self):
self._rescue()
+ self.test_vm_ref = None
+ self.test_device_name = None
- def fake_detach_disk_from_vm(*args, **kwargs):
- pass
+ def fake_power_off_vm_ref(vm_ref):
+ self.test_vm_ref = vm_ref
+ self.assertIsNotNone(vm_ref)
- self.stubs.Set(self.conn._volumeops, "detach_disk_from_vm",
- fake_detach_disk_from_vm)
+ def fake_detach_disk_from_vm(vm_ref, instance,
+ device_name, destroy_disk=False):
+ self.test_device_name = device_name
+ info = self.conn.get_info(instance)
+ self._check_vm_info(info, power_state.SHUTDOWN)
- self.conn.unrescue(self.instance, None)
+ with contextlib.nested(
+ mock.patch.object(self.conn._vmops, "_power_off_vm_ref",
+ side_effect=fake_power_off_vm_ref),
+ mock.patch.object(self.conn._volumeops, "detach_disk_from_vm",
+ side_effect=fake_detach_disk_from_vm),
+ ) as (poweroff, detach):
+ self.conn.unrescue(self.instance, None)
+ poweroff.assert_called_once_with(self.test_vm_ref)
+ detach.assert_called_once_with(self.test_vm_ref, mock.ANY,
+ self.test_device_name)
+ self.test_vm_ref = None
+ self.test_device_name = None
info = self.conn.get_info({'name': 1, 'uuid': self.uuid,
'node': self.instance_node})
self._check_vm_info(info, power_state.RUNNING)
diff --git a/nova/virt/vmwareapi/vmops.py b/nova/virt/vmwareapi/vmops.py
index 0c28a29..30f8373 100644
--- a/nova/virt/vmwareapi/vmops.py
+++ b/nova/virt/vmwareapi/vmops.py
@@ -1159,12 +1159,26 @@ def unrescue(self, instance):
"get_dynamic_property", vm_rescue_ref,
"VirtualMachine", "config.hardware.device")
device = vm_util.get_vmdk_volume_disk(hardware_devices, path=vmdk_path)
+ self._power_off_vm_ref(vm_rescue_ref)
self._volumeops.detach_disk_from_vm(vm_rescue_ref, r_instance, device)
self.destroy(r_instance, None, instance_name=instance_name)
self._power_on(instance)
+ def _power_off_vm_ref(self, vm_ref):
+ """Power off the specifed vm.
+
+ :param vm_ref: a reference object to the VM.
+ """
+ poweroff_task = self._session._call_method(
+ self._session._get_vim(),
+ "PowerOffVM_Task", vm_ref)
+ self._session._wait_for_task(poweroff_task)
+
def power_off(self, instance):
- """Power off the specified instance."""
+ """Power off the specified instance.
+
+ :param instance: nova.objects.instance.Instance
+ """
vm_ref = vm_util.get_vm_ref(self._session, instance)
pwr_state = self._session._call_method(vim_util,
@@ -1173,10 +1187,7 @@ def power_off(self, instance):
# Only PoweredOn VMs can be powered off.
if pwr_state == "poweredOn":
LOG.debug(_("Powering off the VM"), instance=instance)
- poweroff_task = self._session._call_method(
- self._session._get_vim(),
- "PowerOffVM_Task", vm_ref)
- self._session._wait_for_task(poweroff_task)
+ self._power_off_vm_ref(vm_ref)
LOG.debug(_("Powered off the VM"), instance=instance)
# Raise Exception if VM is suspended
elif pwr_state == "suspended":
--
1.9.3

View File

@ -1,182 +0,0 @@
From ffcb17678c7e5409a1f12a09945b18e8879a677d Mon Sep 17 00:00:00 2001
From: Gary Kotton <gkotton@vmware.com>
Date: Thu, 13 Mar 2014 06:53:58 -0700
Subject: [PATCH] VMware: ensure rescue instance is deleted when instance is
deleted
If the user creates a rescue instance and then proceeded to delete
the original instance then the rescue instance would still be up
and running on the backend.
This patch ensures that the rescue instance is cleaned up if
necessary.
The vmops unrescue method has a new parameter indicating if
the original VM should be powered on.
Closes-bug: 1269418
(cherry picked from commit efb66531bc37ee416778a70d46c657608ca767af)
Conflicts:
nova/virt/vmwareapi/vmops.py
Change-Id: I3c1d0b1d003392b306094b80ea1ac99377441fbf
---
nova/tests/virt/vmwareapi/test_driver_api.py | 26 +++++++++++++
nova/virt/vmwareapi/vmops.py | 55 ++++++++++++++++++++--------
2 files changed, 65 insertions(+), 16 deletions(-)
diff --git a/nova/tests/virt/vmwareapi/test_driver_api.py b/nova/tests/virt/vmwareapi/test_driver_api.py
index c1481aa..63f0c59 100644
--- a/nova/tests/virt/vmwareapi/test_driver_api.py
+++ b/nova/tests/virt/vmwareapi/test_driver_api.py
@@ -34,6 +34,7 @@
from nova.compute import api as compute_api
from nova.compute import power_state
from nova.compute import task_states
+from nova.compute import vm_states
from nova import context
from nova import exception
from nova.openstack.common import jsonutils
@@ -1191,6 +1192,31 @@ def test_get_info(self):
'node': self.instance_node})
self._check_vm_info(info, power_state.RUNNING)
+ def destroy_rescued(self, fake_method):
+ self._rescue()
+ with (
+ mock.patch.object(self.conn._volumeops, "detach_disk_from_vm",
+ fake_method)
+ ):
+ self.instance['vm_state'] = vm_states.RESCUED
+ self.conn.destroy(self.context, self.instance, self.network_info)
+ inst_path = '[%s] %s/%s.vmdk' % (self.ds, self.uuid, self.uuid)
+ self.assertFalse(vmwareapi_fake.get_file(inst_path))
+ rescue_file_path = '[%s] %s-rescue/%s-rescue.vmdk' % (self.ds,
+ self.uuid,
+ self.uuid)
+ self.assertFalse(vmwareapi_fake.get_file(rescue_file_path))
+
+ def test_destroy_rescued(self):
+ def fake_detach_disk_from_vm(*args, **kwargs):
+ pass
+ self.destroy_rescued(fake_detach_disk_from_vm)
+
+ def test_destroy_rescued_with_exception(self):
+ def fake_detach_disk_from_vm(*args, **kwargs):
+ raise exception.NovaException('Here is my fake exception')
+ self.destroy_rescued(fake_detach_disk_from_vm)
+
def test_destroy(self):
self._create_vm()
info = self.conn.get_info({'uuid': self.uuid,
diff --git a/nova/virt/vmwareapi/vmops.py b/nova/virt/vmwareapi/vmops.py
index 30f8373..831da48 100644
--- a/nova/virt/vmwareapi/vmops.py
+++ b/nova/virt/vmwareapi/vmops.py
@@ -29,6 +29,7 @@
from nova import compute
from nova.compute import power_state
from nova.compute import task_states
+from nova.compute import vm_states
from nova import context as nova_context
from nova import exception
from nova.openstack.common import excutils
@@ -985,13 +986,9 @@ def _delete(self, instance, network_info):
except Exception as exc:
LOG.exception(exc, instance=instance)
- def destroy(self, instance, network_info, destroy_disks=True,
- instance_name=None):
- """Destroy a VM instance. Steps followed are:
- 1. Power off the VM, if it is in poweredOn state.
- 2. Un-register a VM.
- 3. Delete the contents of the folder holding the VM related data.
- """
+ def _destroy_instance(self, instance, network_info, destroy_disks=True,
+ instance_name=None):
+ # Destroy a VM instance
# Get the instance name. In some cases this may differ from the 'uuid',
# for example when the spawn of a rescue instance takes place.
if not instance_name:
@@ -1029,8 +1026,9 @@ def destroy(self, instance, network_info, destroy_disks=True,
"UnregisterVM", vm_ref)
LOG.debug(_("Unregistered the VM"), instance=instance)
except Exception as excep:
- LOG.warn(_("In vmwareapi:vmops:destroy, got this exception"
- " while un-registering the VM: %s") % str(excep))
+ LOG.warn(_("In vmwareapi:vmops:_destroy_instance, got this "
+ "exception while un-registering the VM: %s"),
+ excep)
# Delete the folder holding the VM related content on
# the datastore.
if destroy_disks and datastore_name:
@@ -1053,15 +1051,39 @@ def destroy(self, instance, network_info, destroy_disks=True,
{'datastore_name': datastore_name},
instance=instance)
except Exception as excep:
- LOG.warn(_("In vmwareapi:vmops:destroy, "
- "got this exception while deleting"
- " the VM contents from the disk: %s")
- % str(excep))
+ LOG.warn(_("In vmwareapi:vmops:_destroy_instance, "
+ "got this exception while deleting "
+ "the VM contents from the disk: %s"),
+ excep)
except Exception as exc:
LOG.exception(exc, instance=instance)
finally:
vm_util.vm_ref_cache_delete(instance_name)
+ def destroy(self, instance, network_info, destroy_disks=True):
+ """Destroy a VM instance.
+
+ Steps followed for each VM are:
+ 1. Power off, if it is in poweredOn state.
+ 2. Un-register.
+ 3. Delete the contents of the folder holding the VM related data.
+ """
+ # If there is a rescue VM then we need to destroy that one too.
+ LOG.debug(_("Destroying instance"), instance=instance)
+ if instance['vm_state'] == vm_states.RESCUED:
+ LOG.debug(_("Rescue VM configured"), instance=instance)
+ try:
+ self.unrescue(instance, power_on=False)
+ LOG.debug(_("Rescue VM destroyed"), instance=instance)
+ except Exception:
+ rescue_name = instance['uuid'] + self._rescue_suffix
+ self._destroy_instance(instance, network_info,
+ destroy_disks=destroy_disks,
+ instance_name=rescue_name)
+ self._destroy_instance(instance, network_info,
+ destroy_disks=destroy_disks)
+ LOG.debug(_("Instance destroyed"), instance=instance)
+
def pause(self, instance):
msg = _("pause not supported for vmwareapi")
raise NotImplementedError(msg)
@@ -1139,7 +1161,7 @@ def rescue(self, context, instance, network_info, image_meta):
adapter_type, disk_type, vmdk_path)
self._power_on(instance, vm_ref=rescue_vm_ref)
- def unrescue(self, instance):
+ def unrescue(self, instance, power_on=True):
"""Unrescue the specified instance."""
# Get the original vmdk_path
vm_ref = vm_util.get_vm_ref(self._session, instance)
@@ -1161,8 +1183,9 @@ def unrescue(self, instance):
device = vm_util.get_vmdk_volume_disk(hardware_devices, path=vmdk_path)
self._power_off_vm_ref(vm_rescue_ref)
self._volumeops.detach_disk_from_vm(vm_rescue_ref, r_instance, device)
- self.destroy(r_instance, None, instance_name=instance_name)
- self._power_on(instance)
+ self._destroy_instance(r_instance, None, instance_name=instance_name)
+ if power_on:
+ self._power_on(instance)
def _power_off_vm_ref(self, vm_ref):
"""Power off the specifed vm.
--
1.9.3

View File

@ -1,432 +0,0 @@
From 135faa7b5d9855312bedc19e5e1ecebae34d3d18 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?P=C3=A1draig=20Brady?= <pbrady@redhat.com>
Date: Fri, 27 Sep 2013 04:07:14 +0100
Subject: [PATCH] ensure we don't boot oversized images
Since we can't generally shrink incoming images, add extra checks
to ensure oversized images are not allowed through.
All cases when populating the libvirt image cache are now handled,
including the initial download from glance, where we avoid
converting to raw, as that could generate non sparse images
much larger than the downloaded image.
* nova/virt/libvirt/utils.py (fetch_image): Allow passing through
of the max_size parameter.
* nova/virt/images.py (fetch_to_raw): Accept the max_size parameter,
and use it to discard images with larger (virtual) sizes.
* nova/virt/libvirt/imagebackend.py (verify_base_size): A new
refactored function to identify and raise exception to oversized images.
(Raw.create_image): Pass the max_size to the fetch function.
Also enforce virtual image size checking for already fetched images,
as this class (despite the name) can be handling qcow files.
(Qcow2.create_image): Pass the max_size to the fetch function,
or verify the virtual size for the instance as done previously.
(Lvm.create_image): Pass the max_size to the fetch function.
Also check the size before transferring to the volume to improve
efficiency by not even attempting the transfer of oversized images.
(Rbd.create_image): Likewise.
* nova/tests/fake_libvirt_utils.py: Support max_size arg.
* nova/tests/test_libvirt.py (test_fetch_raw_image):
Add a case to check oversized images are discarded.
* nova/tests/test_imagebackend.py (test_create_image_too_small):
Adjust to avoid the fetch size check.
Fixes bug: 1177830
Fixes bug: 1206081
Conflicts:
nova/tests/test_imagebackend.py
nova/virt/libvirt/imagebackend.py
Change-Id: Idc35fce580be4f74e23883d1b4bea6475c3f6e30
---
nova/tests/fake_libvirt_utils.py | 2 +-
nova/tests/test_imagebackend.py | 35 ++++++++++-------------------
nova/tests/test_libvirt.py | 24 +++++++++++++++++---
nova/virt/images.py | 24 +++++++++++++++++---
nova/virt/libvirt/imagebackend.py | 47 ++++++++++++++++++++++++++++++---------
nova/virt/libvirt/utils.py | 5 +++--
6 files changed, 95 insertions(+), 42 deletions(-)
diff --git a/nova/tests/fake_libvirt_utils.py b/nova/tests/fake_libvirt_utils.py
index 23b758e..ecf357a 100644
--- a/nova/tests/fake_libvirt_utils.py
+++ b/nova/tests/fake_libvirt_utils.py
@@ -193,7 +193,7 @@ def get_fs_info(path):
'free': 84 * (1024 ** 3)}
-def fetch_image(context, target, image_id, user_id, project_id):
+def fetch_image(context, target, image_id, user_id, project_id, max_size=0):
pass
diff --git a/nova/tests/test_imagebackend.py b/nova/tests/test_imagebackend.py
index 77446e8..93ed23d 100644
--- a/nova/tests/test_imagebackend.py
+++ b/nova/tests/test_imagebackend.py
@@ -189,7 +189,7 @@ def prepare_mocks(self):
def test_create_image(self):
fn = self.prepare_mocks()
- fn(target=self.TEMPLATE_PATH, image_id=None)
+ fn(target=self.TEMPLATE_PATH, max_size=None, image_id=None)
imagebackend.libvirt_utils.copy_image(self.TEMPLATE_PATH, self.PATH)
self.mox.ReplayAll()
@@ -210,7 +210,7 @@ def test_create_image_generated(self):
def test_create_image_extend(self):
fn = self.prepare_mocks()
- fn(target=self.TEMPLATE_PATH, image_id=None)
+ fn(max_size=self.SIZE, target=self.TEMPLATE_PATH, image_id=None)
imagebackend.libvirt_utils.copy_image(self.TEMPLATE_PATH, self.PATH)
imagebackend.disk.extend(self.PATH, self.SIZE)
self.mox.ReplayAll()
@@ -260,7 +260,7 @@ def prepare_mocks(self):
def test_create_image(self):
fn = self.prepare_mocks()
- fn(target=self.TEMPLATE_PATH)
+ fn(max_size=None, target=self.TEMPLATE_PATH)
imagebackend.libvirt_utils.create_cow_image(self.TEMPLATE_PATH,
self.PATH)
self.mox.ReplayAll()
@@ -272,15 +272,12 @@ def test_create_image(self):
def test_create_image_with_size(self):
fn = self.prepare_mocks()
- fn(target=self.TEMPLATE_PATH)
+ fn(max_size=self.SIZE, target=self.TEMPLATE_PATH)
self.mox.StubOutWithMock(os.path, 'exists')
- self.mox.StubOutWithMock(imagebackend.disk, 'get_disk_size')
if self.OLD_STYLE_INSTANCE_PATH:
os.path.exists(self.OLD_STYLE_INSTANCE_PATH).AndReturn(False)
os.path.exists(self.TEMPLATE_PATH).AndReturn(False)
os.path.exists(self.PATH).AndReturn(False)
- imagebackend.disk.get_disk_size(self.TEMPLATE_PATH
- ).AndReturn(self.SIZE)
os.path.exists(self.PATH).AndReturn(False)
imagebackend.libvirt_utils.create_cow_image(self.TEMPLATE_PATH,
self.PATH)
@@ -294,27 +291,24 @@ def test_create_image_with_size(self):
def test_create_image_too_small(self):
fn = self.prepare_mocks()
- fn(target=self.TEMPLATE_PATH)
self.mox.StubOutWithMock(os.path, 'exists')
self.mox.StubOutWithMock(imagebackend.disk, 'get_disk_size')
if self.OLD_STYLE_INSTANCE_PATH:
os.path.exists(self.OLD_STYLE_INSTANCE_PATH).AndReturn(False)
- os.path.exists(self.TEMPLATE_PATH).AndReturn(False)
- os.path.exists(self.PATH).AndReturn(False)
+ os.path.exists(self.TEMPLATE_PATH).AndReturn(True)
imagebackend.disk.get_disk_size(self.TEMPLATE_PATH
).AndReturn(self.SIZE)
self.mox.ReplayAll()
image = self.image_class(self.INSTANCE, self.NAME)
- self.assertRaises(exception.ImageTooLarge, image.create_image, fn,
- self.TEMPLATE_PATH, 1)
+ self.assertRaises(exception.InstanceTypeDiskTooSmall,
+ image.create_image, fn, self.TEMPLATE_PATH, 1)
self.mox.VerifyAll()
def test_generate_resized_backing_files(self):
fn = self.prepare_mocks()
- fn(target=self.TEMPLATE_PATH)
+ fn(max_size=self.SIZE, target=self.TEMPLATE_PATH)
self.mox.StubOutWithMock(os.path, 'exists')
- self.mox.StubOutWithMock(imagebackend.disk, 'get_disk_size')
self.mox.StubOutWithMock(imagebackend.libvirt_utils,
'get_disk_backing_file')
if self.OLD_STYLE_INSTANCE_PATH:
@@ -329,8 +323,6 @@ def test_generate_resized_backing_files(self):
self.QCOW2_BASE)
imagebackend.disk.extend(self.QCOW2_BASE, self.SIZE)
- imagebackend.disk.get_disk_size(self.TEMPLATE_PATH
- ).AndReturn(self.SIZE)
os.path.exists(self.PATH).AndReturn(True)
self.mox.ReplayAll()
@@ -341,9 +333,8 @@ def test_generate_resized_backing_files(self):
def test_qcow2_exists_and_has_no_backing_file(self):
fn = self.prepare_mocks()
- fn(target=self.TEMPLATE_PATH)
+ fn(max_size=self.SIZE, target=self.TEMPLATE_PATH)
self.mox.StubOutWithMock(os.path, 'exists')
- self.mox.StubOutWithMock(imagebackend.disk, 'get_disk_size')
self.mox.StubOutWithMock(imagebackend.libvirt_utils,
'get_disk_backing_file')
if self.OLD_STYLE_INSTANCE_PATH:
@@ -353,8 +344,6 @@ def test_qcow2_exists_and_has_no_backing_file(self):
imagebackend.libvirt_utils.get_disk_backing_file(self.PATH)\
.AndReturn(None)
- imagebackend.disk.get_disk_size(self.TEMPLATE_PATH
- ).AndReturn(self.SIZE)
os.path.exists(self.PATH).AndReturn(True)
self.mox.ReplayAll()
@@ -391,7 +380,7 @@ def prepare_mocks(self):
def _create_image(self, sparse):
fn = self.prepare_mocks()
- fn(target=self.TEMPLATE_PATH)
+ fn(max_size=None, target=self.TEMPLATE_PATH)
self.libvirt_utils.create_lvm_image(self.VG,
self.LV,
self.TEMPLATE_SIZE,
@@ -423,7 +412,7 @@ def _create_image_generated(self, sparse):
def _create_image_resize(self, sparse):
fn = self.prepare_mocks()
- fn(target=self.TEMPLATE_PATH)
+ fn(max_size=self.SIZE, target=self.TEMPLATE_PATH)
self.libvirt_utils.create_lvm_image(self.VG, self.LV,
self.SIZE, sparse=sparse)
self.disk.get_disk_size(self.TEMPLATE_PATH
@@ -462,7 +451,7 @@ def test_create_image_resize_sparsed(self):
def test_create_image_negative(self):
fn = self.prepare_mocks()
- fn(target=self.TEMPLATE_PATH)
+ fn(max_size=self.SIZE, target=self.TEMPLATE_PATH)
self.libvirt_utils.create_lvm_image(self.VG,
self.LV,
self.SIZE,
diff --git a/nova/tests/test_libvirt.py b/nova/tests/test_libvirt.py
index d8c4cf2..e422ec7 100644
--- a/nova/tests/test_libvirt.py
+++ b/nova/tests/test_libvirt.py
@@ -4826,7 +4826,8 @@ def test_fetch_image(self):
image_id = '4'
user_id = 'fake'
project_id = 'fake'
- images.fetch_to_raw(context, image_id, target, user_id, project_id)
+ images.fetch_to_raw(context, image_id, target, user_id, project_id,
+ max_size=0)
self.mox.ReplayAll()
libvirt_utils.fetch_image(context, target, image_id,
@@ -4856,20 +4857,27 @@ class FakeImgInfo(object):
file_format = path.split('.')[-2]
elif file_format == 'converted':
file_format = 'raw'
+
if 'backing' in path:
backing_file = 'backing'
else:
backing_file = None
+ if 'big' in path:
+ virtual_size = 2
+ else:
+ virtual_size = 1
+
FakeImgInfo.file_format = file_format
FakeImgInfo.backing_file = backing_file
+ FakeImgInfo.virtual_size = virtual_size
return FakeImgInfo()
self.stubs.Set(utils, 'execute', fake_execute)
self.stubs.Set(os, 'rename', fake_rename)
self.stubs.Set(os, 'unlink', fake_unlink)
- self.stubs.Set(images, 'fetch', lambda *_: None)
+ self.stubs.Set(images, 'fetch', lambda *_, **__: None)
self.stubs.Set(images, 'qemu_img_info', fake_qemu_img_info)
self.stubs.Set(utils, 'delete_if_exists', fake_rm_on_errror)
@@ -4884,7 +4892,8 @@ class FakeImgInfo(object):
't.qcow2.part', 't.qcow2.converted'),
('rm', 't.qcow2.part'),
('mv', 't.qcow2.converted', 't.qcow2')]
- images.fetch_to_raw(context, image_id, target, user_id, project_id)
+ images.fetch_to_raw(context, image_id, target, user_id, project_id,
+ max_size=1)
self.assertEqual(self.executes, expected_commands)
target = 't.raw'
@@ -4901,6 +4910,15 @@ class FakeImgInfo(object):
context, image_id, target, user_id, project_id)
self.assertEqual(self.executes, expected_commands)
+ target = 'big.qcow2'
+ self.executes = []
+ expected_commands = [('rm', '-f', 'big.qcow2.part')]
+ self.assertRaises(exception.InstanceTypeDiskTooSmall,
+ images.fetch_to_raw,
+ context, image_id, target, user_id, project_id,
+ max_size=1)
+ self.assertEqual(self.executes, expected_commands)
+
del self.executes
def test_get_disk_backing_file(self):
diff --git a/nova/virt/images.py b/nova/virt/images.py
index b40f566..541779a 100755
--- a/nova/virt/images.py
+++ b/nova/virt/images.py
@@ -190,7 +190,7 @@ def convert_image(source, dest, out_format, run_as_root=False):
utils.execute(*cmd, run_as_root=run_as_root)
-def fetch(context, image_href, path, _user_id, _project_id):
+def fetch(context, image_href, path, _user_id, _project_id, max_size=0):
# TODO(vish): Improve context handling and add owner and auth data
# when it is added to glance. Right now there is no
# auth checking in glance, so we assume that access was
@@ -202,9 +202,10 @@ def fetch(context, image_href, path, _user_id, _project_id):
image_service.download(context, image_id, image_file)
-def fetch_to_raw(context, image_href, path, user_id, project_id):
+def fetch_to_raw(context, image_href, path, user_id, project_id, max_size=0):
path_tmp = "%s.part" % path
- fetch(context, image_href, path_tmp, user_id, project_id)
+ fetch(context, image_href, path_tmp, user_id, project_id,
+ max_size=max_size)
with utils.remove_path_on_error(path_tmp):
data = qemu_img_info(path_tmp)
@@ -220,6 +221,23 @@ def fetch_to_raw(context, image_href, path, user_id, project_id):
raise exception.ImageUnacceptable(image_id=image_href,
reason=_("fmt=%(fmt)s backed by: %(backing_file)s") % locals())
+ # We can't generally shrink incoming images, so disallow
+ # images > size of the flavor we're booting. Checking here avoids
+ # an immediate DoS where we convert large qcow images to raw
+ # (which may compress well but not be sparse).
+ # TODO(p-draigbrady): loop through all flavor sizes, so that
+ # we might continue here and not discard the download.
+ # If we did that we'd have to do the higher level size checks
+ # irrespective of whether the base image was prepared or not.
+ disk_size = data.virtual_size
+ if max_size and max_size < disk_size:
+ msg = _('%(base)s virtual size %(disk_size)s '
+ 'larger than flavor root disk size %(size)s')
+ LOG.error(msg % {'base': path,
+ 'disk_size': disk_size,
+ 'size': max_size})
+ raise exception.InstanceTypeDiskTooSmall()
+
if fmt != "raw" and CONF.force_raw_images:
staged = "%s.converted" % path
LOG.debug("%s was %s, converting to raw" % (image_href, fmt))
diff --git a/nova/virt/libvirt/imagebackend.py b/nova/virt/libvirt/imagebackend.py
index e2c7ccf..dc85c97 100755
--- a/nova/virt/libvirt/imagebackend.py
+++ b/nova/virt/libvirt/imagebackend.py
@@ -177,6 +177,36 @@ def _can_fallocate(self):
(CONF.preallocate_images, self.path))
return can_fallocate
+ @staticmethod
+ def verify_base_size(base, size, base_size=0):
+ """Check that the base image is not larger than size.
+ Since images can't be generally shrunk, enforce this
+ constraint taking account of virtual image size.
+ """
+
+ # Note(pbrady): The size and min_disk parameters of a glance
+ # image are checked against the instance size before the image
+ # is even downloaded from glance, but currently min_disk is
+ # adjustable and doesn't currently account for virtual disk size,
+ # so we need this extra check here.
+ # NOTE(cfb): Having a flavor that sets the root size to 0 and having
+ # nova effectively ignore that size and use the size of the
+ # image is considered a feature at this time, not a bug.
+
+ if size is None:
+ return
+
+ if size and not base_size:
+ base_size = disk.get_disk_size(base)
+
+ if size < base_size:
+ msg = _('%(base)s virtual size %(base_size)s '
+ 'larger than flavor root disk size %(size)s')
+ LOG.error(msg % {'base': base,
+ 'base_size': base_size,
+ 'size': size})
+ raise exception.InstanceTypeDiskTooSmall()
+
def snapshot_create(self):
raise NotImplementedError
@@ -217,7 +247,8 @@ def copy_raw_image(base, target, size):
#Generating image in place
prepare_template(target=self.path, *args, **kwargs)
else:
- prepare_template(target=base, *args, **kwargs)
+ prepare_template(target=base, max_size=size, *args, **kwargs)
+ self.verify_base_size(base, size)
if not os.path.exists(self.path):
with utils.remove_path_on_error(self.path):
copy_raw_image(base, self.path, size)
@@ -257,7 +288,9 @@ def copy_qcow2_image(base, target, size):
# Download the unmodified base image unless we already have a copy.
if not os.path.exists(base):
- prepare_template(target=base, *args, **kwargs)
+ prepare_template(target=base, max_size=size, *args, **kwargs)
+ else:
+ self.verify_base_size(base, size)
legacy_backing_size = None
legacy_base = base
@@ -283,13 +316,6 @@ def copy_qcow2_image(base, target, size):
libvirt_utils.copy_image(base, legacy_base)
disk.extend(legacy_base, legacy_backing_size)
- # NOTE(cfb): Having a flavor that sets the root size to 0 and having
- # nova effectively ignore that size and use the size of the
- # image is considered a feature at this time, not a bug.
- if size and size < disk.get_disk_size(base):
- LOG.error('%s virtual size larger than flavor root disk size %s' %
- (base, size))
- raise exception.ImageTooLarge()
if not os.path.exists(self.path):
with utils.remove_path_on_error(self.path):
copy_qcow2_image(base, self.path, size)
@@ -348,6 +374,7 @@ def create_image(self, prepare_template, base, size, *args, **kwargs):
lock_path=self.lock_path)
def create_lvm_image(base, size):
base_size = disk.get_disk_size(base)
+ self.verify_base_size(base, size, base_size=base_size)
resize = size > base_size
size = size if resize else base_size
libvirt_utils.create_lvm_image(self.vg, self.lv,
@@ -365,7 +392,7 @@ def create_lvm_image(base, size):
with self.remove_volume_on_error(self.path):
prepare_template(target=self.path, *args, **kwargs)
else:
- prepare_template(target=base, *args, **kwargs)
+ prepare_template(target=base, max_size=size, *args, **kwargs)
with self.remove_volume_on_error(self.path):
create_lvm_image(base, size)
diff --git a/nova/virt/libvirt/utils.py b/nova/virt/libvirt/utils.py
index 6972243..4c31fcb 100755
--- a/nova/virt/libvirt/utils.py
+++ b/nova/virt/libvirt/utils.py
@@ -592,9 +592,10 @@ def get_fs_info(path):
'used': used}
-def fetch_image(context, target, image_id, user_id, project_id):
+def fetch_image(context, target, image_id, user_id, project_id, max_size=0):
"""Grab image."""
- images.fetch_to_raw(context, image_id, target, user_id, project_id)
+ images.fetch_to_raw(context, image_id, target, user_id, project_id,
+ max_size=max_size)
def get_instance_path(instance, forceold=False, relative=False):
--
1.8.4

View File

@ -1,452 +0,0 @@
From 3cdfe894ab58f7b91bf7fb690fc5bc724e44066f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?P=C3=A1draig=20Brady?= <pbrady@redhat.com>
Date: Fri, 27 Sep 2013 04:07:14 +0100
Subject: [PATCH] ensure we don't boot oversized images
Since we can't generally shrink incoming images, add extra checks
to ensure oversized images are not allowed through.
All cases when populating the libvirt image cache are now handled,
including the initial download from glance, where we avoid
converting to raw, as that could generate non sparse images
much larger than the downloaded image.
* nova/virt/libvirt/utils.py (fetch_image): Allow passing through
of the max_size parameter.
* nova/virt/images.py (fetch_to_raw): Accept the max_size parameter,
and use it to discard images with larger (virtual) sizes.
* nova/virt/libvirt/imagebackend.py (verify_base_size): A new
refactored function to identify and raise exception to oversized images.
(Raw.create_image): Pass the max_size to the fetch function.
Also enforce virtual image size checking for already fetched images,
as this class (despite the name) can be handling qcow files.
(Qcow2.create_image): Pass the max_size to the fetch function,
or verify the virtual size for the instance as done previously.
(Lvm.create_image): Pass the max_size to the fetch function.
Also check the size before transferring to the volume to improve
efficiency by not even attempting the transfer of oversized images.
(Rbd.create_image): Likewise.
* nova/tests/virt/libvirt/fake_libvirt_utils.py: Support max_size arg.
* nova/tests/virt/libvirt/test_libvirt.py (test_fetch_raw_image):
Add a case to check oversized images are discarded.
* nova/tests/virt/libvirt/test_imagebackend.py
(test_create_image_too_small): Adjust to avoid the fetch size check.
Fixes bug: 1177830
Fixes bug: 1206081
Change-Id: I3d47adaa2ad07434853f447feb27d7aae0e2e717
---
nova/tests/virt/libvirt/fake_libvirt_utils.py | 2 +-
nova/tests/virt/libvirt/test_imagebackend.py | 34 ++++++-----------
nova/tests/virt/libvirt/test_libvirt.py | 24 ++++++++++--
nova/virt/images.py | 24 ++++++++++--
nova/virt/libvirt/imagebackend.py | 55 +++++++++++++++++++--------
nova/virt/libvirt/utils.py | 5 ++-
6 files changed, 98 insertions(+), 46 deletions(-)
diff --git a/nova/tests/virt/libvirt/fake_libvirt_utils.py b/nova/tests/virt/libvirt/fake_libvirt_utils.py
index e18f9df..4799837 100644
--- a/nova/tests/virt/libvirt/fake_libvirt_utils.py
+++ b/nova/tests/virt/libvirt/fake_libvirt_utils.py
@@ -197,7 +197,7 @@ def get_fs_info(path):
'free': 84 * (1024 ** 3)}
-def fetch_image(context, target, image_id, user_id, project_id):
+def fetch_image(context, target, image_id, user_id, project_id, max_size=0):
pass
diff --git a/nova/tests/virt/libvirt/test_imagebackend.py b/nova/tests/virt/libvirt/test_imagebackend.py
index b862510..2455ec8 100644
--- a/nova/tests/virt/libvirt/test_imagebackend.py
+++ b/nova/tests/virt/libvirt/test_imagebackend.py
@@ -190,7 +190,7 @@ def prepare_mocks(self):
def test_create_image(self):
fn = self.prepare_mocks()
- fn(target=self.TEMPLATE_PATH, image_id=None)
+ fn(target=self.TEMPLATE_PATH, max_size=None, image_id=None)
imagebackend.libvirt_utils.copy_image(self.TEMPLATE_PATH, self.PATH)
self.mox.ReplayAll()
@@ -211,7 +211,7 @@ def test_create_image_generated(self):
def test_create_image_extend(self):
fn = self.prepare_mocks()
- fn(target=self.TEMPLATE_PATH, image_id=None)
+ fn(max_size=self.SIZE, target=self.TEMPLATE_PATH, image_id=None)
imagebackend.libvirt_utils.copy_image(self.TEMPLATE_PATH, self.PATH)
imagebackend.disk.extend(self.PATH, self.SIZE, use_cow=False)
self.mox.ReplayAll()
@@ -261,7 +261,7 @@ def prepare_mocks(self):
def test_create_image(self):
fn = self.prepare_mocks()
- fn(target=self.TEMPLATE_PATH)
+ fn(max_size=None, target=self.TEMPLATE_PATH)
imagebackend.libvirt_utils.create_cow_image(self.TEMPLATE_PATH,
self.PATH)
self.mox.ReplayAll()
@@ -273,15 +273,12 @@ def test_create_image(self):
def test_create_image_with_size(self):
fn = self.prepare_mocks()
- fn(target=self.TEMPLATE_PATH)
+ fn(max_size=self.SIZE, target=self.TEMPLATE_PATH)
self.mox.StubOutWithMock(os.path, 'exists')
- self.mox.StubOutWithMock(imagebackend.disk, 'get_disk_size')
if self.OLD_STYLE_INSTANCE_PATH:
os.path.exists(self.OLD_STYLE_INSTANCE_PATH).AndReturn(False)
os.path.exists(self.TEMPLATE_PATH).AndReturn(False)
os.path.exists(self.PATH).AndReturn(False)
- imagebackend.disk.get_disk_size(self.TEMPLATE_PATH
- ).AndReturn(self.SIZE)
os.path.exists(self.PATH).AndReturn(False)
imagebackend.libvirt_utils.create_cow_image(self.TEMPLATE_PATH,
self.PATH)
@@ -295,13 +292,11 @@ def test_create_image_with_size(self):
def test_create_image_too_small(self):
fn = self.prepare_mocks()
- fn(target=self.TEMPLATE_PATH)
self.mox.StubOutWithMock(os.path, 'exists')
self.mox.StubOutWithMock(imagebackend.disk, 'get_disk_size')
if self.OLD_STYLE_INSTANCE_PATH:
os.path.exists(self.OLD_STYLE_INSTANCE_PATH).AndReturn(False)
- os.path.exists(self.TEMPLATE_PATH).AndReturn(False)
- os.path.exists(self.PATH).AndReturn(False)
+ os.path.exists(self.TEMPLATE_PATH).AndReturn(True)
imagebackend.disk.get_disk_size(self.TEMPLATE_PATH
).AndReturn(self.SIZE)
self.mox.ReplayAll()
@@ -313,9 +308,8 @@ def test_create_image_too_small(self):
def test_generate_resized_backing_files(self):
fn = self.prepare_mocks()
- fn(target=self.TEMPLATE_PATH)
+ fn(max_size=self.SIZE, target=self.TEMPLATE_PATH)
self.mox.StubOutWithMock(os.path, 'exists')
- self.mox.StubOutWithMock(imagebackend.disk, 'get_disk_size')
self.mox.StubOutWithMock(imagebackend.libvirt_utils,
'get_disk_backing_file')
if self.OLD_STYLE_INSTANCE_PATH:
@@ -330,8 +324,6 @@ def test_generate_resized_backing_files(self):
self.QCOW2_BASE)
imagebackend.disk.extend(self.QCOW2_BASE, self.SIZE, use_cow=True)
- imagebackend.disk.get_disk_size(self.TEMPLATE_PATH
- ).AndReturn(self.SIZE)
os.path.exists(self.PATH).AndReturn(True)
self.mox.ReplayAll()
@@ -342,9 +334,8 @@ def test_generate_resized_backing_files(self):
def test_qcow2_exists_and_has_no_backing_file(self):
fn = self.prepare_mocks()
- fn(target=self.TEMPLATE_PATH)
+ fn(max_size=self.SIZE, target=self.TEMPLATE_PATH)
self.mox.StubOutWithMock(os.path, 'exists')
- self.mox.StubOutWithMock(imagebackend.disk, 'get_disk_size')
self.mox.StubOutWithMock(imagebackend.libvirt_utils,
'get_disk_backing_file')
if self.OLD_STYLE_INSTANCE_PATH:
@@ -354,8 +345,6 @@ def test_qcow2_exists_and_has_no_backing_file(self):
imagebackend.libvirt_utils.get_disk_backing_file(self.PATH)\
.AndReturn(None)
- imagebackend.disk.get_disk_size(self.TEMPLATE_PATH
- ).AndReturn(self.SIZE)
os.path.exists(self.PATH).AndReturn(True)
self.mox.ReplayAll()
@@ -392,7 +381,7 @@ def prepare_mocks(self):
def _create_image(self, sparse):
fn = self.prepare_mocks()
- fn(target=self.TEMPLATE_PATH)
+ fn(max_size=None, target=self.TEMPLATE_PATH)
self.libvirt_utils.create_lvm_image(self.VG,
self.LV,
self.TEMPLATE_SIZE,
@@ -424,7 +413,7 @@ def _create_image_generated(self, sparse):
def _create_image_resize(self, sparse):
fn = self.prepare_mocks()
- fn(target=self.TEMPLATE_PATH)
+ fn(max_size=self.SIZE, target=self.TEMPLATE_PATH)
self.libvirt_utils.create_lvm_image(self.VG, self.LV,
self.SIZE, sparse=sparse)
self.disk.get_disk_size(self.TEMPLATE_PATH
@@ -463,7 +452,7 @@ def test_create_image_resize_sparsed(self):
def test_create_image_negative(self):
fn = self.prepare_mocks()
- fn(target=self.TEMPLATE_PATH)
+ fn(max_size=self.SIZE, target=self.TEMPLATE_PATH)
self.libvirt_utils.create_lvm_image(self.VG,
self.LV,
self.SIZE,
@@ -607,7 +596,7 @@ def test_cache_template_exists(self):
def test_create_image(self):
fn = self.prepare_mocks()
- fn(rbd=self.rbd, target=self.TEMPLATE_PATH)
+ fn(max_size=None, rbd=self.rbd, target=self.TEMPLATE_PATH)
self.rbd.RBD_FEATURE_LAYERING = 1
@@ -635,6 +624,7 @@ def fake_fetch(target, *args, **kwargs):
return
self.stubs.Set(os.path, 'exists', lambda _: True)
+ self.stubs.Set(image, 'check_image_exists', lambda: True)
image.cache(fake_fetch, self.TEMPLATE_PATH, self.SIZE)
diff --git a/nova/tests/virt/libvirt/test_libvirt.py b/nova/tests/virt/libvirt/test_libvirt.py
index ac36be4..5d1361e 100644
--- a/nova/tests/virt/libvirt/test_libvirt.py
+++ b/nova/tests/virt/libvirt/test_libvirt.py
@@ -6308,7 +6308,8 @@ def test_fetch_image(self):
image_id = '4'
user_id = 'fake'
project_id = 'fake'
- images.fetch_to_raw(context, image_id, target, user_id, project_id)
+ images.fetch_to_raw(context, image_id, target, user_id, project_id,
+ max_size=0)
self.mox.ReplayAll()
libvirt_utils.fetch_image(context, target, image_id,
@@ -6338,20 +6339,27 @@ class FakeImgInfo(object):
file_format = path.split('.')[-2]
elif file_format == 'converted':
file_format = 'raw'
+
if 'backing' in path:
backing_file = 'backing'
else:
backing_file = None
+ if 'big' in path:
+ virtual_size = 2
+ else:
+ virtual_size = 1
+
FakeImgInfo.file_format = file_format
FakeImgInfo.backing_file = backing_file
+ FakeImgInfo.virtual_size = virtual_size
return FakeImgInfo()
self.stubs.Set(utils, 'execute', fake_execute)
self.stubs.Set(os, 'rename', fake_rename)
self.stubs.Set(os, 'unlink', fake_unlink)
- self.stubs.Set(images, 'fetch', lambda *_: None)
+ self.stubs.Set(images, 'fetch', lambda *_, **__: None)
self.stubs.Set(images, 'qemu_img_info', fake_qemu_img_info)
self.stubs.Set(fileutils, 'delete_if_exists', fake_rm_on_error)
@@ -6373,7 +6381,8 @@ class FakeImgInfo(object):
't.qcow2.part', 't.qcow2.converted'),
('rm', 't.qcow2.part'),
('mv', 't.qcow2.converted', 't.qcow2')]
- images.fetch_to_raw(context, image_id, target, user_id, project_id)
+ images.fetch_to_raw(context, image_id, target, user_id, project_id,
+ max_size=1)
self.assertEqual(self.executes, expected_commands)
target = 't.raw'
@@ -6390,6 +6399,15 @@ class FakeImgInfo(object):
context, image_id, target, user_id, project_id)
self.assertEqual(self.executes, expected_commands)
+ target = 'big.qcow2'
+ self.executes = []
+ expected_commands = [('rm', '-f', 'big.qcow2.part')]
+ self.assertRaises(exception.InstanceTypeDiskTooSmall,
+ images.fetch_to_raw,
+ context, image_id, target, user_id, project_id,
+ max_size=1)
+ self.assertEqual(self.executes, expected_commands)
+
del self.executes
def test_get_disk_backing_file(self):
diff --git a/nova/virt/images.py b/nova/virt/images.py
index 9c4c101..6d20e65 100644
--- a/nova/virt/images.py
+++ b/nova/virt/images.py
@@ -179,7 +179,7 @@ def convert_image(source, dest, out_format, run_as_root=False):
utils.execute(*cmd, run_as_root=run_as_root)
-def fetch(context, image_href, path, _user_id, _project_id):
+def fetch(context, image_href, path, _user_id, _project_id, max_size=0):
# TODO(vish): Improve context handling and add owner and auth data
# when it is added to glance. Right now there is no
# auth checking in glance, so we assume that access was
@@ -190,9 +190,10 @@ def fetch(context, image_href, path, _user_id, _project_id):
image_service.download(context, image_id, dst_path=path)
-def fetch_to_raw(context, image_href, path, user_id, project_id):
+def fetch_to_raw(context, image_href, path, user_id, project_id, max_size=0):
path_tmp = "%s.part" % path
- fetch(context, image_href, path_tmp, user_id, project_id)
+ fetch(context, image_href, path_tmp, user_id, project_id,
+ max_size=max_size)
with fileutils.remove_path_on_error(path_tmp):
data = qemu_img_info(path_tmp)
@@ -209,6 +210,23 @@ def fetch_to_raw(context, image_href, path, user_id, project_id):
reason=(_("fmt=%(fmt)s backed by: %(backing_file)s") %
{'fmt': fmt, 'backing_file': backing_file}))
+ # We can't generally shrink incoming images, so disallow
+ # images > size of the flavor we're booting. Checking here avoids
+ # an immediate DoS where we convert large qcow images to raw
+ # (which may compress well but not be sparse).
+ # TODO(p-draigbrady): loop through all flavor sizes, so that
+ # we might continue here and not discard the download.
+ # If we did that we'd have to do the higher level size checks
+ # irrespective of whether the base image was prepared or not.
+ disk_size = data.virtual_size
+ if max_size and max_size < disk_size:
+ msg = _('%(base)s virtual size %(disk_size)s '
+ 'larger than flavor root disk size %(size)s')
+ LOG.error(msg % {'base': path,
+ 'disk_size': disk_size,
+ 'size': max_size})
+ raise exception.InstanceTypeDiskTooSmall()
+
if fmt != "raw" and CONF.force_raw_images:
staged = "%s.converted" % path
LOG.debug("%s was %s, converting to raw" % (image_href, fmt))
diff --git a/nova/virt/libvirt/imagebackend.py b/nova/virt/libvirt/imagebackend.py
index 84c46e8..e900789 100644
--- a/nova/virt/libvirt/imagebackend.py
+++ b/nova/virt/libvirt/imagebackend.py
@@ -193,6 +193,36 @@ def _can_fallocate(self):
(CONF.preallocate_images, self.path))
return can_fallocate
+ @staticmethod
+ def verify_base_size(base, size, base_size=0):
+ """Check that the base image is not larger than size.
+ Since images can't be generally shrunk, enforce this
+ constraint taking account of virtual image size.
+ """
+
+ # Note(pbrady): The size and min_disk parameters of a glance
+ # image are checked against the instance size before the image
+ # is even downloaded from glance, but currently min_disk is
+ # adjustable and doesn't currently account for virtual disk size,
+ # so we need this extra check here.
+ # NOTE(cfb): Having a flavor that sets the root size to 0 and having
+ # nova effectively ignore that size and use the size of the
+ # image is considered a feature at this time, not a bug.
+
+ if size is None:
+ return
+
+ if size and not base_size:
+ base_size = disk.get_disk_size(base)
+
+ if size < base_size:
+ msg = _('%(base)s virtual size %(base_size)s '
+ 'larger than flavor root disk size %(size)s')
+ LOG.error(msg % {'base': base,
+ 'base_size': base_size,
+ 'size': size})
+ raise exception.InstanceTypeDiskTooSmall()
+
def snapshot_create(self):
raise NotImplementedError()
@@ -234,7 +264,8 @@ def copy_raw_image(base, target, size):
#Generating image in place
prepare_template(target=self.path, *args, **kwargs)
else:
- prepare_template(target=base, *args, **kwargs)
+ prepare_template(target=base, max_size=size, *args, **kwargs)
+ self.verify_base_size(base, size)
if not os.path.exists(self.path):
with fileutils.remove_path_on_error(self.path):
copy_raw_image(base, self.path, size)
@@ -273,7 +304,9 @@ def copy_qcow2_image(base, target, size):
# Download the unmodified base image unless we already have a copy.
if not os.path.exists(base):
- prepare_template(target=base, *args, **kwargs)
+ prepare_template(target=base, max_size=size, *args, **kwargs)
+ else:
+ self.verify_base_size(base, size)
legacy_backing_size = None
legacy_base = base
@@ -299,17 +332,6 @@ def copy_qcow2_image(base, target, size):
libvirt_utils.copy_image(base, legacy_base)
disk.extend(legacy_base, legacy_backing_size, use_cow=True)
- # NOTE(cfb): Having a flavor that sets the root size to 0 and having
- # nova effectively ignore that size and use the size of the
- # image is considered a feature at this time, not a bug.
- disk_size = disk.get_disk_size(base)
- if size and size < disk_size:
- msg = _('%(base)s virtual size %(disk_size)s'
- 'larger than flavor root disk size %(size)s')
- LOG.error(msg % {'base': base,
- 'disk_size': disk_size,
- 'size': size})
- raise exception.InstanceTypeDiskTooSmall()
if not os.path.exists(self.path):
with fileutils.remove_path_on_error(self.path):
copy_qcow2_image(base, self.path, size)
@@ -367,6 +389,7 @@ def create_image(self, prepare_template, base, size, *args, **kwargs):
@utils.synchronized(base, external=True, lock_path=self.lock_path)
def create_lvm_image(base, size):
base_size = disk.get_disk_size(base)
+ self.verify_base_size(base, size, base_size=base_size)
resize = size > base_size
size = size if resize else base_size
libvirt_utils.create_lvm_image(self.vg, self.lv,
@@ -384,7 +407,7 @@ def create_lvm_image(base, size):
with self.remove_volume_on_error(self.path):
prepare_template(target=self.path, *args, **kwargs)
else:
- prepare_template(target=base, *args, **kwargs)
+ prepare_template(target=base, max_size=size, *args, **kwargs)
with self.remove_volume_on_error(self.path):
create_lvm_image(base, size)
@@ -514,7 +537,9 @@ def create_image(self, prepare_template, base, size, *args, **kwargs):
features = self.rbd.RBD_FEATURE_LAYERING
if not os.path.exists(base):
- prepare_template(target=base, *args, **kwargs)
+ prepare_template(target=base, max_size=size, *args, **kwargs)
+ else:
+ self.verify_base_size(base, size)
# keep using the command line import instead of librbd since it
# detects zeroes to preserve sparseness in the image
diff --git a/nova/virt/libvirt/utils.py b/nova/virt/libvirt/utils.py
index 66ff83e..d7c92b7 100644
--- a/nova/virt/libvirt/utils.py
+++ b/nova/virt/libvirt/utils.py
@@ -639,9 +639,10 @@ def get_fs_info(path):
'used': used}
-def fetch_image(context, target, image_id, user_id, project_id):
+def fetch_image(context, target, image_id, user_id, project_id, max_size=0):
"""Grab image."""
- images.fetch_to_raw(context, image_id, target, user_id, project_id)
+ images.fetch_to_raw(context, image_id, target, user_id, project_id,
+ max_size=max_size)
def get_instance_path(instance, forceold=False, relative=False):
--
1.8.4

View File

@ -1,111 +0,0 @@
From df2ea2e3acdede21b40d47b7adbeac04213d031b Mon Sep 17 00:00:00 2001
From: John Garbutt <john.garbutt@rackspace.com>
Date: Thu, 12 Sep 2013 18:11:49 +0100
Subject: [PATCH] xenapi: enforce filters after live-migration
Currently and network filters, including security groups, are
lost after a server has been live-migrated.
This partially fixes the issue by ensuring that security groups are
re-applied to the VM once it reached the destination, and been started.
This leaves a small amount of time during the live-migrate where the VM
is not protected. There is a further bug raised to close the rest of
this whole, but this helps keep the VM protected for the majority of the
time.
Fixes bug 1202266
(Cherry picked from commit: 5cced7a6dd32d231c606e25dbf762d199bf9cca7)
Change-Id: I66bc7af1c6da74e18dce47180af0cb6020ba2c1a
---
nova/tests/test_xenapi.py | 22 +++++++++++++++++++++-
nova/virt/xenapi/driver.py | 4 ++--
nova/virt/xenapi/vmops.py | 18 ++++++++++++++++++
3 files changed, 41 insertions(+), 3 deletions(-)
diff --git a/nova/tests/test_xenapi.py b/nova/tests/test_xenapi.py
index f7fb81d..d4c19a4 100644
--- a/nova/tests/test_xenapi.py
+++ b/nova/tests/test_xenapi.py
@@ -2723,7 +2723,27 @@ def test_post_live_migration_at_destination(self):
# ensure method is present
stubs.stubout_session(self.stubs, stubs.FakeSessionForVMTests)
self.conn = xenapi_conn.XenAPIDriver(fake.FakeVirtAPI(), False)
- self.conn.post_live_migration_at_destination(None, None, None, None)
+
+ fake_instance = "instance"
+ fake_network_info = "network_info"
+
+ def fake_fw(instance, network_info):
+ self.assertEquals(instance, fake_instance)
+ self.assertEquals(network_info, fake_network_info)
+ fake_fw.called += 1
+
+ fake_fw.called = 0
+ _vmops = self.conn._vmops
+ self.stubs.Set(_vmops.firewall_driver,
+ 'setup_basic_filtering', fake_fw)
+ self.stubs.Set(_vmops.firewall_driver,
+ 'prepare_instance_filter', fake_fw)
+ self.stubs.Set(_vmops.firewall_driver,
+ 'apply_instance_filter', fake_fw)
+
+ self.conn.post_live_migration_at_destination(None, fake_instance,
+ fake_network_info, None)
+ self.assertEqual(fake_fw.called, 3)
def test_check_can_live_migrate_destination_with_block_migration(self):
stubs.stubout_session(self.stubs, stubs.FakeSessionForVMTests)
diff --git a/nova/virt/xenapi/driver.py b/nova/virt/xenapi/driver.py
index 128f67f..564c587 100755
--- a/nova/virt/xenapi/driver.py
+++ b/nova/virt/xenapi/driver.py
@@ -1,4 +1,3 @@
-# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright (c) 2010 Citrix Systems, Inc.
# Copyright 2010 OpenStack Foundation
@@ -514,7 +513,8 @@ def post_live_migration_at_destination(self, ctxt, instance_ref,
:params : block_migration: if true, post operation of block_migraiton.
"""
# TODO(JohnGarbutt) look at moving/downloading ramdisk and kernel
- pass
+ self._vmops.post_live_migration_at_destination(ctxt, instance_ref,
+ network_info, block_device_info, block_device_info)
def unfilter_instance(self, instance_ref, network_info):
"""Removes security groups configured for an instance."""
diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py
index eccf3e0..ae5c697 100644
--- a/nova/virt/xenapi/vmops.py
+++ b/nova/virt/xenapi/vmops.py
@@ -1737,6 +1737,24 @@ def live_migrate(self, context, instance, destination_hostname,
recover_method(context, instance, destination_hostname,
block_migration)
+ def post_live_migration_at_destination(self, context, instance,
+ network_info, block_migration,
+ block_device_info):
+ # FIXME(johngarbutt): we should block all traffic until we have
+ # applied security groups, however this requires changes to XenServer
+ try:
+ self.firewall_driver.setup_basic_filtering(
+ instance, network_info)
+ except NotImplementedError:
+ # NOTE(salvatore-orlando): setup_basic_filtering might be
+ # empty or not implemented at all, as basic filter could
+ # be implemented with VIF rules created by xapi plugin
+ pass
+
+ self.firewall_driver.prepare_instance_filter(instance,
+ network_info)
+ self.firewall_driver.apply_instance_filter(instance, network_info)
+
def get_per_instance_usage(self):
"""Get usage info about each active instance."""
usage = {}
--
1.8.4

View File

@ -1,51 +0,0 @@
From 01de658210fd65171bfbf5450c93673b5ce0bd9e Mon Sep 17 00:00:00 2001
From: John Garbutt <john.garbutt@rackspace.com>
Date: Mon, 21 Oct 2013 19:34:43 +0100
Subject: [PATCH] xenapi: apply firewall rules in finish_migrate
When security groups were added, the rules were not re-applied to
servers that have been migrated to a new hypervisor.
This change ensures the firewall rules are applied as part of creating
the new VM in finish_migrate. This code follows a very similar pattern
to the code in spawn, and that is where the cut and paste code comes
from. This code duplication was removed in Havana.
Fixes bug 1073306
Change-Id: I6295a782df328a759e358fb82b76dd3f7bd4b39e
---
nova/virt/xenapi/vmops.py | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py
index eccf3e0..7a96ac2 100644
--- a/nova/virt/xenapi/vmops.py
+++ b/nova/virt/xenapi/vmops.py
@@ -277,8 +277,23 @@ def finish_migration(self, context, migration, instance, disk_info,
self._attach_mapped_block_devices(instance, block_device_info)
+ try:
+ self.firewall_driver.setup_basic_filtering(
+ instance, network_info)
+ except NotImplementedError:
+ # NOTE(salvatore-orlando): setup_basic_filtering might be
+ # empty or not implemented at all, as basic filter could
+ # be implemented with VIF rules created by xapi plugin
+ pass
+
+ self.firewall_driver.prepare_instance_filter(instance,
+ network_info)
+
# 5. Start VM
self._start(instance, vm_ref=vm_ref)
+
+ self.firewall_driver.apply_instance_filter(instance, network_info)
+
self._update_instance_progress(context, instance,
step=5,
total_steps=RESIZE_TOTAL_STEPS)
--
1.8.4

View File

@ -1,4 +0,0 @@
#Don't touch this unless you know what you are doing
PID_PATH=/run/nova
LOCKDIR_PATH=/var/lock/nova

View File

@ -1,36 +0,0 @@
From 74aa04e2ca7942cb1e1a86dcbaffeb72d260ccd7 Mon Sep 17 00:00:00 2001
From: Russell Bryant <rbryant@redhat.com>
Date: Wed, 1 May 2013 09:41:57 -0400
Subject: [PATCH] Remove insecure default for signing_dir option.
The sample api-paste.ini file included an insecure value for the
signing_dir option for the keystone authtoken middleware. Comment out
the option so that we just rely on the default behavior by default.
Fix bug 1174608.
Conflicts:
etc/nova/api-paste.ini
Change-Id: I6189788953d789c34456bbe150b8ed6ce6f68403
(cherry picked from commit 58d6879b1caaa750c39c8e452a0634c24ffef2ce)
---
etc/nova/api-paste.ini | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/etc/nova/api-paste.ini b/etc/nova/api-paste.ini
index 3970974..95307b2 100644
--- a/etc/nova/api-paste.ini
+++ b/etc/nova/api-paste.ini
@@ -124,4 +124,7 @@ auth_protocol = http
admin_tenant_name = %SERVICE_TENANT_NAME%
admin_user = %SERVICE_USER%
admin_password = %SERVICE_PASSWORD%
-signing_dir = /tmp/keystone-signing-nova
+# signing_dir is configurable, but the default behavior of the authtoken
+# middleware should be sufficient. It will create a temporary directory
+# in the home directory for the user the nova process is running as.
+#signing_dir = /var/lib/nova/keystone-signing
--
1.8.1.5

View File

@ -1,115 +0,0 @@
From 6740c4141ea1152529b82cbf6e5b808eaba912e7 Mon Sep 17 00:00:00 2001
From: Chet Burgess <cfb@metacloud.com>
Date: Thu, 9 May 2013 09:57:28 +0000
Subject: [PATCH] Check QCOW2 image size during root disk creation
glance can only tell us the size of the file, not the virtual
size of the QCOW2. As such we need to check the virtual size of
the image once its cached and ensure it's <= to the flavor's
root disk size.
Change-Id: I833467284126557eb598b8350a84e10c06292fa9
Fixes: bug 1177830
(cherry picked from commit 44a8aba1d5da87d54db48079103fdef946666d80)
---
nova/tests/test_imagebackend.py | 18 ++++++++++++++++++
nova/virt/libvirt/imagebackend.py | 12 ++++++++++++
2 files changed, 30 insertions(+)
diff --git a/nova/tests/test_imagebackend.py b/nova/tests/test_imagebackend.py
index f0bb718..da14f20 100644
--- a/nova/tests/test_imagebackend.py
+++ b/nova/tests/test_imagebackend.py
@@ -17,6 +17,7 @@
import os
+from nova import exception
from nova import flags
from nova import test
from nova.tests import fake_libvirt_utils
@@ -190,7 +191,10 @@ class Qcow2TestCase(_ImageTestCase):
fn = self.prepare_mocks()
fn(target=self.TEMPLATE_PATH)
self.mox.StubOutWithMock(os.path, 'exists')
+ self.mox.StubOutWithMock(imagebackend.disk, 'get_disk_size')
os.path.exists(self.QCOW2_BASE).AndReturn(False)
+ imagebackend.disk.get_disk_size(self.TEMPLATE_PATH
+ ).AndReturn(self.SIZE)
imagebackend.libvirt_utils.copy_image(self.TEMPLATE_PATH,
self.QCOW2_BASE)
imagebackend.disk.extend(self.QCOW2_BASE, self.SIZE)
@@ -203,11 +207,25 @@ class Qcow2TestCase(_ImageTestCase):
self.mox.VerifyAll()
+ def test_create_image_too_small(self):
+ self.mox.StubOutWithMock(imagebackend.disk, 'get_disk_size')
+ imagebackend.disk.get_disk_size(self.TEMPLATE_PATH
+ ).AndReturn(self.SIZE)
+ self.mox.ReplayAll()
+
+ image = self.image_class(self.INSTANCE, self.NAME)
+ self.assertRaises(exception.ImageTooLarge, image.create_image, None,
+ self.TEMPLATE_PATH, 1)
+ self.mox.VerifyAll()
+
def test_create_image_with_size_template_exists(self):
fn = self.prepare_mocks()
fn(target=self.TEMPLATE_PATH)
self.mox.StubOutWithMock(os.path, 'exists')
+ self.mox.StubOutWithMock(imagebackend.disk, 'get_disk_size')
os.path.exists(self.QCOW2_BASE).AndReturn(True)
+ imagebackend.disk.get_disk_size(self.TEMPLATE_PATH
+ ).AndReturn(self.SIZE)
imagebackend.libvirt_utils.create_cow_image(self.QCOW2_BASE,
self.PATH)
self.mox.ReplayAll()
diff --git a/nova/virt/libvirt/imagebackend.py b/nova/virt/libvirt/imagebackend.py
index 0f2f044..5e7023e 100644
--- a/nova/virt/libvirt/imagebackend.py
+++ b/nova/virt/libvirt/imagebackend.py
@@ -19,14 +19,17 @@ import abc
import contextlib
import os
+from nova import exception
from nova import flags
from nova.openstack.common import cfg
from nova.openstack.common import excutils
+from nova.openstack.common import log as logging
from nova import utils
from nova.virt.disk import api as disk
from nova.virt.libvirt import config
from nova.virt.libvirt import utils as libvirt_utils
+
__imagebackend_opts = [
cfg.StrOpt('libvirt_images_type',
default='default',
@@ -46,6 +49,8 @@ __imagebackend_opts = [
FLAGS = flags.FLAGS
FLAGS.register_opts(__imagebackend_opts)
+LOG = logging.getLogger(__name__)
+
class Image(object):
__metaclass__ = abc.ABCMeta
@@ -170,6 +175,13 @@ class Qcow2(Image):
disk.extend(qcow2_base, size)
libvirt_utils.create_cow_image(qcow2_base, target)
+ # NOTE(cfb): Having a flavor that sets the root size to 0 and having
+ # nova effectively ignore that size and use the size of the
+ # image is considered a feature at this time, not a bug.
+ if size and size < disk.get_disk_size(base):
+ LOG.error('%s virtual size larger than flavor root disk size %s' %
+ (base, size))
+ raise exception.ImageTooLarge()
prepare_template(target=base, *args, **kwargs)
with utils.remove_path_on_error(self.path):
copy_qcow2_image(base, self.path, size)
--
1.8.1.5

View File

@ -1,96 +0,0 @@
From a4fc0c800502338e4530cad910efb64a5483e1ea Mon Sep 17 00:00:00 2001
From: Chet Burgess <cfb@metacloud.com>
Date: Thu, 9 May 2013 09:57:28 +0000
Subject: [PATCH] Check QCOW2 image size during root disk creation
glance can only tell us the size of the file, not the virtual
size of the QCOW2. As such we need to check the virtual size of
the image once its cached and ensure it's <= to the flavor's
root disk size.
Change-Id: I833467284126557eb598b8350a84e10c06292fa9
Fixes: bug 1177830
(cherry picked from commit 44a8aba1d5da87d54db48079103fdef946666d80)
---
nova/tests/test_imagebackend.py | 21 +++++++++++++++++++++
nova/virt/libvirt/imagebackend.py | 8 ++++++++
2 files changed, 29 insertions(+)
diff --git a/nova/tests/test_imagebackend.py b/nova/tests/test_imagebackend.py
index d571bbf..4ec36da 100644
--- a/nova/tests/test_imagebackend.py
+++ b/nova/tests/test_imagebackend.py
@@ -20,6 +20,7 @@ import os
import fixtures
from oslo.config import cfg
+from nova import exception
from nova.openstack.common import uuidutils
from nova import test
from nova.tests import fake_libvirt_utils
@@ -253,9 +254,12 @@ class Qcow2TestCase(_ImageTestCase, test.TestCase):
fn = self.prepare_mocks()
fn(target=self.TEMPLATE_PATH)
self.mox.StubOutWithMock(os.path, 'exists')
+ self.mox.StubOutWithMock(imagebackend.disk, 'get_disk_size')
if self.OLD_STYLE_INSTANCE_PATH:
os.path.exists(self.OLD_STYLE_INSTANCE_PATH).AndReturn(False)
os.path.exists(self.TEMPLATE_PATH).AndReturn(False)
+ imagebackend.disk.get_disk_size(self.TEMPLATE_PATH
+ ).AndReturn(self.SIZE)
os.path.exists(self.PATH).AndReturn(False)
imagebackend.libvirt_utils.create_cow_image(self.TEMPLATE_PATH,
self.PATH)
@@ -267,6 +271,23 @@ class Qcow2TestCase(_ImageTestCase, test.TestCase):
self.mox.VerifyAll()
+ def test_create_image_too_small(self):
+ fn = self.prepare_mocks()
+ fn(target=self.TEMPLATE_PATH)
+ self.mox.StubOutWithMock(os.path, 'exists')
+ self.mox.StubOutWithMock(imagebackend.disk, 'get_disk_size')
+ if self.OLD_STYLE_INSTANCE_PATH:
+ os.path.exists(self.OLD_STYLE_INSTANCE_PATH).AndReturn(False)
+ os.path.exists(self.TEMPLATE_PATH).AndReturn(False)
+ imagebackend.disk.get_disk_size(self.TEMPLATE_PATH
+ ).AndReturn(self.SIZE)
+ self.mox.ReplayAll()
+
+ image = self.image_class(self.INSTANCE, self.NAME)
+ self.assertRaises(exception.ImageTooLarge, image.create_image, fn,
+ self.TEMPLATE_PATH, 1)
+ self.mox.VerifyAll()
+
class LvmTestCase(_ImageTestCase, test.TestCase):
VG = 'FakeVG'
diff --git a/nova/virt/libvirt/imagebackend.py b/nova/virt/libvirt/imagebackend.py
index b6b1b88..2ca71cc 100755
--- a/nova/virt/libvirt/imagebackend.py
+++ b/nova/virt/libvirt/imagebackend.py
@@ -21,6 +21,7 @@ import os
from oslo.config import cfg
+from nova import exception
from nova.openstack.common import excutils
from nova.openstack.common import fileutils
from nova.openstack.common import lockutils
@@ -255,6 +256,13 @@ class Qcow2(Image):
if not os.path.exists(base):
prepare_template(target=base, *args, **kwargs)
+ # NOTE(cfb): Having a flavor that sets the root size to 0 and having
+ # nova effectively ignore that size and use the size of the
+ # image is considered a feature at this time, not a bug.
+ if size and size < disk.get_disk_size(base):
+ LOG.error('%s virtual size larger than flavor root disk size %s' %
+ (base, size))
+ raise exception.ImageTooLarge()
if not os.path.exists(self.path):
with utils.remove_path_on_error(self.path):
copy_qcow2_image(base, self.path, size)
--
1.8.1.5

View File

@ -1,63 +0,0 @@
#!/sbin/runscript
# Copyright 1999-2013 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
BASENAME=$(echo $SVCNAME | cut -d '-' -f 1)
SERVERNAME=$(echo $SVCNAME | cut -d '-' -f 2)
depend() {
need net
}
checkconfig() {
if [ ! -r /etc/conf.d/$BASENAME ]; then
eerror "No nova conf.d file found: /etc/conf.d/$BASENAME)"
return 1
fi
return 0
}
start() {
checkconfig || return $?
. /etc/conf.d/$BASENAME
ebegin "Starting ${SVCNAME}"
if [ ! -d ${PID_PATH} ]; then
mkdir ${PID_PATH}
chown nova:root ${PID_PATH}
fi
if [ ! -d ${LOCKDIR_PATH} ]; then
mkdir ${LOCKDIR_PATH}
chown nova:root ${LOCKDIR_PATH}
fi
start-stop-daemon --start \
--quiet \
--user nova \
--pidfile "${PID_PATH}/${SVCNAME}.pid" \
--make-pidfile \
--background \
--exec /usr/bin/nova-${SERVERNAME} -- --config-file /etc/nova/nova.conf
eend $? "Failed to start ${SVCNAME}"
}
stop() {
checkconfig || return $?
. /etc/conf.d/$BASENAME
ebegin "Stopping ${SVCNAME}"
start-stop-daemon --stop \
--quiet \
--user nova \
--pidfile "${PID_PATH}/${SVCNAME}.pid" \
--exec /usr/bin/nova-${SERVERNAME} -- --config-file /etc/nova/nova.conf
eend $? "Failed to stop ${SVCNAME}"
}
#restart() {
#
#}

View File

@ -1,3 +0,0 @@
Defaults:nova !requiretty
nova ALL = (root) NOPASSWD: /usr/bin/nova-rootwrap

View File

@ -1,124 +0,0 @@
# Copyright 1999-2013 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Header: /var/cvsroot/gentoo-x86/sys-cluster/nova/nova-2013.1.3-r6.ebuild,v 1.2 2013/09/27 01:41:21 prometheanfire Exp $
EAPI=5
PYTHON_COMPAT=( python2_7 )
inherit distutils-r1 eutils multilib
DESCRIPTION="Nova is a cloud computing fabric controller (main part of an
IaaS system). It is written in Python."
HOMEPAGE="https://launchpad.net/nova"
SRC_URI="http://launchpad.net/${PN}/grizzly/${PV}/+download/${P}.tar.gz"
LICENSE="Apache-2.0"
SLOT="0"
KEYWORDS="~amd64 ~x86"
IUSE="+api +cert +compute +conductor +consoleauth +kvm +network +novncproxy +scheduler +spicehtml5proxy +xvpvncproxy xen sqlite mysql postgres"
REQUIRED_USE="|| ( mysql postgres sqlite )
|| ( kvm xen )"
DEPEND="dev-python/setuptools[${PYTHON_USEDEP}]
app-admin/sudo"
RDEPEND=">=dev-python/amqplib-0.6.1[${PYTHON_USEDEP}]
>=dev-python/anyjson-0.2.4[${PYTHON_USEDEP}]
>=dev-python/cheetah-2.4.4[${PYTHON_USEDEP}]
sqlite? ( >=dev-python/sqlalchemy-0.7.8[sqlite,${PYTHON_USEDEP}]
<dev-python/sqlalchemy-0.7.10[sqlite,${PYTHON_USEDEP}] )
mysql? ( >=dev-python/sqlalchemy-0.7.8[mysql,${PYTHON_USEDEP}]
<dev-python/sqlalchemy-0.7.10[mysql,${PYTHON_USEDEP}] )
postgres? ( >=dev-python/sqlalchemy-0.7.8[postgres,${PYTHON_USEDEP}]
<dev-python/sqlalchemy-0.7.10[postgres,${PYTHON_USEDEP}] )
dev-python/boto[${PYTHON_USEDEP}]
>=dev-python/lxml-2.3[${PYTHON_USEDEP}]
>=dev-python/eventlet-0.9.17[${PYTHON_USEDEP}]
>=dev-python/kombu-1.0.4-r1[${PYTHON_USEDEP}]
>=dev-python/routes-1.12.3-r1[${PYTHON_USEDEP}]
~dev-python/webob-1.2.3[${PYTHON_USEDEP}]
>=dev-python/greenlet-0.3.1[${PYTHON_USEDEP}]
>=dev-python/pastedeploy-1.5.0-r1[${PYTHON_USEDEP}]
dev-python/paste[${PYTHON_USEDEP}]
>=dev-python/sqlalchemy-migrate-0.7.2[${PYTHON_USEDEP}]
dev-python/netaddr[${PYTHON_USEDEP}]
>=dev-python/suds-0.4[${PYTHON_USEDEP}]
dev-python/paramiko[${PYTHON_USEDEP}]
dev-python/pyasn1[${PYTHON_USEDEP}]
>=dev-python/Babel-0.9.6[${PYTHON_USEDEP}]
>=dev-python/iso8601-0.1.4[${PYTHON_USEDEP}]
dev-python/httplib2[${PYTHON_USEDEP}]
>=dev-python/setuptools-git-0.4[${PYTHON_USEDEP}]
>=dev-python/python-cinderclient-1.0.1[${PYTHON_USEDEP}]
>=dev-python/python-glanceclient-0.5.0[${PYTHON_USEDEP}]
<dev-python/python-glanceclient-2[${PYTHON_USEDEP}]
>=dev-python/python-neutronclient-2.2.0[${PYTHON_USEDEP}]
<=dev-python/python-neutronclient-3.0.0[${PYTHON_USEDEP}]
>=dev-python/python-keystoneclient-0.2.0[${PYTHON_USEDEP}]
>=dev-python/stevedore-0.7[${PYTHON_USEDEP}]
<dev-python/websockify-0.4[${PYTHON_USEDEP}]
>=dev-python/oslo-config-1.1.0[${PYTHON_USEDEP}]
<dev-python/oslo-config-1.2.0[${PYTHON_USEDEP}]
virtual/python-argparse[${PYTHON_USEDEP}]
app-emulation/libvirt
novncproxy? ( www-apps/novnc )
kvm? ( app-emulation/qemu )
xen? ( app-emulation/xen
app-emulation/xen-tools )"
PATCHES=(
"${FILESDIR}/2013.1.3-CVE-2013-4261.patch"
"${FILESDIR}/2013.1.3-CVE-2013-4278.patch"
)
pkg_setup() {
enewgroup nova
enewuser nova -1 -1 /var/lib/nova nova
}
python_install() {
distutils-r1_python_install
newconfd "${FILESDIR}/nova-confd" "nova"
newinitd "${FILESDIR}/nova-initd" "nova"
use api && dosym /etc/init.d/nova /etc/init.d/nova-api
use cert && dosym /etc/init.d/nova /etc/init.d/nova-cert
use compute && dosym /etc/init.d/nova /etc/init.d/nova-compute
use conductor && dosym /etc/init.d/nova /etc/init.d/nova-conductor
use consoleauth && dosym /etc/init.d/nova /etc/init.d/nova-consoleauth
use network && dosym /etc/init.d/nova /etc/init.d/nova-network
use novncproxy &&dosym /etc/init.d/nova /etc/init.d/nova-novncproxy
use scheduler && dosym /etc/init.d/nova /etc/init.d/nova-scheduler
use spicehtml5proxy && dosym /etc/init.d/nova /etc/init.d/nova-spicehtml5proxy
use xvpvncproxy && dosym /etc/init.d/nova /etc/init.d/nova-xvpncproxy
diropts -m 0750
dodir /var/run/nova /var/log/nova /var/lock/nova
fowners nova:nova /var/log/nova /var/lock/nova /var/run/nova
diropts -m 0755
dodir /var/lib/nova/instances
fowners nova:nova /var/lib/nova/instances
keepdir /etc/nova
insinto /etc/nova
newins "etc/nova/nova.conf.sample" "nova.conf"
doins "etc/nova/api-paste.ini"
doins "etc/nova/logging_sample.conf"
doins "etc/nova/policy.json"
doins "etc/nova/rootwrap.conf"
insinto /etc/nova/rootwrap.d
doins "etc/nova/rootwrap.d/api-metadata.filters"
doins "etc/nova/rootwrap.d/compute.filters"
doins "etc/nova/rootwrap.d/network.filters"
#copy migration conf file (not coppied on install via setup.py script)
insinto /usr/$(get_libdir)/python2.7/site-packages/nova/db/sqlalchemy/migrate_repo/
doins "nova/db/sqlalchemy/migrate_repo/migrate.cfg"
#copy the CA cert dir (not coppied on install via setup.py script)
cp -R "${S}/nova/CA" "${D}/usr/$(get_libdir)/python2.7/site-packages/nova/" || die "isntalling CA files failed"
#add sudoers definitions for user nova
insinto /etc/sudoers.d/
doins "${FILESDIR}/nova-sudoers"
}

View File

@ -1,125 +0,0 @@
# Copyright 1999-2013 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Header: /var/cvsroot/gentoo-x86/sys-cluster/nova/nova-2013.2-r1.ebuild,v 1.1 2013/11/11 03:21:57 prometheanfire Exp $
EAPI=5
PYTHON_COMPAT=( python2_7 )
inherit distutils-r1 eutils multilib
DESCRIPTION="Nova is a cloud computing fabric controller (main part of an
IaaS system). It is written in Python."
HOMEPAGE="https://launchpad.net/nova"
SRC_URI="http://launchpad.net/${PN}/havana/${PV}/+download/${P}.tar.gz"
LICENSE="Apache-2.0"
SLOT="0"
KEYWORDS="~amd64 ~x86"
IUSE="+api +cert +compute +conductor +consoleauth +kvm +network +novncproxy +scheduler +spicehtml5proxy +xvpvncproxy sqlite mysql postgres xen"
REQUIRED_USE="|| ( mysql postgres sqlite )
|| ( kvm xen )"
DEPEND="dev-python/setuptools[${PYTHON_USEDEP}]
>=dev-python/pbr-0.5.21[${PYTHON_USEDEP}]
<dev-python/pbr-1.0[${PYTHON_USEDEP}]
app-admin/sudo"
RDEPEND="sqlite? ( >=dev-python/sqlalchemy-0.7.8[sqlite,${PYTHON_USEDEP}]
<dev-python/sqlalchemy-0.7.99[sqlite,${PYTHON_USEDEP}] )
mysql? ( >=dev-python/sqlalchemy-0.7.8[mysql,${PYTHON_USEDEP}]
<dev-python/sqlalchemy-0.7.99[mysql,${PYTHON_USEDEP}] )
postgres? ( >=dev-python/sqlalchemy-0.7.8[postgres,${PYTHON_USEDEP}]
<dev-python/sqlalchemy-0.7.99[postgres,${PYTHON_USEDEP}] )
>=dev-python/amqplib-0.6.1[${PYTHON_USEDEP}]
>=dev-python/anyjson-0.3.3[${PYTHON_USEDEP}]
virtual/python-argparse[${PYTHON_USEDEP}]
>=dev-python/boto-2.4.0[${PYTHON_USEDEP}]
!~dev-python/boto-2.13.0[${PYTHON_USEDEP}]
>=dev-python/eventlet-0.13.0[${PYTHON_USEDEP}]
dev-python/jinja[${PYTHON_USEDEP}]
>=dev-python/kombu-2.4.8[${PYTHON_USEDEP}]
>=dev-python/lxml-2.3[${PYTHON_USEDEP}]
>=dev-python/routes-1.12.3-r1[${PYTHON_USEDEP}]
>=dev-python/webob-1.2.3[${PYTHON_USEDEP}]
<dev-python/webob-1.3[${PYTHON_USEDEP}]
>=dev-python/greenlet-0.3.2[${PYTHON_USEDEP}]
>=dev-python/pastedeploy-1.5.0-r1[${PYTHON_USEDEP}]
dev-python/paste[${PYTHON_USEDEP}]
>=dev-python/sqlalchemy-migrate-0.7.2[${PYTHON_USEDEP}]
dev-python/netaddr[${PYTHON_USEDEP}]
>=dev-python/suds-0.4[${PYTHON_USEDEP}]
>=dev-python/paramiko-1.8.0[${PYTHON_USEDEP}]
dev-python/pyasn1[${PYTHON_USEDEP}]
>=dev-python/Babel-0.9.6[${PYTHON_USEDEP}]
>=dev-python/iso8601-0.1.4[${PYTHON_USEDEP}]
>=dev-python/python-cinderclient-1.0.5[${PYTHON_USEDEP}]
>=dev-python/python-neutronclient-2.3.0[${PYTHON_USEDEP}]
<=dev-python/python-neutronclient-3.0.0[${PYTHON_USEDEP}]
>=dev-python/python-glanceclient-0.9.0[${PYTHON_USEDEP}]
>=dev-python/python-keystoneclient-0.3.2[${PYTHON_USEDEP}]
>=dev-python/stevedore-0.10[${PYTHON_USEDEP}]
>=dev-python/websockify-0.5.1[${PYTHON_USEDEP}]
<dev-python/websockify-0.6[${PYTHON_USEDEP}]
>=dev-python/oslo-config-1.2.0[${PYTHON_USEDEP}]
app-emulation/libvirt
novncproxy? ( www-apps/novnc )
sys-apps/iproute2
net-misc/openvswitch
kvm? ( app-emulation/qemu )
xen? ( app-emulation/xen
app-emulation/xen-tools )"
PATCHES=(
)
pkg_setup() {
enewgroup nova
enewuser nova -1 -1 /var/lib/nova nova
}
python_install() {
distutils-r1_python_install
newconfd "${FILESDIR}/nova-confd" "nova"
newinitd "${FILESDIR}/nova-initd" "nova"
use api && dosym /etc/init.d/nova /etc/init.d/nova-api
use cert && dosym /etc/init.d/nova /etc/init.d/nova-cert
use compute && dosym /etc/init.d/nova /etc/init.d/nova-compute
use conductor && dosym /etc/init.d/nova /etc/init.d/nova-conductor
use consoleauth && dosym /etc/init.d/nova /etc/init.d/nova-consoleauth
use network && dosym /etc/init.d/nova /etc/init.d/nova-network
use novncproxy &&dosym /etc/init.d/nova /etc/init.d/nova-novncproxy
use scheduler && dosym /etc/init.d/nova /etc/init.d/nova-scheduler
use spicehtml5proxy && dosym /etc/init.d/nova /etc/init.d/nova-spicehtml5proxy
use xvpvncproxy && dosym /etc/init.d/nova /etc/init.d/nova-xvpncproxy
diropts -m 0750
dodir /var/run/nova /var/log/nova /var/lock/nova
fowners nova:nova /var/log/nova /var/lock/nova /var/run/nova
diropts -m 0755
dodir /var/lib/nova/instances
fowners nova:nova /var/lib/nova/instances
keepdir /etc/nova
insinto /etc/nova
newins "etc/nova/nova.conf.sample" "nova.conf"
doins "etc/nova/api-paste.ini"
doins "etc/nova/logging_sample.conf"
doins "etc/nova/policy.json"
doins "etc/nova/rootwrap.conf"
insinto /etc/nova/rootwrap.d
doins "etc/nova/rootwrap.d/api-metadata.filters"
doins "etc/nova/rootwrap.d/compute.filters"
doins "etc/nova/rootwrap.d/network.filters"
#copy migration conf file (not coppied on install via setup.py script)
insinto /usr/$(get_libdir)/python2.7/site-packages/nova/db/sqlalchemy/migrate_repo/
doins "nova/db/sqlalchemy/migrate_repo/migrate.cfg"
#copy the CA cert dir (not coppied on install via setup.py script)
cp -R "${S}/nova/CA" "${D}/usr/$(get_libdir)/python2.7/site-packages/nova/" || die "isntalling CA files failed"
#add sudoers definitions for user nova
insinto /etc/sudoers.d/
doins "${FILESDIR}/nova-sudoers"
}

View File

@ -1,128 +0,0 @@
# Copyright 1999-2013 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Header: /var/cvsroot/gentoo-x86/sys-cluster/nova/nova-2013.2-r2.ebuild,v 1.1 2013/11/17 22:35:55 prometheanfire Exp $
EAPI=5
PYTHON_COMPAT=( python2_7 )
inherit distutils-r1 eutils multilib
DESCRIPTION="Nova is a cloud computing fabric controller (main part of an
IaaS system). It is written in Python."
HOMEPAGE="https://launchpad.net/nova"
SRC_URI="http://launchpad.net/${PN}/havana/${PV}/+download/${P}.tar.gz"
LICENSE="Apache-2.0"
SLOT="0"
KEYWORDS="~amd64 ~x86"
IUSE="+api +cert +compute +conductor +consoleauth +kvm +network +novncproxy +scheduler +spicehtml5proxy +xvpvncproxy sqlite mysql postgres xen"
REQUIRED_USE="|| ( mysql postgres sqlite )
|| ( kvm xen )"
DEPEND="dev-python/setuptools[${PYTHON_USEDEP}]
>=dev-python/pbr-0.5.21[${PYTHON_USEDEP}]
<dev-python/pbr-1.0[${PYTHON_USEDEP}]
app-admin/sudo"
RDEPEND="sqlite? ( >=dev-python/sqlalchemy-0.7.8[sqlite,${PYTHON_USEDEP}]
<dev-python/sqlalchemy-0.7.99[sqlite,${PYTHON_USEDEP}] )
mysql? ( >=dev-python/sqlalchemy-0.7.8[mysql,${PYTHON_USEDEP}]
<dev-python/sqlalchemy-0.7.99[mysql,${PYTHON_USEDEP}] )
postgres? ( >=dev-python/sqlalchemy-0.7.8[postgres,${PYTHON_USEDEP}]
<dev-python/sqlalchemy-0.7.99[postgres,${PYTHON_USEDEP}] )
>=dev-python/amqplib-0.6.1[${PYTHON_USEDEP}]
>=dev-python/anyjson-0.3.3[${PYTHON_USEDEP}]
virtual/python-argparse[${PYTHON_USEDEP}]
>=dev-python/boto-2.4.0[${PYTHON_USEDEP}]
!~dev-python/boto-2.13.0[${PYTHON_USEDEP}]
>=dev-python/eventlet-0.13.0[${PYTHON_USEDEP}]
dev-python/jinja[${PYTHON_USEDEP}]
>=dev-python/kombu-2.4.8[${PYTHON_USEDEP}]
>=dev-python/lxml-2.3[${PYTHON_USEDEP}]
>=dev-python/routes-1.12.3-r1[${PYTHON_USEDEP}]
>=dev-python/webob-1.2.3[${PYTHON_USEDEP}]
<dev-python/webob-1.3[${PYTHON_USEDEP}]
>=dev-python/greenlet-0.3.2[${PYTHON_USEDEP}]
>=dev-python/pastedeploy-1.5.0-r1[${PYTHON_USEDEP}]
dev-python/paste[${PYTHON_USEDEP}]
>=dev-python/sqlalchemy-migrate-0.7.2[${PYTHON_USEDEP}]
dev-python/netaddr[${PYTHON_USEDEP}]
>=dev-python/suds-0.4[${PYTHON_USEDEP}]
>=dev-python/paramiko-1.8.0[${PYTHON_USEDEP}]
dev-python/pyasn1[${PYTHON_USEDEP}]
>=dev-python/Babel-0.9.6[${PYTHON_USEDEP}]
>=dev-python/iso8601-0.1.4[${PYTHON_USEDEP}]
>=dev-python/python-cinderclient-1.0.5[${PYTHON_USEDEP}]
>=dev-python/python-neutronclient-2.3.0[${PYTHON_USEDEP}]
<=dev-python/python-neutronclient-3.0.0[${PYTHON_USEDEP}]
>=dev-python/python-glanceclient-0.9.0[${PYTHON_USEDEP}]
>=dev-python/python-keystoneclient-0.3.2[${PYTHON_USEDEP}]
>=dev-python/stevedore-0.10[${PYTHON_USEDEP}]
>=dev-python/websockify-0.5.1[${PYTHON_USEDEP}]
<dev-python/websockify-0.6[${PYTHON_USEDEP}]
>=dev-python/oslo-config-1.2.0[${PYTHON_USEDEP}]
app-emulation/libvirt
novncproxy? ( www-apps/novnc )
sys-apps/iproute2
net-misc/openvswitch
sys-fs/sysfsutils
sys-fs/multipath-tools
kvm? ( app-emulation/qemu )
xen? ( app-emulation/xen
app-emulation/xen-tools )"
PATCHES=(
"${FILESDIR}/CVE-2013-4463_4469-havana.patch"
)
pkg_setup() {
enewgroup nova
enewuser nova -1 -1 /var/lib/nova nova
}
python_install() {
distutils-r1_python_install
newconfd "${FILESDIR}/nova-confd" "nova"
newinitd "${FILESDIR}/nova-initd" "nova"
use api && dosym /etc/init.d/nova /etc/init.d/nova-api
use cert && dosym /etc/init.d/nova /etc/init.d/nova-cert
use compute && dosym /etc/init.d/nova /etc/init.d/nova-compute
use conductor && dosym /etc/init.d/nova /etc/init.d/nova-conductor
use consoleauth && dosym /etc/init.d/nova /etc/init.d/nova-consoleauth
use network && dosym /etc/init.d/nova /etc/init.d/nova-network
use novncproxy &&dosym /etc/init.d/nova /etc/init.d/nova-novncproxy
use scheduler && dosym /etc/init.d/nova /etc/init.d/nova-scheduler
use spicehtml5proxy && dosym /etc/init.d/nova /etc/init.d/nova-spicehtml5proxy
use xvpvncproxy && dosym /etc/init.d/nova /etc/init.d/nova-xvpncproxy
diropts -m 0750
dodir /var/run/nova /var/log/nova /var/lock/nova
fowners nova:nova /var/log/nova /var/lock/nova /var/run/nova
diropts -m 0755
dodir /var/lib/nova/instances
fowners nova:nova /var/lib/nova/instances
keepdir /etc/nova
insinto /etc/nova
newins "etc/nova/nova.conf.sample" "nova.conf"
doins "etc/nova/api-paste.ini"
doins "etc/nova/logging_sample.conf"
doins "etc/nova/policy.json"
doins "etc/nova/rootwrap.conf"
insinto /etc/nova/rootwrap.d
doins "etc/nova/rootwrap.d/api-metadata.filters"
doins "etc/nova/rootwrap.d/compute.filters"
doins "etc/nova/rootwrap.d/network.filters"
#copy migration conf file (not coppied on install via setup.py script)
insinto /usr/$(get_libdir)/python2.7/site-packages/nova/db/sqlalchemy/migrate_repo/
doins "nova/db/sqlalchemy/migrate_repo/migrate.cfg"
#copy the CA cert dir (not coppied on install via setup.py script)
cp -R "${S}/nova/CA" "${D}/usr/$(get_libdir)/python2.7/site-packages/nova/" || die "isntalling CA files failed"
#add sudoers definitions for user nova
insinto /etc/sudoers.d/
doins "${FILESDIR}/nova-sudoers"
}

View File

@ -1,123 +0,0 @@
# Copyright 1999-2013 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Header: /var/cvsroot/gentoo-x86/sys-cluster/nova/nova-2013.2.ebuild,v 1.1 2013/10/29 06:15:52 prometheanfire Exp $
EAPI=5
PYTHON_COMPAT=( python2_7 )
inherit distutils-r1 eutils multilib
DESCRIPTION="Nova is a cloud computing fabric controller (main part of an
IaaS system). It is written in Python."
HOMEPAGE="https://launchpad.net/nova"
SRC_URI="http://launchpad.net/${PN}/havana/${PV}/+download/${P}.tar.gz"
LICENSE="Apache-2.0"
SLOT="0"
KEYWORDS="~amd64 ~x86"
IUSE="+api +cert +compute +conductor +consoleauth +kvm +network +novncproxy +scheduler +spicehtml5proxy +xvpvncproxy sqlite mysql postgres xen"
REQUIRED_USE="|| ( mysql postgres sqlite )
|| ( kvm xen )"
DEPEND="dev-python/setuptools[${PYTHON_USEDEP}]
>=dev-python/pbr-0.5.21[${PYTHON_USEDEP}]
<dev-python/pbr-1.0[${PYTHON_USEDEP}]
app-admin/sudo"
RDEPEND="sqlite? ( >=dev-python/sqlalchemy-0.7.8[sqlite,${PYTHON_USEDEP}]
<dev-python/sqlalchemy-0.7.99[sqlite,${PYTHON_USEDEP}] )
mysql? ( >=dev-python/sqlalchemy-0.7.8[mysql,${PYTHON_USEDEP}]
<dev-python/sqlalchemy-0.7.99[mysql,${PYTHON_USEDEP}] )
postgres? ( >=dev-python/sqlalchemy-0.7.8[postgres,${PYTHON_USEDEP}]
<dev-python/sqlalchemy-0.7.99[postgres,${PYTHON_USEDEP}] )
>=dev-python/amqplib-0.6.1[${PYTHON_USEDEP}]
>=dev-python/anyjson-0.3.3[${PYTHON_USEDEP}]
virtual/python-argparse[${PYTHON_USEDEP}]
>=dev-python/boto-2.4.0[${PYTHON_USEDEP}]
!~dev-python/boto-2.13.0[${PYTHON_USEDEP}]
>=dev-python/eventlet-0.13.0[${PYTHON_USEDEP}]
dev-python/jinja[${PYTHON_USEDEP}]
>=dev-python/kombu-2.4.8[${PYTHON_USEDEP}]
>=dev-python/lxml-2.3[${PYTHON_USEDEP}]
>=dev-python/routes-1.12.3-r1[${PYTHON_USEDEP}]
>=dev-python/webob-1.2.3[${PYTHON_USEDEP}]
<dev-python/webob-1.3[${PYTHON_USEDEP}]
>=dev-python/greenlet-0.3.2[${PYTHON_USEDEP}]
>=dev-python/pastedeploy-1.5.0-r1[${PYTHON_USEDEP}]
dev-python/paste[${PYTHON_USEDEP}]
>=dev-python/sqlalchemy-migrate-0.7.2[${PYTHON_USEDEP}]
dev-python/netaddr[${PYTHON_USEDEP}]
>=dev-python/suds-0.4[${PYTHON_USEDEP}]
>=dev-python/paramiko-1.8.0[${PYTHON_USEDEP}]
dev-python/pyasn1[${PYTHON_USEDEP}]
>=dev-python/Babel-0.9.6[${PYTHON_USEDEP}]
>=dev-python/iso8601-0.1.4[${PYTHON_USEDEP}]
>=dev-python/python-cinderclient-1.0.5[${PYTHON_USEDEP}]
>=dev-python/python-neutronclient-2.3.0[${PYTHON_USEDEP}]
<=dev-python/python-neutronclient-3.0.0[${PYTHON_USEDEP}]
>=dev-python/python-glanceclient-0.9.0[${PYTHON_USEDEP}]
>=dev-python/python-keystoneclient-0.3.2[${PYTHON_USEDEP}]
>=dev-python/stevedore-0.10[${PYTHON_USEDEP}]
>=dev-python/websockify-0.5.1[${PYTHON_USEDEP}]
<dev-python/websockify-0.6[${PYTHON_USEDEP}]
>=dev-python/oslo-config-1.2.0[${PYTHON_USEDEP}]
app-emulation/libvirt
novncproxy? ( www-apps/novnc )
kvm? ( app-emulation/qemu )
xen? ( app-emulation/xen
app-emulation/xen-tools )"
PATCHES=(
)
pkg_setup() {
enewgroup nova
enewuser nova -1 -1 /var/lib/nova nova
}
python_install() {
distutils-r1_python_install
newconfd "${FILESDIR}/nova-confd" "nova"
newinitd "${FILESDIR}/nova-initd" "nova"
use api && dosym /etc/init.d/nova /etc/init.d/nova-api
use cert && dosym /etc/init.d/nova /etc/init.d/nova-cert
use compute && dosym /etc/init.d/nova /etc/init.d/nova-compute
use conductor && dosym /etc/init.d/nova /etc/init.d/nova-conductor
use consoleauth && dosym /etc/init.d/nova /etc/init.d/nova-consoleauth
use network && dosym /etc/init.d/nova /etc/init.d/nova-network
use novncproxy &&dosym /etc/init.d/nova /etc/init.d/nova-novncproxy
use scheduler && dosym /etc/init.d/nova /etc/init.d/nova-scheduler
use spicehtml5proxy && dosym /etc/init.d/nova /etc/init.d/nova-spicehtml5proxy
use xvpvncproxy && dosym /etc/init.d/nova /etc/init.d/nova-xvpncproxy
diropts -m 0750
dodir /var/run/nova /var/log/nova /var/lock/nova
fowners nova:nova /var/log/nova /var/lock/nova /var/run/nova
diropts -m 0755
dodir /var/lib/nova/instances
fowners nova:nova /var/lib/nova/instances
keepdir /etc/nova
insinto /etc/nova
newins "etc/nova/nova.conf.sample" "nova.conf"
doins "etc/nova/api-paste.ini"
doins "etc/nova/logging_sample.conf"
doins "etc/nova/policy.json"
doins "etc/nova/rootwrap.conf"
insinto /etc/nova/rootwrap.d
doins "etc/nova/rootwrap.d/api-metadata.filters"
doins "etc/nova/rootwrap.d/compute.filters"
doins "etc/nova/rootwrap.d/network.filters"
#copy migration conf file (not coppied on install via setup.py script)
insinto /usr/$(get_libdir)/python2.7/site-packages/nova/db/sqlalchemy/migrate_repo/
doins "nova/db/sqlalchemy/migrate_repo/migrate.cfg"
#copy the CA cert dir (not coppied on install via setup.py script)
cp -R "${S}/nova/CA" "${D}/usr/$(get_libdir)/python2.7/site-packages/nova/" || die "isntalling CA files failed"
#add sudoers definitions for user nova
insinto /etc/sudoers.d/
doins "${FILESDIR}/nova-sudoers"
}

View File

@ -1,6 +1,6 @@
# Copyright 1999-2014 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Header: /var/cvsroot/gentoo-x86/sys-cluster/nova/nova-2014.1-r2.ebuild,v 1.3 2014/06/09 04:56:40 prometheanfire Exp $
# $Header: /var/cvsroot/gentoo-x86/sys-cluster/nova/nova-2014.1.1.ebuild,v 1.1 2014/06/16 03:35:39 prometheanfire Exp $
EAPI=5
PYTHON_COMPAT=( python2_7 )
@ -76,8 +76,6 @@ RDEPEND="sqlite? ( >=dev-python/sqlalchemy-0.7.8[sqlite,${PYTHON_USEDEP}]
app-emulation/xen-tools )"
PATCHES=(
"${FILESDIR}/2014.1-CVE-2014-2573-1.patch"
"${FILESDIR}/2014.1-CVE-2014-2573-2.patch"
)
pkg_setup() {