nova-2013.1.3-r6 added

This commit is contained in:
Kolan Sh 2013-09-30 23:54:05 +04:00
parent 7dd9e004bc
commit b9ebebc297
14 changed files with 1245 additions and 0 deletions

View File

@ -0,0 +1 @@
DIST nova-2013.1.3.tar.gz 5780115 SHA256 f7c25186920daccb16867c5fd272318beb8cc076e5a55f79b5906618ef2724f4 SHA512 3de29f1cf0789285c7600796588058f056d4196138584bb5ec13a0ea034bbc0569d116a668db67022e302b29995af5960093af1103996269d73dccd62a5dd238 WHIRLPOOL ebb06733a710764004f99da2a69d5479cdd50e35da6d0992233ab9ca0a7a5854a678c5d184d40f97a66fa3abd052b1e6de4629963dd58292f677707997e56239

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,124 @@
# 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"
}