nova-2014.1.1 added
This commit is contained in:
parent
08a4cd6547
commit
5f1a154968
|
@ -1 +0,0 @@
|
||||||
DIST quantum-2013.1.3.tar.gz 1174471 SHA256 79e60ec1aef800da3a4e1841909cdd8b2cf645979d08f27bc481957c7944e93d SHA512 cba87ff6b6695bc6d09b60bea86e9fb42fcc9d5358dd3c06d1a6880f9654d9155d881485b49cec05aaae9428fdafa7d2d4061b15b9c02a69de49475b0cc064b8 WHIRLPOOL deaf4a9ae8df78580a7418d65a00850c57f34cedbe40e38f4832849d2e8ae8f4eadb06d37be039c1c2a16e8893f891763888d72e3e174dac96df56e733ad8bb7
|
|
|
@ -1,2 +0,0 @@
|
||||||
#Don't touch this unless you know what you are doing
|
|
||||||
PID_PATH=/run/quantum
|
|
|
@ -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() {
|
|
||||||
#
|
|
||||||
#}
|
|
|
@ -1,4 +0,0 @@
|
||||||
Defaults:neutron !requiretty
|
|
||||||
|
|
||||||
neutron ALL = (root) NOPASSWD: /usr/bin/quantum-rootwrap
|
|
||||||
|
|
|
@ -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
|
|
||||||
}
|
|
|
@ -1,3 +1 @@
|
||||||
DIST nova-2013.1.3.tar.gz 5780115 SHA256 f7c25186920daccb16867c5fd272318beb8cc076e5a55f79b5906618ef2724f4 SHA512 3de29f1cf0789285c7600796588058f056d4196138584bb5ec13a0ea034bbc0569d116a668db67022e302b29995af5960093af1103996269d73dccd62a5dd238 WHIRLPOOL ebb06733a710764004f99da2a69d5479cdd50e35da6d0992233ab9ca0a7a5854a678c5d184d40f97a66fa3abd052b1e6de4629963dd58292f677707997e56239
|
DIST nova-2014.1.1.tar.gz 7979809 SHA256 3cb3b48c72c39e7637d6016039d353ad33de69bcd6ed04dbfdb0db9313eb9a5b SHA512 6f7b449e09e796c483d93399af24c2cd77042776e1c4d36c3bcd34814b42a252151542b684785ba6c1b28bc0b302cc15f5057da7f90884c73ff6b11ec748323e WHIRLPOOL 0d959b4655d6010825b0ef73b6ce983cd6a0679f5aa5d41ebfbddce26e74d402d9d571c65d26f71e60bb627fc9d4d924d1e4622c1d96d73e3b484f1c68502df7
|
||||||
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
|
|
||||||
|
|
|
@ -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
|
|
||||||
|
|
|
@ -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
|
|
||||||
|
|
|
@ -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
|
|
||||||
|
|
||||||
|
|
|
@ -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
|
|
||||||
|
|
|
@ -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
|
|
||||||
|
|
||||||
|
|
|
@ -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
|
|
||||||
|
|
|
@ -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
|
|
||||||
|
|
|
@ -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
|
|
||||||
|
|
|
@ -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
|
|
||||||
|
|
|
@ -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
|
|
||||||
|
|
|
@ -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
|
|
||||||
|
|
|
@ -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
|
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
#Don't touch this unless you know what you are doing
|
|
||||||
PID_PATH=/run/nova
|
|
||||||
LOCKDIR_PATH=/var/lock/nova
|
|
||||||
|
|
|
@ -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
|
|
||||||
|
|
|
@ -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
|
|
||||||
|
|
|
@ -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
|
|
||||||
|
|
|
@ -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() {
|
|
||||||
#
|
|
||||||
#}
|
|
|
@ -1,3 +0,0 @@
|
||||||
Defaults:nova !requiretty
|
|
||||||
|
|
||||||
nova ALL = (root) NOPASSWD: /usr/bin/nova-rootwrap
|
|
|
@ -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"
|
|
||||||
}
|
|
|
@ -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"
|
|
||||||
}
|
|
|
@ -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"
|
|
||||||
}
|
|
|
@ -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"
|
|
||||||
}
|
|
|
@ -1,6 +1,6 @@
|
||||||
# Copyright 1999-2014 Gentoo Foundation
|
# Copyright 1999-2014 Gentoo Foundation
|
||||||
# Distributed under the terms of the GNU General Public License v2
|
# 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
|
EAPI=5
|
||||||
PYTHON_COMPAT=( python2_7 )
|
PYTHON_COMPAT=( python2_7 )
|
||||||
|
@ -76,8 +76,6 @@ RDEPEND="sqlite? ( >=dev-python/sqlalchemy-0.7.8[sqlite,${PYTHON_USEDEP}]
|
||||||
app-emulation/xen-tools )"
|
app-emulation/xen-tools )"
|
||||||
|
|
||||||
PATCHES=(
|
PATCHES=(
|
||||||
"${FILESDIR}/2014.1-CVE-2014-2573-1.patch"
|
|
||||||
"${FILESDIR}/2014.1-CVE-2014-2573-2.patch"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
pkg_setup() {
|
pkg_setup() {
|
Loading…
Reference in New Issue