# HG changeset patch # User Drew Fisher # Date 1397572273 25200 # Node ID 3e8d5f02f4a0ad007e2b6ec83f7d9e32378023fd # Parent 7ff897151ce763de527d35190ec4bed59c673663 18416129 neutron-l3-agent should include dependency on ipfilter service 18407503 neutron net-delete doesn't delete subnets/ports with no VM associated 18545343 nova-conductor's method shouldn't try to enable mysql 18545393 cinder-volume's method shouldn't try to enable iscsi/target 18545462 Some panels, menus, and options should be removed from Horizon 18545581 upstream bug 1187129 should be patched in 18551500 keystone's SMF method shouldn't try to enable mysql 18553610 problem in SERVICE/KEYSTONE diff -r 7ff897151ce7 -r 3e8d5f02f4a0 components/openstack/cinder/files/cinder-volume --- a/components/openstack/cinder/files/cinder-volume Mon Apr 14 14:24:04 2014 -0700 +++ b/components/openstack/cinder/files/cinder-volume Tue Apr 15 07:31:13 2014 -0700 @@ -14,40 +14,12 @@ # License for the specific language governing permissions and limitations # under the License. -import ConfigParser import os import smf_include -from subprocess import CalledProcessError, Popen, PIPE, check_call - def start(): - """ checks cinder's conf file for the ZFSISCSIDriver. If it's found, make - sure svc:/network/iscsi/target:default is online. - - """ - parser = ConfigParser.ConfigParser() - parser.read("/etc/cinder/cinder.conf") - driver = parser.get("DEFAULT", "volume_driver") - if driver == "cinder.volume.drivers.solaris.zfs.ZFSISCSIDriver": - iscsi_svc = "svc:/network/iscsi/target:default" - cmd = ["/usr/bin/svcs", "-H", "-o", "state", iscsi_svc] - try: - p = Popen(cmd, stdout=PIPE, stderr=PIPE) - output, error = p.communicate() - except CalledProcessError: - print "%s not found. Is it installed?" % iscsi_svc - return smf_include.SMF_EXIT_ERR_CONFIG - - if output.strip() != "online": - cmd = ["/usr/sbin/svcadm", "enable", "-rs", iscsi_svc] - try: - check_call(cmd) - except CalledProcessError as err: - print "enabling %s failed: %s" % (iscsi_svc, err) - return smf_include.SMF_EXIT_ERR_CONFIG - smf_include.smf_subprocess("/usr/bin/pfexec /usr/lib/cinder/cinder-volume") if __name__ == "__main__": diff -r 7ff897151ce7 -r 3e8d5f02f4a0 components/openstack/horizon/Makefile --- a/components/openstack/horizon/Makefile Mon Apr 14 14:24:04 2014 -0700 +++ b/components/openstack/horizon/Makefile Tue Apr 15 07:31:13 2014 -0700 @@ -54,7 +54,9 @@ $(MKDIR) $(PROTO_DIR)/usr/lib/python2.6/vendor-packages/openstack_dashboard/static/solaris/img; \ $(CP) files/branding/img/* $(PROTO_DIR)/usr/lib/python2.6/vendor-packages/openstack_dashboard/static/solaris/img; \ $(MKDIR) $(PROTO_DIR)/usr/lib/python2.6/vendor-packages/openstack_dashboard/static/solaris/theme; \ - $(CP) files/branding/theme/_stylesheets.html $(PROTO_DIR)/usr/lib/python2.6/vendor-packages/openstack_dashboard/static/solaris/theme) + $(CP) files/branding/theme/_stylesheets.html $(PROTO_DIR)/usr/lib/python2.6/vendor-packages/openstack_dashboard/static/solaris/theme; \ + $(CP) files/overrides.py $(PROTO_DIR)/usr/lib/python2.6/vendor-packages/openstack_dashboard); \ + $(PYTHON) -m compileall $(PROTO_DIR)/$(PYTHON_VENDOR_PACKAGES) # common targets build: $(BUILD_NO_ARCH) diff -r 7ff897151ce7 -r 3e8d5f02f4a0 components/openstack/horizon/files/local_settings.py --- a/components/openstack/horizon/files/local_settings.py Mon Apr 14 14:24:04 2014 -0700 +++ b/components/openstack/horizon/files/local_settings.py Tue Apr 15 07:31:13 2014 -0700 @@ -46,6 +46,7 @@ 'exceptions': {'recoverable': exceptions.RECOVERABLE, 'not_found': exceptions.NOT_FOUND, 'unauthorized': exceptions.UNAUTHORIZED}, + 'customization_module': 'openstack_dashboard.overrides', } # Specify a regular expression to validate user passwords. diff -r 7ff897151ce7 -r 3e8d5f02f4a0 components/openstack/horizon/files/overrides.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/components/openstack/horizon/files/overrides.py Tue Apr 15 07:31:13 2014 -0700 @@ -0,0 +1,95 @@ +# Copyright (c) 2014, Oracle and/or its affiliates. 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. + +""" +Solaris-specific customizations for Horizon +""" + +from horizon import tabs +from openstack_dashboard.dashboards.admin.networks.forms import CreateNetwork +from openstack_dashboard.dashboards.admin.networks.ports.forms import \ + CreatePort +from openstack_dashboard.dashboards.admin.networks.ports.tables import \ + DeletePort, PortsTable +from openstack_dashboard.dashboards.admin.networks.subnets.tables import \ + DeleteSubnet, SubnetsTable +from openstack_dashboard.dashboards.admin.networks.tables import \ + DeleteNetwork, NetworksTable +from openstack_dashboard.dashboards.project.instances.tabs import \ + InstanceDetailTabs, LogTab, OverviewTab +from openstack_dashboard.dashboards.project.instances.workflows import \ + create_instance +from openstack_dashboard.dashboards.project.networks.ports.tables import \ + PortsTable as projectPortsTable +from openstack_dashboard.dashboards.project.networks.subnets.tables import \ + DeleteSubnet as projectDeleteSubnet +from openstack_dashboard.dashboards.project.networks.subnets.tables import \ + SubnetsTable as projectSubnetsTable +from openstack_dashboard.dashboards.project.networks.tables import \ + CreateSubnet as projectCreateSubnet +from openstack_dashboard.dashboards.project.networks.tables import \ + DeleteNetwork as projectDeleteNetwork +from openstack_dashboard.dashboards.project.networks.tables import \ + NetworksTable as projectNetworksTable +from openstack_dashboard.dashboards.project.networks.workflows import \ + CreateNetworkInfoAction, CreateSubnetDetailAction, CreateSubnetInfoAction + +# remove PostCreationStep from LaunchInstance +create_instance.LaunchInstance.default_steps = \ + (create_instance.SelectProjectUser, + create_instance.SetInstanceDetails, + create_instance.SetAccessControls, + create_instance.SetNetwork) + +# remove the 'Console' tab from Instance Detail +InstanceDetailTabs.tabs = (OverviewTab, LogTab) + +# Disable 'admin_state' and 'shared' checkboxes on Create Networks +CreateNetwork.base_fields['admin_state'].widget.attrs['disabled'] = True +CreateNetwork.base_fields['shared'].widget.attrs['disabled'] = True + +# Disable 'admin_state' checkbox on Create Port +CreatePort.base_fields['admin_state'].widget.attrs['disabled'] = True + +# Remove the ability to Update Ports +PortsTable._meta.row_actions = (DeletePort,) + +# Remove the ability to Update Subnets +SubnetsTable._meta.row_actions = (DeleteSubnet,) + +# Remove the ability to Edit Networks +NetworksTable._meta.row_actions = (DeleteNetwork,) + +# Remove the ability to Update project Ports +projectPortsTable._meta.row_actions = () + +# Remove the ability to Update project Subnets +projectSubnetsTable._meta.row_actions = (projectDeleteSubnet,) + +# Remove the ability to Edit project Networks +projectNetworksTable._meta.row_actions = (projectCreateSubnet, + projectDeleteNetwork) + +# Disable 'admin_state' checkbox on Create project Networks +CreateNetworkInfoAction.base_fields['admin_state'].widget.attrs['disabled'] = \ + True + +# Disable 'no_gateway' checkbox on Create project Networks +CreateSubnetInfoAction.base_fields['no_gateway'].widget.attrs['disabled'] = \ + True + +# change 'allocation_pools' and 'host_routes' to readonly +base_fields = CreateSubnetDetailAction.base_fields +base_fields['allocation_pools'].widget.attrs['readonly'] = 'readonly' +base_fields['host_routes'].widget.attrs['readonly'] = 'readonly' diff -r 7ff897151ce7 -r 3e8d5f02f4a0 components/openstack/horizon/horizon.p5m --- a/components/openstack/horizon/horizon.p5m Mon Apr 14 14:24:04 2014 -0700 +++ b/components/openstack/horizon/horizon.p5m Tue Apr 15 07:31:13 2014 -0700 @@ -680,6 +680,7 @@ file path=usr/lib/python$(PYVER)/vendor-packages/openstack_dashboard/openstack/common/__init__.py file path=usr/lib/python$(PYVER)/vendor-packages/openstack_dashboard/openstack/common/setup.py file path=usr/lib/python$(PYVER)/vendor-packages/openstack_dashboard/openstack/common/version.py +file path=usr/lib/python$(PYVER)/vendor-packages/openstack_dashboard/overrides.py file path=usr/lib/python$(PYVER)/vendor-packages/openstack_dashboard/settings.py dir path=usr/lib/python$(PYVER)/vendor-packages/openstack_dashboard/static \ owner=webservd group=webservd diff -r 7ff897151ce7 -r 3e8d5f02f4a0 components/openstack/horizon/patches/04-lauchpad-1187129.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/components/openstack/horizon/patches/04-lauchpad-1187129.patch Tue Apr 15 07:31:13 2014 -0700 @@ -0,0 +1,52 @@ +From d7b8c1eeb6c36800a891584ad948b4b5ab1f52bf Mon Sep 17 00:00:00 2001 +From: armando-migliaccio +Date: Mon, 3 Jun 2013 13:57:44 -0700 +Subject: [PATCH] Fix bug in port creation form + +'network_name' is not a recognized Quantum attribute, so passing it +in the request to the Quantum Server causes an error. In the end this +is not required because the network is identified by its id. So +this patch removes it (as it's done in other cases as well). + +Fixes bug #1187129 + +Change-Id: Ie18c7bd504f8c241d002d6a050b8bcc59ed9fc03 + +Fixed in Havana 2013.2 +--- + .../dashboards/admin/networks/ports/forms.py | 1 + + .../dashboards/admin/networks/tests.py | 2 -- + 2 files changed, 1 insertion(+), 2 deletions(-) + +diff --git a/openstack_dashboard/dashboards/admin/networks/ports/forms.py b/openstack_dashboard/dashboards/admin/networks/ports/forms.py +index 7a1f45d..939952b 100644 +--- a/openstack_dashboard/dashboards/admin/networks/ports/forms.py ++++ b/openstack_dashboard/dashboards/admin/networks/ports/forms.py +@@ -57,6 +57,7 @@ class CreatePort(forms.SelfHandlingForm): + network = api.quantum.network_get(request, data['network_id']) + data['tenant_id'] = network.tenant_id + data['admin_state_up'] = data['admin_state'] ++ del data['network_name'] + del data['admin_state'] + + port = api.quantum.port_create(request, **data) +diff --git a/openstack_dashboard/dashboards/admin/networks/tests.py b/openstack_dashboard/dashboards/admin/networks/tests.py +index d6c0123..9c2cd19 100644 +--- a/openstack_dashboard/dashboards/admin/networks/tests.py ++++ b/openstack_dashboard/dashboards/admin/networks/tests.py +@@ -651,7 +651,6 @@ class NetworkPortTests(test.BaseAdminViewTests): + api.quantum.port_create(IsA(http.HttpRequest), + tenant_id=network.tenant_id, + network_id=network.id, +- network_name=network.name, + name=port.name, + admin_state_up=port.admin_state_up, + device_id=port.device_id, +@@ -688,7 +687,6 @@ class NetworkPortTests(test.BaseAdminViewTests): + api.quantum.port_create(IsA(http.HttpRequest), + tenant_id=network.tenant_id, + network_id=network.id, +- network_name=network.name, + name=port.name, + admin_state_up=port.admin_state_up, + device_id=port.device_id, diff -r 7ff897151ce7 -r 3e8d5f02f4a0 components/openstack/keystone/files/keystone --- a/components/openstack/keystone/files/keystone Mon Apr 14 14:24:04 2014 -0700 +++ b/components/openstack/keystone/files/keystone Tue Apr 15 07:31:13 2014 -0700 @@ -14,21 +14,16 @@ # License for the specific language governing permissions and limitations # under the License. -import ConfigParser import os import sys import smf_include -from subprocess import CalledProcessError, check_call, PIPE, Popen - -from sqlalchemy import create_engine +from subprocess import CalledProcessError, check_call -def db_sync(): - """ function to create the database schema - """ - +def start(): + # sync the database to make sure it's ready cmd = ["/usr/bin/keystone-manage", "db_sync"] try: check_call(cmd) @@ -36,47 +31,6 @@ print "Unable to create database for Keystone: %s" % err sys.exit(smf_include.SMF_EXIT_ERR_CONFIG) - -def start(): - # read the options from the config file - parser = ConfigParser.ConfigParser() - parser.read("/etc/keystone/keystone.conf") - - # get the database type - db_engine = create_engine(parser.get("sql", "connection")) - db_type = db_engine.name - - if db_type == "sqlite": - # look to see if file exists or if it's zero length - abspath = os.path.abspath(db_engine.url.database) - if not os.path.exists(abspath) or os.path.getsize(abspath) == 0: - db_sync() - - elif db_type == "mysql": - mysql_svc = "svc:/application/database/mysql:version_55" - cmd = ["/usr/bin/svcs", "-H", "-o", "state", mysql_svc] - - try: - p = Popen(cmd, stdout=PIPE, stderr=PIPE) - output, error = p.communicate() - except CalledProcessError: - print "mysql service not found. Is it installed?" - return smf_include.SMF_EXIT_ERR_CONFIG - - if output.strip() != "online": - # attempt to start mysql - cmd = ["/usr/sbin/svcadm", "enable", "-rs", mysql_svc] - - try: - check_call(cmd) - except CalledProcessError as err: - print "starting mysql service failed: %s" % err - return smf_include.SMF_EXIT_ERR_CONFIG - - # not sure how to check if the database is valid, so just create - # the database every time for now - db_sync() - smf_include.smf_subprocess("/usr/lib/keystone/keystone-all") if __name__ == "__main__": diff -r 7ff897151ce7 -r 3e8d5f02f4a0 components/openstack/keystone/patches/07-CVE-2014-2828.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/components/openstack/keystone/patches/07-CVE-2014-2828.patch Tue Apr 15 07:31:13 2014 -0700 @@ -0,0 +1,56 @@ +Upstream patch for bug 1300274. + +Fixed in Havana 2013.2.4, Icehouse 2014.1 + +From e364ba5b12de8e4c11bd80bcca903f9615dcfc2e Mon Sep 17 00:00:00 2001 +From: Florent Flament +Date: Tue, 1 Apr 2014 12:48:22 +0000 +Subject: Sanitizes authentication methods received in requests. + +When a user authenticates against Identity V3 API, he can specify +multiple authentication methods. This patch removes duplicates, which +could have been used to achieve DoS attacks. + +Closes-Bug: 1300274 +(cherry picked from commit ef868ad92c00e23a4a5e9eb71e3e0bf5ae2fff0c) +Cherry-pick from https://review.openstack.org/#/c/84425/ + +Change-Id: I6e60324309baa094a5e54b012fb0fc528fea72ab + +--- keystone-2013.1.4/keystone/auth/controllers.py.orig 2014-04-10 14:46:27.890585026 -0600 ++++ keystone-2013.1.4/keystone/auth/controllers.py 2014-04-10 14:47:53.783687911 -0600 +@@ -228,7 +228,13 @@ + :returns: list of auth method names + + """ +- return self.auth['identity']['methods'] ++ # Sanitizes methods received in request's body ++ # Filters out duplicates, while keeping elements' order. ++ method_names = [] ++ for method in self.auth['identity']['methods']: ++ if method not in method_names: ++ method_names.append(method) ++ return method_names + + def get_method_data(self, method): + """ Get the auth method payload. +--- keystone-2013.1.4/tests/test_v3_auth.py.orig 2014-04-10 14:50:45.929495618 -0600 ++++ keystone-2013.1.4/tests/test_v3_auth.py 2014-04-10 14:50:48.764440233 -0600 +@@ -83,6 +83,17 @@ + None, + auth_data) + ++ def test_get_method_names_duplicates(self): ++ auth_data = self.build_authentication_request( ++ token='test', ++ user_id='test', ++ password='test')['auth'] ++ auth_data['identity']['methods'] = ['password', 'token', ++ 'password', 'password'] ++ context = None ++ auth_info = auth.controllers.AuthInfo(context, auth_data) ++ self.assertEqual(auth_info.get_method_names(), ++ ['password', 'token']) + + class TestTokenAPIs(test_v3.RestfulTestCase): + def setUp(self): diff -r 7ff897151ce7 -r 3e8d5f02f4a0 components/openstack/neutron/files/evs/plugin.py --- a/components/openstack/neutron/files/evs/plugin.py Mon Apr 14 14:24:04 2014 -0700 +++ b/components/openstack/neutron/files/evs/plugin.py Tue Apr 15 07:31:13 2014 -0700 @@ -487,16 +487,26 @@ def get_subnets_count(self, context, filters=None): return len(self.get_ipnets(context, filters)) - def _release_subnet_dhcp_port(self, context, subnet): + def _release_subnet_dhcp_port(self, context, subnet, delete_network): """Release any dhcp port associated with the subnet""" filters = dict(evs=subnet['network_id']) portlist = self.get_ports(context, filters) - if len(portlist) == 1: + + if delete_network: + # One can delete a network if there is only one port that has a + # VNIC attached to it and that port happens to be a DHCP port. + ports_with_deviceid = [port for port in portlist + if port['device_id'] != ''] + update_subnet = len(ports_with_deviceid) == 1 + else: + # One can delete a subnet if there is only one port and that + # port happens to be a DHCP port. + update_subnet = len(portlist) == 1 + if update_subnet: # the lone port is a dhcp port created by dhcp agent # it must be released before we can delete the subnet - assert portlist[0]['device_owner'] == 'network:dhcp' subnet_update = {'subnet': {'enable_dhcp': False}, - 'evs_rpccall_sync': True} + 'evs_rpccall_sync': True} self.update_subnet(context, subnet['id'], subnet_update) def delete_subnet(self, context, id): @@ -515,7 +525,7 @@ # False that in turn sends a subnet.udpate notification. This # results in DHCP agent releasing the port. if subnet['enable_dhcp']: - self._release_subnet_dhcp_port(context, subnet) + self._release_subnet_dhcp_port(context, subnet, False) evs.removeIPnet(id) except radcli.ObjectError as oe: raise EVSControllerError(oe.get_payload().errmsg) @@ -649,7 +659,7 @@ subnets = self.get_subnets(context, filters=filters) dhcp_subnets = [s for s in subnets if s['enable_dhcp']] for subnet in dhcp_subnets: - self._release_subnet_dhcp_port(context, subnet) + self._release_subnet_dhcp_port(context, subnet, True) self._evsc.deleteEVS(id, context.tenant_id) except radcli.ObjectError as oe: raise EVSControllerError(oe.get_payload().errmsg) diff -r 7ff897151ce7 -r 3e8d5f02f4a0 components/openstack/neutron/files/neutron-l3-agent --- a/components/openstack/neutron/files/neutron-l3-agent Mon Apr 14 14:24:04 2014 -0700 +++ b/components/openstack/neutron/files/neutron-l3-agent Tue Apr 15 07:31:13 2014 -0700 @@ -19,6 +19,8 @@ import smf_include +from subprocess import Popen, PIPE + def start(): # verify paths are valid @@ -27,6 +29,31 @@ print '%s does not exist or is not readable' % f return smf_include.SMF_EXIT_ERR_CONFIG + # System-wide forwarding (either ipv4 or ipv6 or both) must be enabled + # before neutron-l3-agent can be started. + cmd = ["/usr/sbin/ipadm", "show-prop", "-c", "-p", "forwarding", + "-o", "current", "ipv4"] + p = Popen(cmd, stdout=PIPE, stderr=PIPE) + output, error = p.communicate() + if p.returncode != 0: + print "failed to determine if IPv4 forwarding is enabled or not" + return smf_include.SMF_EXIT_ERR_FATAL + v4fwding = "on" in output + + cmd = ["/usr/sbin/ipadm", "show-prop", "-c", "-p", "forwarding", + "-o", "current", "ipv6"] + p = Popen(cmd, stdout=PIPE, stderr=PIPE) + output, error = p.communicate() + if p.returncode != 0: + print "failed to determine if IPv6 forwarding is enabled or not" + return smf_include.SMF_EXIT_ERR_FATAL + v6fwding = "on" in output + + if not any((v4fwding, v6fwding)): + print "System-wide IPv4 or IPv6 (or both) forwarding must be enabled " \ + "before enabling %s" % os.getenv("SMF_FMRI") + return smf_include.SMF_EXIT_ERR_CONFIG + cmd = "/usr/lib/neutron/neutron-l3-agent --config-file %s " \ "--config-file %s" % tuple(sys.argv[2:4]) smf_include.smf_subprocess(cmd) diff -r 7ff897151ce7 -r 3e8d5f02f4a0 components/openstack/neutron/files/neutron-l3-agent.xml --- a/components/openstack/neutron/files/neutron-l3-agent.xml Mon Apr 14 14:24:04 2014 -0700 +++ b/components/openstack/neutron/files/neutron-l3-agent.xml Tue Apr 15 07:31:13 2014 -0700 @@ -30,6 +30,11 @@ + + + + diff -r 7ff897151ce7 -r 3e8d5f02f4a0 components/openstack/nova/files/nova-conductor --- a/components/openstack/nova/files/nova-conductor Mon Apr 14 14:24:04 2014 -0700 +++ b/components/openstack/nova/files/nova-conductor Tue Apr 15 07:31:13 2014 -0700 @@ -14,21 +14,16 @@ # License for the specific language governing permissions and limitations # under the License. -import ConfigParser import os import sys import smf_include -from subprocess import CalledProcessError, check_call, PIPE, Popen - -from sqlalchemy import create_engine +from subprocess import CalledProcessError, check_call -def db_sync(): - """ function to create the database schema - """ - +def start(): + # sync the database to make sure it's ready cmd = ["/usr/bin/nova-manage", "db", "sync"] try: check_call(cmd) @@ -36,47 +31,6 @@ print "Unable to create database for Nova: %s" % err sys.exit(smf_include.SMF_EXIT_ERR_CONFIG) - -def start(): - # read the options from the config file - parser = ConfigParser.ConfigParser() - parser.read("/etc/nova/nova.conf") - - # get the database type - db_engine = create_engine(parser.get("DEFAULT", "sql_connection")) - db_type = db_engine.name - - if db_type == "sqlite": - # look to see if file exists or if it's zero length - abspath = os.path.abspath(db_engine.url.database) - if not os.path.exists(abspath) or os.path.getsize(abspath) == 0: - db_sync() - - elif db_type == "mysql": - mysql_svc = "svc:/application/database/mysql:version_55" - cmd = ["/usr/bin/svcs", "-H", "-o", "state", mysql_svc] - - try: - p = Popen(cmd, stdout=PIPE, stderr=PIPE) - output, error = p.communicate() - except CalledProcessError: - print "mysql service not found. Is it installed?" - return smf_include.SMF_EXIT_ERR_CONFIG - - if output.strip() != "online": - # attempt to start mysql - cmd = ["/usr/sbin/svcadm", "enable", "-rs", mysql_svc] - - try: - check_call(cmd) - except CalledProcessError as err: - print "starting mysql service failed: %s" % err - return smf_include.SMF_EXIT_ERR_CONFIG - - # not sure how to check if the database is valid, so just create - # the database every time for now - db_sync() - smf_include.smf_subprocess("/usr/lib/nova/nova-conductor") if __name__ == "__main__":