[openstack-nova/el6] Update from upstream stable pending patches

Pádraig Brady pbrady at fedoraproject.org
Mon Jun 11 14:03:35 UTC 2012


commit e671fd6d60cee8075c6726d3c41f115c51c75a29
Author: Pádraig Brady <P at draigBrady.com>
Date:   Mon Jun 11 14:50:18 2012 +0100

    Update from upstream stable pending patches
    
    (cherry picked from commit 2a65c3b)
    
    Conflicts:
    
    	openstack-nova.spec

 ...-Only-invoke-.lower-on-non-None-protocols.patch |   63 ++++++++
 ...e-a-utf8-version-of-the-dns_domains-table.patch |  153 ++++++++++++++++++
 0038-Don-t-query-nova-network-on-startup.patch     |  165 ++++++++++++++++++++
 openstack-nova.spec                                |   13 ++-
 4 files changed, 393 insertions(+), 1 deletions(-)
---
diff --git a/0036-Only-invoke-.lower-on-non-None-protocols.patch b/0036-Only-invoke-.lower-on-non-None-protocols.patch
new file mode 100644
index 0000000..83a92c4
--- /dev/null
+++ b/0036-Only-invoke-.lower-on-non-None-protocols.patch
@@ -0,0 +1,63 @@
+From b6b82ea423f9aaa2c2791f258122f6b98d66e5e8 Mon Sep 17 00:00:00 2001
+From: Soren Hansen <sorhanse at cisco.com>
+Date: Mon, 11 Jun 2012 09:23:33 +0200
+Subject: [PATCH] Only invoke .lower() on non-None protocols
+
+When using source group based security group rules (rather than CIDR
+based ones), it's permissible to not set a protocol and port. However,
+Nova would always try to convert the protocol to lower case, which would
+fail if the protocol wasn't set.
+
+Fixes bug 1010514
+
+Change-Id: I9b1519a52ececd16a497acebfe022508cbe96126
+---
+ .mailmap                   |    1 +
+ nova/tests/test_libvirt.py |    7 +++++++
+ nova/virt/firewall.py      |    6 +++++-
+ 3 files changed, 13 insertions(+), 1 deletions(-)
+
+diff --git a/.mailmap b/.mailmap
+index 1537739..38783c9 100644
+diff --git a/nova/tests/test_libvirt.py b/nova/tests/test_libvirt.py
+index ac8cdca..af30051 100644
+--- a/nova/tests/test_libvirt.py
++++ b/nova/tests/test_libvirt.py
+@@ -1718,6 +1718,10 @@ class IptablesFirewallTestCase(test.TestCase):
+                                        'to_port': 81,
+                                        'group_id': src_secgroup['id']})
+ 
++        db.security_group_rule_create(admin_ctxt,
++                                      {'parent_group_id': secgroup['id'],
++                                       'group_id': src_secgroup['id']})
++
+         db.instance_add_security_group(admin_ctxt, instance_ref['uuid'],
+                                        secgroup['id'])
+         db.instance_add_security_group(admin_ctxt, src_instance_ref['uuid'],
+@@ -1798,6 +1802,9 @@ class IptablesFirewallTestCase(test.TestCase):
+                                '--dports 80:81 -s %s' % ip['address'])
+             self.assertTrue(len(filter(regex.match, self.out_rules)) > 0,
+                             "TCP port 80/81 acceptance rule wasn't added")
++            regex = re.compile('-A .* -j ACCEPT -s %s' % ip['address'])
++            self.assertTrue(len(filter(regex.match, self.out_rules)) > 0,
++                            "Protocol/port-less acceptance rule wasn't added")
+ 
+         regex = re.compile('-A .* -j ACCEPT -p tcp '
+                            '-m multiport --dports 80:81 -s 192.168.10.0/24')
+diff --git a/nova/virt/firewall.py b/nova/virt/firewall.py
+index a41ece6..f0f1594 100644
+--- a/nova/virt/firewall.py
++++ b/nova/virt/firewall.py
+@@ -300,7 +300,11 @@ class IptablesFirewallDriver(FirewallDriver):
+                 else:
+                     fw_rules = ipv6_rules
+ 
+-                protocol = rule.protocol.lower()
++                protocol = rule.protocol
++
++                if protocol:
++                    protocol = rule.protocol.lower()
++
+                 if version == 6 and protocol == 'icmp':
+                     protocol = 'icmpv6'
+ 
diff --git a/0037-Create-a-utf8-version-of-the-dns_domains-table.patch b/0037-Create-a-utf8-version-of-the-dns_domains-table.patch
new file mode 100644
index 0000000..18614cb
--- /dev/null
+++ b/0037-Create-a-utf8-version-of-the-dns_domains-table.patch
@@ -0,0 +1,153 @@
+From abc01f2430b592388fe3bb1818f6dd13d8d02b0e Mon Sep 17 00:00:00 2001
+From: Dan Prince <dprince at redhat.com>
+Date: Fri, 8 Jun 2012 16:59:27 -0400
+Subject: [PATCH] Create a utf8 version of the dns_domains table.
+
+The old dns_domains table was encoded in the 'latin1'
+charset and has its primary key length set to 512.
+This is too long to be a valid pkey in a proper 'utf8' encoded
+table and seems to cause a slew of errors like:
+
+1) Dumping a database with mysqldump and trying to import it fails
+because this table is latin1 but fkeys to utf8 tables (projects).
+
+2) Trying to alter the old dns_domains table fails with errors
+like:
+mysql> ALTER TABLE dns_domains DROP PRIMARY KEY;
+ERROR 1025 (HY000): Error on rename of './nova/#sql-6cf_855'....
+
+This patch creates an Essex fix that re-creates the dns_domains
+table with a shorter 'domain' column which works with the utf8
+charset. This database upgrade will run on MySQL databases only
+which have a dns_domains table with a domain column length of
+VARCHAR(512).
+
+Fixes LP Bug #993663 on Essex.
+
+Change-Id: I97888fbc18ebfc0e25c9ba31160588c9cdf5c448
+---
+ nova/db/sqlalchemy/fix_dns_domains.py |   91 +++++++++++++++++++++++++++++++++
+ nova/db/sqlalchemy/migration.py       |    5 ++-
+ 2 files changed, 95 insertions(+), 1 deletions(-)
+ create mode 100644 nova/db/sqlalchemy/fix_dns_domains.py
+
+diff --git a/nova/db/sqlalchemy/fix_dns_domains.py b/nova/db/sqlalchemy/fix_dns_domains.py
+new file mode 100644
+index 0000000..9fa8ffe
+--- /dev/null
++++ b/nova/db/sqlalchemy/fix_dns_domains.py
+@@ -0,0 +1,91 @@
++# vim: tabstop=4 shiftwidth=4 softtabstop=4
++
++# Copyright (c) 2012 Red Hat, Inc.
++# All Rights Reserved.
++#
++#    Licensed under the Apache License, Version 2.0 (the "License"); you may
++#    not use this file except in compliance with the License. You may obtain
++#    a copy of the License at
++#
++#         http://www.apache.org/licenses/LICENSE-2.0
++#
++#    Unless required by applicable law or agreed to in writing, software
++#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
++#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
++#    License for the specific language governing permissions and limitations
++#    under the License.
++
++from sqlalchemy import Boolean, Column, DateTime, ForeignKey
++from sqlalchemy import MetaData, String, Table
++
++from nova import log as logging
++
++LOG = logging.getLogger(__name__)
++
++
++def run(migrate_engine):
++    meta = MetaData()
++    meta.bind = migrate_engine
++
++    # NOTE(dprince): The old dns_domains table is in the 'latin1'
++    # charset and had its primary key length set to 512.
++    # This is too long to be a valid pkey in the 'utf8' table charset
++    # and is the root cause of errors like:
++    #
++    # 1) Dumping a database with mysqldump and trying to import it fails
++    #    because this table is latin1 but fkeys to utf8 tables (projects).
++    #
++    # 2) Trying to alter the old dns_domains table fails with errors like:
++    #    mysql> ALTER TABLE dns_domains DROP PRIMARY KEY;
++    #    ERROR 1025 (HY000): Error on rename of './nova/#sql-6cf_855'....
++    #
++    # In short this table is just in a bad state. So... lets create a new one
++    # with a shorter 'domain' column which is valid for the utf8 charset.
++    #
++    # Since this is stable/essex we fix the table without bumping
++    # the migration number. The same upgrade will run during Folsom but
++    # that won't hurt anything.
++    #
++    # https://bugs.launchpad.net/nova/+bug/993663
++    dns_domains_old = Table('dns_domains', meta, autoload=True)
++    domain_type = str(dns_domains_old.c.domain.type)
++    if migrate_engine.name == 'mysql' and domain_type == 'VARCHAR(512)':
++        LOG.audit('Applying database fix for Essex dns_domains table.')
++        dns_domains_old.rename(name='dns_domains_old')
++
++        #Bind new metadata to avoid issues after the rename
++        meta = MetaData()
++        meta.bind = migrate_engine
++        projects = Table('projects', meta, autoload=True)  # Required for fkey
++
++        dns_domains_new = Table('dns_domains', meta,
++            Column('created_at', DateTime),
++            Column('updated_at', DateTime),
++            Column('deleted_at', DateTime),
++            Column('deleted', Boolean),
++            Column('domain', String(length=255), nullable=False,
++                   primary_key=True),
++            Column('scope', String(length=255)),
++            Column('availability_zone', String(length=255)),
++            Column('project_id', String(length=255),
++                   ForeignKey('projects.id')),
++            mysql_engine='InnoDB',
++            mysql_charset='utf8',
++        )
++        dns_domains_new.create()
++
++        dns_domains_old = Table('dns_domains_old', meta, autoload=True)
++        record_list = list(dns_domains_old.select().execute())
++        for rec in record_list:
++            row = dns_domains_new.insert()
++            row.execute({'created_at': rec['created_at'],
++                        'updated_at': rec['updated_at'],
++                        'deleted_at': rec['deleted_at'],
++                        'deleted': rec['deleted'],
++                        'domain': rec['domain'],
++                        'scope': rec['scope'],
++                        'availability_zone': rec['availability_zone'],
++                        'project_id': rec['project_id'],
++                        })
++
++        dns_domains_old.drop()
+diff --git a/nova/db/sqlalchemy/migration.py b/nova/db/sqlalchemy/migration.py
+index 16177cb..847fa02 100644
+--- a/nova/db/sqlalchemy/migration.py
++++ b/nova/db/sqlalchemy/migration.py
+@@ -19,6 +19,8 @@
+ import os
+ import sys
+ 
++from nova.db.sqlalchemy import fix_dns_domains
++from nova.db.sqlalchemy.session import get_engine
+ from nova import exception
+ from nova import flags
+ 
+@@ -48,7 +50,8 @@ def db_sync(version=None):
+     current_version = db_version()
+     repo_path = _find_migrate_repo()
+     if version is None or version > current_version:
+-        return versioning_api.upgrade(FLAGS.sql_connection, repo_path, version)
++        versioning_api.upgrade(FLAGS.sql_connection, repo_path, version)
++        return fix_dns_domains.run(get_engine())
+     else:
+         return versioning_api.downgrade(FLAGS.sql_connection, repo_path,
+                                         version)
diff --git a/0038-Don-t-query-nova-network-on-startup.patch b/0038-Don-t-query-nova-network-on-startup.patch
new file mode 100644
index 0000000..67dd54c
--- /dev/null
+++ b/0038-Don-t-query-nova-network-on-startup.patch
@@ -0,0 +1,165 @@
+From 1cee536c3e040aa2b1b1b3a1e5e9f1b2001c9b84 Mon Sep 17 00:00:00 2001
+From: Russell Bryant <rbryant at redhat.com>
+Date: Mon, 11 Jun 2012 14:07:19 +0100
+Subject: [PATCH] Don't query nova-network on startup.
+
+Backport from commit 8db54f3.
+Fix bug 999698.
+
+nova-compute requested network info for each instance on startup via rpc.
+If all services get (re)started at the same time, nova-network may not
+be available to take this request, resulting in a lost request.  To
+combat this issue, get the network info from the cache in the database
+on startup.  If by some chance this information is not correct, it will
+get fixed up by a periodic task.
+
+Change-Id: Ifb0634e87770f565e4ab36a54f6e9e19e5f31632
+---
+ nova/api/openstack/common.py                       |   10 ++--------
+ nova/api/openstack/compute/contrib/cloudpipe.py    |    4 ++--
+ nova/compute/manager.py                            |    2 +-
+ nova/compute/utils.py                              |    6 ++++++
+ .../openstack/compute/contrib/test_cloudpipe.py    |   14 +++++++-------
+ 5 files changed, 18 insertions(+), 18 deletions(-)
+
+diff --git a/nova/api/openstack/common.py b/nova/api/openstack/common.py
+index 040e8be..38f3821 100644
+--- a/nova/api/openstack/common.py
++++ b/nova/api/openstack/common.py
+@@ -27,9 +27,9 @@ from nova.api.openstack import wsgi
+ from nova.api.openstack import xmlutil
+ from nova.compute import vm_states
+ from nova.compute import task_states
++from nova.compute import utils as compute_utils
+ from nova import flags
+ from nova import log as logging
+-from nova.network import model as network_model
+ from nova import quota
+ 
+ 
+@@ -302,12 +302,6 @@ def get_networks_for_instance_from_nw_info(nw_info):
+     return networks
+ 
+ 
+-def get_nw_info_for_instance(context, instance):
+-    info_cache = instance['info_cache'] or {}
+-    cached_nwinfo = info_cache.get('network_info') or []
+-    return network_model.NetworkInfo.hydrate(cached_nwinfo)
+-
+-
+ def get_networks_for_instance(context, instance):
+     """Returns a prepared nw_info list for passing into the view builders
+ 
+@@ -319,7 +313,7 @@ def get_networks_for_instance(context, instance):
+                                      {'addr': '172.16.2.1', 'version': 4}]},
+          ...}
+     """
+-    nw_info = get_nw_info_for_instance(context, instance)
++    nw_info = compute_utils.get_nw_info_for_instance(instance)
+     return get_networks_for_instance_from_nw_info(nw_info)
+ 
+ 
+diff --git a/nova/api/openstack/compute/contrib/cloudpipe.py b/nova/api/openstack/compute/contrib/cloudpipe.py
+index dcdc87d..fcdde9e 100644
+--- a/nova/api/openstack/compute/contrib/cloudpipe.py
++++ b/nova/api/openstack/compute/contrib/cloudpipe.py
+@@ -16,13 +16,13 @@
+ 
+ import os
+ 
+-from nova.api.openstack import common
+ from nova.api.openstack import wsgi
+ from nova.api.openstack import xmlutil
+ from nova.api.openstack import extensions
+ from nova.auth import manager
+ from nova.cloudpipe import pipelib
+ from nova import compute
++from nova.compute import utils as compute_utils
+ from nova.compute import vm_states
+ from nova import db
+ from nova import exception
+@@ -91,7 +91,7 @@ class CloudpipeController(object):
+             return rv
+         rv['instance_id'] = instance['uuid']
+         rv['created_at'] = utils.isotime(instance['created_at'])
+-        nw_info = common.get_nw_info_for_instance(elevated, instance)
++        nw_info = compute_utils.get_nw_info_for_instance(instance)
+         if not nw_info:
+             return rv
+         vif = nw_info[0]
+diff --git a/nova/compute/manager.py b/nova/compute/manager.py
+index 053e80e..7cf462e 100644
+--- a/nova/compute/manager.py
++++ b/nova/compute/manager.py
+@@ -254,7 +254,7 @@ class ComputeManager(manager.SchedulerDependentManager):
+             elif drv_state == power_state.RUNNING:
+                 # Hyper-V and VMWareAPI drivers will raise an exception
+                 try:
+-                    net_info = self._get_instance_nw_info(context, instance)
++                    net_info = compute_utils.get_nw_info_for_instance(instance)
+                     self.driver.ensure_filtering_rules_for_instance(instance,
+                                                 self._legacy_nw_info(net_info))
+                 except NotImplementedError:
+diff --git a/nova/compute/utils.py b/nova/compute/utils.py
+index 1e5eb8b..6104c10 100644
+--- a/nova/compute/utils.py
++++ b/nova/compute/utils.py
+@@ -77,6 +77,12 @@ def notify_usage_exists(instance_ref, current_period=False):
+                         usage_info)
+ 
+ 
++def get_nw_info_for_instance(instance):
++    info_cache = instance['info_cache'] or {}
++    cached_nwinfo = info_cache.get('network_info') or []
++    return network_model.NetworkInfo.hydrate(cached_nwinfo)
++
++
+ def legacy_network_info(network_model):
+     """
+     Return the legacy network_info representation of the network_model
+diff --git a/nova/tests/api/openstack/compute/contrib/test_cloudpipe.py b/nova/tests/api/openstack/compute/contrib/test_cloudpipe.py
+index 531590c..4dfa97d 100644
+--- a/nova/tests/api/openstack/compute/contrib/test_cloudpipe.py
++++ b/nova/tests/api/openstack/compute/contrib/test_cloudpipe.py
+@@ -17,9 +17,9 @@ import datetime
+ 
+ from lxml import etree
+ 
+-from nova.api.openstack import common
+ from nova.api.openstack import wsgi
+ from nova.api.openstack.compute.contrib import cloudpipe
++from nova.compute import utils as compute_utils
+ from nova import db
+ from nova import flags
+ from nova import test
+@@ -67,11 +67,11 @@ class CloudpipeTest(test.TestCase):
+ 
+     def test_cloudpipe_list_no_network(self):
+ 
+-        def common_get_nw_info_for_instance(context, instance):
++        def fake_get_nw_info_for_instance(instance):
+             return {}
+ 
+-        self.stubs.Set(common, "get_nw_info_for_instance",
+-                       common_get_nw_info_for_instance)
++        self.stubs.Set(compute_utils, "get_nw_info_for_instance",
++                       fake_get_nw_info_for_instance)
+         self.stubs.Set(self.controller.compute_api, "get_all",
+                        compute_api_get_all)
+         req = fakes.HTTPRequest.blank('/v2/fake/os-cloudpipe')
+@@ -88,12 +88,12 @@ class CloudpipeTest(test.TestCase):
+             return {'vpn_public_address': '127.0.0.1',
+                     'vpn_public_port': 22}
+ 
+-        def common_get_nw_info_for_instance(context, instance):
++        def fake_get_nw_info_for_instance(instance):
+             return fake_network.fake_get_instance_nw_info(self.stubs,
+                                                           spectacular=True)
+ 
+-        self.stubs.Set(common, "get_nw_info_for_instance",
+-                       common_get_nw_info_for_instance)
++        self.stubs.Set(compute_utils, "get_nw_info_for_instance",
++                       fake_get_nw_info_for_instance)
+         self.stubs.Set(self.controller.network_api, "get",
+                        network_api_get)
+         self.stubs.Set(self.controller.compute_api, "get_all",
diff --git a/openstack-nova.spec b/openstack-nova.spec
index e0a8cd6..560d30a 100644
--- a/openstack-nova.spec
+++ b/openstack-nova.spec
@@ -2,7 +2,7 @@
 
 Name:             openstack-nova
 Version:          2012.1
-Release:          10%{?dist}
+Release:          11%{?dist}
 Summary:          OpenStack Compute (nova)
 
 Group:            Applications/System
@@ -67,6 +67,9 @@ Patch0032: 0032-ensure-atomic-manipulation-of-libvirt-disk-images.patch
 Patch0033: 0033-Ensure-we-don-t-access-the-net-when-building-docs.patch
 Patch0034: 0034-fix-useexisting-deprecation-warnings.patch
 Patch0035: 0035-support-a-configurable-libvirt-injection-partition.patch
+Patch0036: 0036-Only-invoke-.lower-on-non-None-protocols.patch
+Patch0037: 0037-Create-a-utf8-version-of-the-dns_domains-table.patch
+Patch0038: 0038-Don-t-query-nova-network-on-startup.patch
 
 # This is EPEL specific and not upstream
 Patch100:         openstack-nova-newdeps.patch
@@ -227,6 +230,9 @@ This package contains documentation files for nova.
 %patch0033 -p1
 %patch0034 -p1
 %patch0035 -p1
+%patch0036 -p1
+%patch0037 -p1
+%patch0038 -p1
 
 # Apply EPEL patch
 %patch100 -p1
@@ -424,6 +430,11 @@ fi
 %endif
 
 %changelog
+* Mon Jun 11 2012 Pádraig Brady <P at draigBrady.com> - 2012.1-11
+- fix an exception caused by the fix for CVE-2012-2654
+- fix the encoding of the dns_domains table (requires a db sync)
+- fix a crash due to a nova services startup race (#825051)
+
 * Wed Jun 08 2012 Pádraig Brady <P at draigBrady.com> - 2012.1-10
 - Enable libguestfs image inspection
 


More information about the scm-commits mailing list