public inbox for gentoo-commits@lists.gentoo.org
 help / color / mirror / Atom feed
* [gentoo-commits] repo/gentoo:master commit in: app-admin/glance/files/, app-admin/glance/
@ 2015-08-14  5:21 Matt Thode
  0 siblings, 0 replies; 5+ messages in thread
From: Matt Thode @ 2015-08-14  5:21 UTC (permalink / raw
  To: gentoo-commits

commit:     2d4637cbfa732ff2cb94f440debc1ec813cafe58
Author:     Matthew Thode <prometheanfire <AT> gentoo <DOT> org>
AuthorDate: Fri Aug 14 05:22:26 2015 +0000
Commit:     Matt Thode <prometheanfire <AT> gentoo <DOT> org>
CommitDate: Fri Aug 14 05:22:26 2015 +0000
URL:        https://gitweb.gentoo.org/repo/gentoo.git/commit/?id=2d4637cb

app-admin/glance: fixing CVE-2015-5163

CVE: CVE-2015-5163
Signed-off-by: Matthew Thode <prometheanfire <AT> gentoo.org>

Package-Manager: portage-2.2.20.1

 .../glance/files/cve-2015-5163-stable-kilo.patch   | 260 +++++++++++++++++++++
 ...e-2015.1.1.ebuild => glance-2015.1.1-r1.ebuild} |   1 +
 2 files changed, 261 insertions(+)

diff --git a/app-admin/glance/files/cve-2015-5163-stable-kilo.patch b/app-admin/glance/files/cve-2015-5163-stable-kilo.patch
new file mode 100644
index 0000000..91507c9
--- /dev/null
+++ b/app-admin/glance/files/cve-2015-5163-stable-kilo.patch
@@ -0,0 +1,260 @@
+From eb99e45829a1b4c93db5692bdbf636a86faa56c4 Mon Sep 17 00:00:00 2001
+From: Flavio Percoco <flaper87@gmail.com>
+Date: Thu, 9 Jul 2015 14:44:04 +0200
+Subject: Don't import files with backed files
+
+There's a security issue where it'd be possible to import images with
+backed files using the task engine and then use/convert those to access
+system files or any other file in the system. An example of an attack
+would be to import an image with a backing file pointing to
+`/etc/passwd`, then convert it to raw and download the generated image.
+
+This patch forbids importing files with baking files entirely. It does
+that in the `_ImportToFS` task, which is the one that imports the image
+locally to then execute other tasks on it. It's not necessary for the
+`_ImportToStore` task because other tasks won't be executed when the
+image is imported in the final store.
+
+Change-Id: I35f43c3b3f326942fb53b7dadb94700ac4513494
+Closes-bug: #1471912
+(cherry picked from commit d529863a1e8d2307526bdb395b4aebe97f81603d)
+
+diff --git a/glance/async/flows/base_import.py b/glance/async/flows/base_import.py
+index 7656bde..d216aa8 100644
+--- a/glance/async/flows/base_import.py
++++ b/glance/async/flows/base_import.py
+@@ -13,12 +13,15 @@
+ #    License for the specific language governing permissions and limitations
+ #    under the License.
+ 
++import json
+ import logging
+ import os
+ 
+ import glance_store as store_api
+ from glance_store import backend
++from oslo_concurrency import processutils as putils
+ from oslo_config import cfg
++from oslo_utils import excutils
+ import six
+ from stevedore import named
+ from taskflow.patterns import linear_flow as lf
+@@ -146,6 +149,29 @@ class _ImportToFS(task.Task):
+         data = script_utils.get_image_data_iter(self.uri)
+ 
+         path = self.store.add(image_id, data, 0, context=None)[0]
++
++        try:
++            # NOTE(flaper87): Consider moving this code to a common
++            # place that other tasks can consume as well.
++            stdout, stderr = putils.trycmd('qemu-img', 'info',
++                                           '--output=json', path,
++                                           log_errors=putils.LOG_ALL_ERRORS)
++        except OSError as exc:
++            with excutils.save_and_reraise_exception():
++                msg = (_LE('Failed to execute security checks on the image '
++                           '%(task_id)s: %(exc)s') %
++                       {'task_id': self.task_id, 'exc': exc.message})
++                LOG.error(msg)
++
++        metadata = json.loads(stdout)
++
++        backing_file = metadata.get('backing-filename')
++        if backing_file is not None:
++            msg = _("File %(path)s has invalid backing file "
++                    "%(bfile)s, aborting.") % {'path': path,
++                                               'bfile': backing_file}
++            raise RuntimeError(msg)
++
+         return path
+ 
+     def revert(self, image_id, result=None, **kwargs):
+diff --git a/glance/tests/unit/async/flows/test_import.py b/glance/tests/unit/async/flows/test_import.py
+index 70f790c..4cf3d13 100644
+--- a/glance/tests/unit/async/flows/test_import.py
++++ b/glance/tests/unit/async/flows/test_import.py
+@@ -13,14 +13,17 @@
+ #    License for the specific language governing permissions and limitations
+ #    under the License.
+ 
++import json
+ import mock
+ import os
+ import urllib2
+ 
+ import glance_store
++from oslo_concurrency import processutils as putils
+ from oslo_config import cfg
+ from six.moves import cStringIO
+ from taskflow import task
++from taskflow.types import failure
+ 
+ import glance.async.flows.base_import as import_flow
+ from glance.async import taskflow_executor
+@@ -106,16 +109,23 @@ class TestImportTask(test_utils.BaseTestCase):
+ 
+         with mock.patch.object(script_utils, 'get_image_data_iter') as dmock:
+             dmock.return_value = cStringIO("TEST_IMAGE")
+-            executor.begin_processing(self.task.task_id)
+-            image_path = os.path.join(self.test_dir, self.image.image_id)
+-            tmp_image_path = os.path.join(self.work_dir,
+-                                          "%s.tasks_import" % image_path)
+-            self.assertFalse(os.path.exists(tmp_image_path))
+-            self.assertTrue(os.path.exists(image_path))
+-            self.assertEqual(1, len(list(self.image.locations)))
+-            self.assertEqual("file://%s/%s" % (self.test_dir,
+-                                               self.image.image_id),
+-                             self.image.locations[0]['url'])
++
++            with mock.patch.object(putils, 'trycmd') as tmock:
++                tmock.return_value = (json.dumps({
++                    'format': 'qcow2',
++                }), None)
++
++                executor.begin_processing(self.task.task_id)
++                image_path = os.path.join(self.test_dir, self.image.image_id)
++                tmp_image_path = os.path.join(self.work_dir,
++                                              "%s.tasks_import" % image_path)
++
++                self.assertFalse(os.path.exists(tmp_image_path))
++                self.assertTrue(os.path.exists(image_path))
++                self.assertEqual(1, len(list(self.image.locations)))
++                self.assertEqual("file://%s/%s" % (self.test_dir,
++                                                   self.image.image_id),
++                                 self.image.locations[0]['url'])
+ 
+     def test_import_flow_missing_work_dir(self):
+         self.config(engine_mode='serial', group='taskflow_executor')
+@@ -151,6 +161,54 @@ class TestImportTask(test_utils.BaseTestCase):
+                 self.assertFalse(os.path.exists(tmp_image_path))
+                 self.assertTrue(os.path.exists(image_path))
+ 
++    def test_import_flow_backed_file_import_to_fs(self):
++        self.config(engine_mode='serial', group='taskflow_executor')
++
++        img_factory = mock.MagicMock()
++
++        executor = taskflow_executor.TaskExecutor(
++            self.context,
++            self.task_repo,
++            self.img_repo,
++            img_factory)
++
++        self.task_repo.get.return_value = self.task
++
++        def create_image(*args, **kwargs):
++            kwargs['image_id'] = UUID1
++            return self.img_factory.new_image(*args, **kwargs)
++
++        self.img_repo.get.return_value = self.image
++        img_factory.new_image.side_effect = create_image
++
++        with mock.patch.object(script_utils, 'get_image_data_iter') as dmock:
++            dmock.return_value = cStringIO("TEST_IMAGE")
++
++            with mock.patch.object(putils, 'trycmd') as tmock:
++                tmock.return_value = (json.dumps({
++                    'backing-filename': '/etc/password'
++                }), None)
++
++                with mock.patch.object(import_flow._ImportToFS,
++                                       'revert') as rmock:
++                    self.assertRaises(RuntimeError,
++                                      executor.begin_processing,
++                                      self.task.task_id)
++                    self.assertTrue(rmock.called)
++                    self.assertIsInstance(rmock.call_args[1]['result'],
++                                          failure.Failure)
++
++                    image_path = os.path.join(self.test_dir,
++                                              self.image.image_id)
++
++                    fname = "%s.tasks_import" % image_path
++                    tmp_image_path = os.path.join(self.work_dir, fname)
++
++                    self.assertFalse(os.path.exists(tmp_image_path))
++                    # Note(sabari): The image should not have been uploaded to
++                    # the store as the flow failed before ImportToStore Task.
++                    self.assertFalse(os.path.exists(image_path))
++
+     def test_import_flow_revert(self):
+         self.config(engine_mode='serial',
+                     group='taskflow_executor')
+@@ -175,20 +233,31 @@ class TestImportTask(test_utils.BaseTestCase):
+         with mock.patch.object(script_utils, 'get_image_data_iter') as dmock:
+             dmock.return_value = cStringIO("TEST_IMAGE")
+ 
+-            with mock.patch.object(import_flow, "_get_import_flows") as imock:
+-                imock.return_value = (x for x in [_ErrorTask()])
+-                self.assertRaises(RuntimeError,
+-                                  executor.begin_processing, self.task.task_id)
+-                image_path = os.path.join(self.test_dir, self.image.image_id)
+-                tmp_image_path = os.path.join(self.work_dir,
+-                                              "%s.tasks_import" % image_path)
+-                self.assertFalse(os.path.exists(tmp_image_path))
+-
+-                # NOTE(flaper87): Eventually, we want this to be assertTrue.
+-                # The current issue is there's no way to tell taskflow to
+-                # continue on failures. That is, revert the subflow but keep
+-                # executing the parent flow. Under discussion/development.
+-                self.assertFalse(os.path.exists(image_path))
++            with mock.patch.object(putils, 'trycmd') as tmock:
++                tmock.return_value = (json.dumps({
++                    'format': 'qcow2',
++                }), None)
++
++                with mock.patch.object(import_flow,
++                                       "_get_import_flows") as imock:
++                    imock.return_value = (x for x in [_ErrorTask()])
++                    self.assertRaises(RuntimeError,
++                                      executor.begin_processing,
++                                      self.task.task_id)
++
++                    image_path = os.path.join(self.test_dir,
++                                              self.image.image_id)
++                    tmp_image_path = os.path.join(self.work_dir,
++                                                  ("%s.tasks_import" %
++                                                   image_path))
++                    self.assertFalse(os.path.exists(tmp_image_path))
++
++                    # NOTE(flaper87): Eventually, we want this to be assertTrue
++                    # The current issue is there's no way to tell taskflow to
++                    # continue on failures. That is, revert the subflow but
++                    # keep executing the parent flow. Under
++                    # discussion/development.
++                    self.assertFalse(os.path.exists(image_path))
+ 
+     def test_import_flow_no_import_flows(self):
+         self.config(engine_mode='serial',
+@@ -271,15 +340,20 @@ class TestImportTask(test_utils.BaseTestCase):
+         with mock.patch.object(script_utils, 'get_image_data_iter') as dmock:
+             dmock.return_value = "test"
+ 
+-            image_id = UUID1
+-            path = import_fs.execute(image_id)
+-            reader, size = glance_store.get_from_backend(path)
+-            self.assertEqual(4, size)
+-            self.assertEqual(dmock.return_value, "".join(reader))
++            with mock.patch.object(putils, 'trycmd') as tmock:
++                tmock.return_value = (json.dumps({
++                    'format': 'qcow2',
++                }), None)
++
++                image_id = UUID1
++                path = import_fs.execute(image_id)
++                reader, size = glance_store.get_from_backend(path)
++                self.assertEqual(4, size)
++                self.assertEqual(dmock.return_value, "".join(reader))
+ 
+-            image_path = os.path.join(self.work_dir, image_id)
+-            tmp_image_path = os.path.join(self.work_dir, image_path)
+-            self.assertTrue(os.path.exists(tmp_image_path))
++                image_path = os.path.join(self.work_dir, image_id)
++                tmp_image_path = os.path.join(self.work_dir, image_path)
++                self.assertTrue(os.path.exists(tmp_image_path))
+ 
+     def test_delete_from_fs(self):
+         delete_fs = import_flow._DeleteFromFS(self.task.task_id,
+-- 
+cgit v0.10.2
+

diff --git a/app-admin/glance/glance-2015.1.1.ebuild b/app-admin/glance/glance-2015.1.1-r1.ebuild
similarity index 99%
rename from app-admin/glance/glance-2015.1.1.ebuild
rename to app-admin/glance/glance-2015.1.1-r1.ebuild
index b220166..e7df249 100644
--- a/app-admin/glance/glance-2015.1.1.ebuild
+++ b/app-admin/glance/glance-2015.1.1-r1.ebuild
@@ -137,6 +137,7 @@ RDEPEND="
 "
 
 PATCHES=(
+	"${FILESDIR}/cve-2015-5163-stable-kilo.patch"
 )
 
 pkg_setup() {


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [gentoo-commits] repo/gentoo:master commit in: app-admin/glance/files/, app-admin/glance/
@ 2015-09-22 17:46 Matt Thode
  0 siblings, 0 replies; 5+ messages in thread
From: Matt Thode @ 2015-09-22 17:46 UTC (permalink / raw
  To: gentoo-commits

commit:     4cb4bc39e1d1f115d6db596e0a7e6f23db3f924e
Author:     Matthew Thode <mthode <AT> mthode <DOT> org>
AuthorDate: Tue Sep 22 17:45:22 2015 +0000
Commit:     Matt Thode <prometheanfire <AT> gentoo <DOT> org>
CommitDate: Tue Sep 22 17:45:59 2015 +0000
URL:        https://gitweb.gentoo.org/repo/gentoo.git/commit/?id=4cb4bc39

app-admin/glance: fixing CVE-2015-5251

Package-Manager: portage-2.2.20.1

 .../glance/files/cve-2015-5251-stable-kilo.patch   | 192 +++++++++++++++++++++
 app-admin/glance/glance-2015.1.1-r2.ebuild         | 190 ++++++++++++++++++++
 2 files changed, 382 insertions(+)

diff --git a/app-admin/glance/files/cve-2015-5251-stable-kilo.patch b/app-admin/glance/files/cve-2015-5251-stable-kilo.patch
new file mode 100644
index 0000000..f868645
--- /dev/null
+++ b/app-admin/glance/files/cve-2015-5251-stable-kilo.patch
@@ -0,0 +1,192 @@
+From 9beca533f42ae1fc87418de0c360e19bc59b24b5 Mon Sep 17 00:00:00 2001
+From: Stuart McLaren <stuart.mclaren@hp.com>
+Date: Tue, 11 Aug 2015 10:37:09 +0000
+Subject: [PATCH] Prevent image status being directly modified via v1
+
+Users shouldn't be able to change an image's status directly via the
+v1 API.
+
+Some existing consumers of Glance set the x-image-meta-status header in
+requests to the Glance API, eg:
+
+https://github.com/openstack/nova/blob/master/plugins/xenserver/xenapi/etc/xapi.d/plugins/glance#L184
+
+We should try to prevent users setting 'status' via v1, but without breaking
+existing benign API calls such as these.
+
+I've adopted the following approach (which has some prior art in 'protected properties').
+
+If a PUT request is received which contains an x-image-meta-status header:
+
+* The user provided status is ignored if it matches the current image
+  status (this prevents benign calls such as the nova one above from
+  breaking). The usual code (eg 200) will be returned.
+
+* If the user provided status doesn't match the current image status (ie
+  there is a real attempt to change the value) 403 will be returned. This
+  will break any calls which currently intentionally change the status.
+
+APIImpact
+
+Closes-bug: 1482371
+
+Change-Id: I44fadf32abb57c962b67467091c3f51c1ccc25e6
+(cherry picked from commit 4d08db5b6d42323ac1958ef3b7417d875e7bea8c)
+---
+ glance/api/v1/__init__.py                          |  3 +
+ glance/api/v1/images.py                            |  9 +++
+ glance/tests/functional/v1/test_api.py             | 89 ++++++++++++++++++++++
+ .../integration/legacy_functional/test_v1_api.py   |  2 +
+ 4 files changed, 103 insertions(+)
+
+diff --git a/glance/api/v1/__init__.py b/glance/api/v1/__init__.py
+index 74de9aa1411d8e926770b67f7d851cf14e794414..9306bbb4fe78f77a26bb539c717fdfd2b38767c8 100644
+--- a/glance/api/v1/__init__.py
++++ b/glance/api/v1/__init__.py
+@@ -21,3 +21,6 @@ SUPPORTED_PARAMS = ('limit', 'marker', 'sort_key', 'sort_dir')
+ 
+ # Metadata which only an admin can change once the image is active
+ ACTIVE_IMMUTABLE = ('size', 'checksum')
++
++# Metadata which cannot be changed (irrespective of the current image state)
++IMMUTABLE = ('status',)
+diff --git a/glance/api/v1/images.py b/glance/api/v1/images.py
+index e33b91fbca79377e78ccfd329fa542ad422f5ffc..95e32949d958d0f57a3b60c141b91784a5801f5a 100644
+--- a/glance/api/v1/images.py
++++ b/glance/api/v1/images.py
+@@ -57,6 +57,7 @@ _LW = i18n._LW
+ SUPPORTED_PARAMS = glance.api.v1.SUPPORTED_PARAMS
+ SUPPORTED_FILTERS = glance.api.v1.SUPPORTED_FILTERS
+ ACTIVE_IMMUTABLE = glance.api.v1.ACTIVE_IMMUTABLE
++IMMUTABLE = glance.api.v1.IMMUTABLE
+ 
+ CONF = cfg.CONF
+ CONF.import_opt('disk_formats', 'glance.common.config', group='image_format')
+@@ -912,6 +913,14 @@ class Controller(controller.BaseController):
+                                         request=req,
+                                         content_type="text/plain")
+ 
++        for key in IMMUTABLE:
++            if (image_meta.get(key) is not None and
++                    image_meta.get(key) != orig_image_meta.get(key)):
++                msg = _("Forbidden to modify '%s' of image.") % key
++                raise HTTPForbidden(explanation=msg,
++                                    request=req,
++                                    content_type="text/plain")
++
+         # The default behaviour for a PUT /images/<IMAGE_ID> is to
+         # override any properties that were previously set. This, however,
+         # leads to a number of issues for the common use case where a caller
+diff --git a/glance/tests/functional/v1/test_api.py b/glance/tests/functional/v1/test_api.py
+index 9fba3bb5e40c8742530691228c7b436b385fc2ca..6b3bfbb4270f1eb0f50418504e65be30ea23d10b 100644
+--- a/glance/tests/functional/v1/test_api.py
++++ b/glance/tests/functional/v1/test_api.py
+@@ -715,3 +715,92 @@ class TestApi(functional.FunctionalTest):
+         self.assertEqual(404, response.status)
+ 
+         self.stop_servers()
++
++    def test_status_cannot_be_manipulated_directly(self):
++        self.cleanup()
++        self.start_servers(**self.__dict__.copy())
++        headers = minimal_headers('Image1')
++
++        # Create a 'queued' image
++        http = httplib2.Http()
++        headers = {'Content-Type': 'application/octet-stream',
++                   'X-Image-Meta-Disk-Format': 'raw',
++                   'X-Image-Meta-Container-Format': 'bare'}
++        path = "http://%s:%d/v1/images" % ("127.0.0.1", self.api_port)
++        response, content = http.request(path, 'POST', headers=headers,
++                                         body=None)
++        self.assertEqual(201, response.status)
++        image = jsonutils.loads(content)['image']
++        self.assertEqual('queued', image['status'])
++
++        # Ensure status of 'queued' image can't be changed
++        path = "http://%s:%d/v1/images/%s" % ("127.0.0.1", self.api_port,
++                                              image['id'])
++        http = httplib2.Http()
++        headers = {'X-Image-Meta-Status': 'active'}
++        response, content = http.request(path, 'PUT', headers=headers)
++        self.assertEqual(403, response.status)
++        response, content = http.request(path, 'HEAD')
++        self.assertEqual(200, response.status)
++        self.assertEqual('queued', response['x-image-meta-status'])
++
++        # We allow 'setting' to the same status
++        http = httplib2.Http()
++        headers = {'X-Image-Meta-Status': 'queued'}
++        response, content = http.request(path, 'PUT', headers=headers)
++        self.assertEqual(200, response.status)
++        response, content = http.request(path, 'HEAD')
++        self.assertEqual(200, response.status)
++        self.assertEqual('queued', response['x-image-meta-status'])
++
++        # Make image active
++        http = httplib2.Http()
++        headers = {'Content-Type': 'application/octet-stream'}
++        response, content = http.request(path, 'PUT', headers=headers,
++                                         body='data')
++        self.assertEqual(200, response.status)
++        image = jsonutils.loads(content)['image']
++        self.assertEqual('active', image['status'])
++
++        # Ensure status of 'active' image can't be changed
++        http = httplib2.Http()
++        headers = {'X-Image-Meta-Status': 'queued'}
++        response, content = http.request(path, 'PUT', headers=headers)
++        self.assertEqual(403, response.status)
++        response, content = http.request(path, 'HEAD')
++        self.assertEqual(200, response.status)
++        self.assertEqual('active', response['x-image-meta-status'])
++
++        # We allow 'setting' to the same status
++        http = httplib2.Http()
++        headers = {'X-Image-Meta-Status': 'active'}
++        response, content = http.request(path, 'PUT', headers=headers)
++        self.assertEqual(200, response.status)
++        response, content = http.request(path, 'HEAD')
++        self.assertEqual(200, response.status)
++        self.assertEqual('active', response['x-image-meta-status'])
++
++        # Create a 'queued' image, ensure 'status' header is ignored
++        http = httplib2.Http()
++        path = "http://%s:%d/v1/images" % ("127.0.0.1", self.api_port)
++        headers = {'Content-Type': 'application/octet-stream',
++                   'X-Image-Meta-Status': 'active'}
++        response, content = http.request(path, 'POST', headers=headers,
++                                         body=None)
++        self.assertEqual(201, response.status)
++        image = jsonutils.loads(content)['image']
++        self.assertEqual('queued', image['status'])
++
++        # Create an 'active' image, ensure 'status' header is ignored
++        http = httplib2.Http()
++        path = "http://%s:%d/v1/images" % ("127.0.0.1", self.api_port)
++        headers = {'Content-Type': 'application/octet-stream',
++                   'X-Image-Meta-Disk-Format': 'raw',
++                   'X-Image-Meta-Status': 'queued',
++                   'X-Image-Meta-Container-Format': 'bare'}
++        response, content = http.request(path, 'POST', headers=headers,
++                                         body='data')
++        self.assertEqual(201, response.status)
++        image = jsonutils.loads(content)['image']
++        self.assertEqual('active', image['status'])
++        self.stop_servers()
+diff --git a/glance/tests/integration/legacy_functional/test_v1_api.py b/glance/tests/integration/legacy_functional/test_v1_api.py
+index dff436465919569480bdbac537d20a6d61c98f46..511d46dfe18028bb430504784cc9d24c58736c3b 100644
+--- a/glance/tests/integration/legacy_functional/test_v1_api.py
++++ b/glance/tests/integration/legacy_functional/test_v1_api.py
+@@ -358,6 +358,8 @@ class TestApi(base.ApiTest):
+         path = "/v1/images"
+         response, content = self.http.request(path, 'POST', headers=headers)
+         self.assertEqual(201, response.status)
++        image = jsonutils.loads(content)['image']
++        self.assertEqual('active', image['status'])
+ 
+         # 2. HEAD image-location
+         # Verify image size is zero and the status is active
+-- 
+2.5.0
+

diff --git a/app-admin/glance/glance-2015.1.1-r2.ebuild b/app-admin/glance/glance-2015.1.1-r2.ebuild
new file mode 100644
index 0000000..2083b07
--- /dev/null
+++ b/app-admin/glance/glance-2015.1.1-r2.ebuild
@@ -0,0 +1,190 @@
+# Copyright 1999-2015 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id$
+
+EAPI=5
+PYTHON_COMPAT=( python2_7 )
+
+inherit distutils-r1 user
+
+DESCRIPTION="Provides services for discovering, registering, and retrieving
+virtual machine images"
+HOMEPAGE="https://launchpad.net/glance"
+SRC_URI="https://launchpad.net/${PN}/kilo/${PV}/+download/${P}.tar.gz"
+
+LICENSE="Apache-2.0"
+SLOT="0"
+KEYWORDS="~amd64 ~x86"
+IUSE="doc mysql postgres +sqlite +swift test"
+REQUIRED_USE="|| ( mysql postgres sqlite )"
+
+DEPEND="
+		dev-python/setuptools[${PYTHON_USEDEP}]
+		>=dev-python/pbr-0.8.0[${PYTHON_USEDEP}]
+		<dev-python/pbr-1.0[${PYTHON_USEDEP}]
+		test? (
+			${RDEPEND}
+			>=dev-python/hacking-0.10.0[${PYTHON_USEDEP}]
+			<dev-python/hacking-0.11[${PYTHON_USEDEP}]
+			~dev-python/Babel-1.3[${PYTHON_USEDEP}]
+			>=dev-python/coverage-3.6[${PYTHON_USEDEP}]
+			>=dev-python/fixtures-0.3.14[${PYTHON_USEDEP}]
+			<dev-python/fixtures-1.3.0[${PYTHON_USEDEP}]
+			>=dev-python/mock-1.0[${PYTHON_USEDEP}]
+			<dev-python/mock-1.1.0[${PYTHON_USEDEP}]
+			>=dev-python/sphinx-1.1.2[${PYTHON_USEDEP}]
+			!~dev-python/sphinx-1.2.0[${PYTHON_USEDEP}]
+			<dev-python/sphinx-1.3[${PYTHON_USEDEP}]
+			>=dev-python/requests-2.2.0[${PYTHON_USEDEP}]
+			!~dev-python/requests-2.4.0[${PYTHON_USEDEP}]
+			>=dev-python/testrepository-0.0.18[${PYTHON_USEDEP}]
+			>=dev-python/testtools-0.9.36[${PYTHON_USEDEP}]
+			!~dev-python/testtools-1.2.0[${PYTHON_USEDEP}]
+			>=dev-python/psutil-1.1.1[${PYTHON_USEDEP}]
+			<dev-python/psutil-2.0.0[${PYTHON_USEDEP}]
+			>=dev-python/oslotest-1.5.1[${PYTHON_USEDEP}]
+			<dev-python/oslotest-1.6.0[${PYTHON_USEDEP}]
+			dev-python/mysql-python[${PYTHON_USEDEP}]
+			dev-python/psycopg[${PYTHON_USEDEP}]
+			~dev-python/pysendfile-2.0.1[${PYTHON_USEDEP}]
+			dev-python/qpid-python[${PYTHON_USEDEP}]
+			>=dev-python/pyxattr-0.5.0[${PYTHON_USEDEP}]
+			>=dev-python/oslo-sphinx-2.5.0[${PYTHON_USEDEP}]
+			<dev-python/oslo-sphinx-2.6.0[${PYTHON_USEDEP}]
+			>=dev-python/elasticsearch-py-1.3.0[${PYTHON_USEDEP}]
+		)"
+
+#note to self, wsgiref is a python builtin, no need to package it
+#>=dev-python/wsgiref-0.1.2[${PYTHON_USEDEP}]
+
+RDEPEND="
+	>=dev-python/greenlet-0.3.2[${PYTHON_USEDEP}]
+	sqlite? (
+		>=dev-python/sqlalchemy-0.9.7[sqlite,${PYTHON_USEDEP}]
+		<=dev-python/sqlalchemy-0.9.99[sqlite,${PYTHON_USEDEP}]
+	)
+	mysql? (
+		dev-python/mysql-python
+		>=dev-python/sqlalchemy-0.9.7[${PYTHON_USEDEP}]
+		<=dev-python/sqlalchemy-0.9.99[${PYTHON_USEDEP}]
+	)
+	postgres? (
+		dev-python/psycopg:2
+		>=dev-python/sqlalchemy-0.9.7[${PYTHON_USEDEP}]
+		<=dev-python/sqlalchemy-0.9.99[${PYTHON_USEDEP}]
+	)
+	>=dev-python/anyjson-0.3.3[${PYTHON_USEDEP}]
+	>=dev-python/eventlet-0.16.1[${PYTHON_USEDEP}]
+	!~dev-python/eventlet-0.17.0[${PYTHON_USEDEP}]
+	>=dev-python/pastedeploy-1.5.0[${PYTHON_USEDEP}]
+	>=dev-python/routes-1.12.3[${PYTHON_USEDEP}]
+	!~dev-python/routes-2.0[${PYTHON_USEDEP}]
+	>=dev-python/webob-1.2.3[${PYTHON_USEDEP}]
+	>=dev-python/sqlalchemy-migrate-0.9.5[${PYTHON_USEDEP}]
+	>=dev-python/httplib2-0.7.5[${PYTHON_USEDEP}]
+	>=dev-python/kombu-2.5.0[${PYTHON_USEDEP}]
+	>=dev-python/pycrypto-2.6[${PYTHON_USEDEP}]
+	>=dev-python/iso8601-0.1.9[${PYTHON_USEDEP}]
+	dev-python/ordereddict[${PYTHON_USEDEP}]
+	>=dev-python/oslo-config-1.9.3[${PYTHON_USEDEP}]
+	<dev-python/oslo-config-1.10.0[${PYTHON_USEDEP}]
+	>=dev-python/oslo-concurrency-1.8.0[${PYTHON_USEDEP}]
+	<dev-python/oslo-concurrency-1.9.0[${PYTHON_USEDEP}]
+	>=dev-python/oslo-context-0.2.0[${PYTHON_USEDEP}]
+	<dev-python/oslo-context-0.3.0[${PYTHON_USEDEP}]
+	>=dev-python/oslo-utils-1.4.0[${PYTHON_USEDEP}]
+	<dev-python/oslo-utils-1.5.0[${PYTHON_USEDEP}]
+	>=dev-python/stevedore-1.3.0[${PYTHON_USEDEP}]
+	<dev-python/stevedore-1.4.0[${PYTHON_USEDEP}]
+	>=dev-python/taskflow-0.7.1[${PYTHON_USEDEP}]
+	<dev-python/taskflow-0.8.0[${PYTHON_USEDEP}]
+	>=dev-python/keystonemiddleware-1.5.0[${PYTHON_USEDEP}]
+	<dev-python/keystonemiddleware-1.6.0[${PYTHON_USEDEP}]
+	>=dev-python/WSME-0.6[${PYTHON_USEDEP}]
+	<dev-python/WSME-0.7[${PYTHON_USEDEP}]
+	dev-python/posix_ipc[${PYTHON_USEDEP}]
+	swift? (
+		>=dev-python/python-swiftclient-2.2.0[${PYTHON_USEDEP}]
+		<dev-python/python-swiftclient-2.5.0[${PYTHON_USEDEP}]
+	)
+	>=dev-python/oslo-vmware-0.11.1[${PYTHON_USEDEP}]
+	<dev-python/oslo-vmware-0.12.0[${PYTHON_USEDEP}]
+	dev-python/paste[${PYTHON_USEDEP}]
+	>=dev-python/jsonschema-2.0.0[${PYTHON_USEDEP}]
+	<dev-python/jsonschema-3.0.0[${PYTHON_USEDEP}]
+	>=dev-python/python-keystoneclient-1.2.0[${PYTHON_USEDEP}]
+	<dev-python/python-keystoneclient-1.4.0[${PYTHON_USEDEP}]
+	>=dev-python/pyopenssl-0.11[${PYTHON_USEDEP}]
+	>=dev-python/six-1.9.0[${PYTHON_USEDEP}]
+	>=dev-python/oslo-db-1.7.0[${PYTHON_USEDEP}]
+	<dev-python/oslo-db-1.8.0[${PYTHON_USEDEP}]
+	>=dev-python/oslo-i18n-1.5.0[${PYTHON_USEDEP}]
+	<dev-python/oslo-i18n-1.6.0[${PYTHON_USEDEP}]
+	>=dev-python/oslo-log-1.0.0[${PYTHON_USEDEP}]
+	<dev-python/oslo-log-1.1.0[${PYTHON_USEDEP}]
+	>=dev-python/oslo-messaging-1.8.0[${PYTHON_USEDEP}]
+	<dev-python/oslo-messaging-1.9.0[${PYTHON_USEDEP}]
+	>=dev-python/oslo-policy-0.3.1[${PYTHON_USEDEP}]
+	<dev-python/oslo-policy-0.4.0[${PYTHON_USEDEP}]
+	>=dev-python/oslo-serialization-1.4.0[${PYTHON_USEDEP}]
+	<dev-python/oslo-serialization-1.5.0[${PYTHON_USEDEP}]
+	>=dev-python/retrying-1.2.3[${PYTHON_USEDEP}]
+	!~dev-python/retrying-1.3.0[${PYTHON_USEDEP}]
+	>=dev-python/osprofiler-0.3.0[${PYTHON_USEDEP}]
+	>=dev-python/glance_store-0.3.0[${PYTHON_USEDEP}]
+	<dev-python/glance_store-0.5.0[${PYTHON_USEDEP}]
+	>=dev-python/semantic_version-2.3.1[${PYTHON_USEDEP}]
+"
+
+PATCHES=(
+	"${FILESDIR}/cve-2015-5163-stable-kilo.patch"
+	"${FILESDIR}/cve-2015-5251-stable-kilo.patch"
+)
+
+pkg_setup() {
+	enewgroup glance
+	enewuser glance -1 -1 /var/lib/glance glance
+}
+
+python_prepare_all() {
+	sed -i '/xattr/d' test-requirements.txt || die
+	sed -i '/pysendfile/d' test-requirements.txt || die
+	distutils-r1_python_prepare_all
+}
+
+python_compile_all() {
+	use doc && "${PYTHON}" setup.py build_sphinx
+}
+
+python_test() {
+	# https://bugs.launchpad.net/glance/+bug/1251105
+	# https://bugs.launchpad.net/glance/+bug/1242501
+	testr init
+	testr run --parallel || die "failed testsuite under python2.7"
+}
+
+python_install() {
+	distutils-r1_python_install
+
+	for svc in api registry scrubber; do
+		newinitd "${FILESDIR}/glance.initd" glance-${svc}
+	done
+
+	diropts -m 0750 -o glance -g glance
+	dodir /var/log/glance /var/lib/glance/images /var/lib/glance/scrubber
+	keepdir /etc/glance
+	keepdir /var/log/glance
+	keepdir /var/lib/glance/images
+	keepdir /var/lib/glance/scrubber
+
+	insinto /etc/glance
+	insopts -m 0640 -o glance -g glance
+	doins etc/*.ini
+	doins etc/*.conf
+	doins etc/*.sample
+}
+
+python_install_all() {
+	use doc && local HTML_DOCS=( doc/build/html/. )
+	distutils-r1_python_install_all
+}


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [gentoo-commits] repo/gentoo:master commit in: app-admin/glance/files/, app-admin/glance/
@ 2015-10-03 19:14 Matt Thode
  0 siblings, 0 replies; 5+ messages in thread
From: Matt Thode @ 2015-10-03 19:14 UTC (permalink / raw
  To: gentoo-commits

commit:     0cbb7fc1a349f095ff77fea9b8857c57e7c5fd54
Author:     Matthew Thode <prometheanfire <AT> gentoo <DOT> org>
AuthorDate: Sat Oct  3 19:13:15 2015 +0000
Commit:     Matt Thode <prometheanfire <AT> gentoo <DOT> org>
CommitDate: Sat Oct  3 19:13:49 2015 +0000
URL:        https://gitweb.gentoo.org/repo/gentoo.git/commit/?id=0cbb7fc1

app-admin/glance: fixing CVE-2015-5286

Package-Manager: portage-2.2.20.1

 .../glance/files/CVE-2015-3289_2015.1.0.patch      |  50 ------
 .../glance/files/CVE-2015-5286_2015.1.1.patch      | 137 +++++++++++++++
 app-admin/glance/glance-2015.1.1-r3.ebuild         | 191 +++++++++++++++++++++
 3 files changed, 328 insertions(+), 50 deletions(-)

diff --git a/app-admin/glance/files/CVE-2015-3289_2015.1.0.patch b/app-admin/glance/files/CVE-2015-3289_2015.1.0.patch
deleted file mode 100644
index 5b69774..0000000
--- a/app-admin/glance/files/CVE-2015-3289_2015.1.0.patch
+++ /dev/null
@@ -1,50 +0,0 @@
-From 88f92eb11d556bf43e2800a05973ad2da0db0195 Mon Sep 17 00:00:00 2001
-From: Flavio Percoco <flaper87@gmail.com>
-Date: Fri, 8 May 2015 11:44:14 +0200
-Subject: [PATCH] Save image data after setting the data
-
-The image's locations are missing when image's are imported using tasks
-because the ImportToStore task is not saving the image metadata after
-the import. This patch fixes that.
-
-Change-Id: I43dec450d5fc4bee2131d78dbe3c2b2373c3f739
-Closes-bug: #1453068
-(cherry picked from commit 4efb56aae9288952bdb0d368a7c307e8524b80d8)
----
- glance/async/flows/base_import.py            | 4 ++++
- glance/tests/unit/async/flows/test_import.py | 4 ++++
- 2 files changed, 8 insertions(+)
-
-diff --git a/glance/async/flows/base_import.py b/glance/async/flows/base_import.py
-index 487247c..7656bde 100644
---- a/glance/async/flows/base_import.py
-+++ b/glance/async/flows/base_import.py
-@@ -283,6 +283,10 @@ class _ImportToStore(task.Task):
- 
-         image_import.set_image_data(image, file_path or self.uri, None)
- 
-+        # NOTE(flaper87): We need to save the image again after the locations
-+        # have been set in the image.
-+        self.image_repo.save(image)
-+
- 
- class _SaveImage(task.Task):
- 
-diff --git a/glance/tests/unit/async/flows/test_import.py b/glance/tests/unit/async/flows/test_import.py
-index 0f355bc..7acd599 100644
---- a/glance/tests/unit/async/flows/test_import.py
-+++ b/glance/tests/unit/async/flows/test_import.py
-@@ -112,6 +112,10 @@ class TestImportTask(test_utils.BaseTestCase):
-                                           "%s.tasks_import" % image_path)
-             self.assertFalse(os.path.exists(tmp_image_path))
-             self.assertTrue(os.path.exists(image_path))
-+            self.assertEqual(1, len(list(self.image.locations)))
-+            self.assertEqual("file://%s/%s" % (self.test_dir,
-+                                               self.image.image_id),
-+                             self.image.locations[0]['url'])
- 
-     def test_import_flow_missing_work_dir(self):
-         self.config(engine_mode='serial', group='taskflow_executor')
--- 
-2.3.6
-

diff --git a/app-admin/glance/files/CVE-2015-5286_2015.1.1.patch b/app-admin/glance/files/CVE-2015-5286_2015.1.1.patch
new file mode 100644
index 0000000..0478135
--- /dev/null
+++ b/app-admin/glance/files/CVE-2015-5286_2015.1.1.patch
@@ -0,0 +1,137 @@
+From 5bebd513fa71edcdb84f7dec7b16f3523c0c1092 Mon Sep 17 00:00:00 2001
+From: Mike Fedosin <mfedosin@mirantis.com>
+Date: Sun, 20 Sep 2015 17:01:22 +0300
+Subject: Cleanup chunks for deleted image if token expired
+
+In patch I47229b366c25367ec1bd48aec684e0880f3dfe60 it was
+introduced the logic that if image was deleted during file
+upload when we want to update image status from 'saving'
+to 'active' it's expected to get Duplicate error and delete
+stale chunks after that. But if user's token is expired
+there will be Unathorized exception and chunks will stay
+in store and clog it.
+And when, the upload operation for such an image is
+completed the operator configured quota can be exceeded.
+
+This patch fixes the issue of left over chunks for an image
+which was deleted from saving status, by correctly handle
+auth exceptions from registry server.
+
+Partial-bug: #1498163
+
+Conflicts:
+	glance/api/v1/upload_utils.py
+        (Kilo catches NotFound instead of ImagenotFound)
+
+Change-Id: I17a66eca55bfb83107046910e69c4da01415deec
+(cherry picked from commit 98a8832777a0639a4031e52c69f0d565b3f500c5)
+
+diff --git a/glance/api/v1/upload_utils.py b/glance/api/v1/upload_utils.py
+index 7adb2dc..ad4f724 100644
+--- a/glance/api/v1/upload_utils.py
++++ b/glance/api/v1/upload_utils.py
+@@ -171,6 +171,14 @@ def upload_data_to_store(req, image_meta, image_data, store, notifier):
+                     raise exception.NotFound()
+                 else:
+                     raise
++
++        except exception.NotAuthenticated as e:
++            # Delete image data due to possible token expiration.
++            LOG.debug("Authentication error - the token may have "
++                      "expired during file upload. Deleting image data for "
++                      " %s " % image_id)
++            initiate_deletion(req, location_data, image_id)
++            raise webob.exc.HTTPUnauthorized(explanation=e.msg, request=req)
+         except exception.NotFound:
+             msg = _LI("Image %s could not be found after upload. The image may"
+                       " have been deleted during the upload.") % image_id
+diff --git a/glance/api/v2/image_data.py b/glance/api/v2/image_data.py
+index 4025eeb..9967662 100644
+--- a/glance/api/v2/image_data.py
++++ b/glance/api/v2/image_data.py
+@@ -88,7 +88,19 @@ class ImageDataController(object):
+                 raise webob.exc.HTTPGone(explanation=msg,
+                                          request=req,
+                                          content_type='text/plain')
+-
++            except exception.NotAuthenticated:
++                msg = (_("Authentication error - the token may have "
++                         "expired during file upload. Deleting image data for "
++                         "%s.") % image_id)
++                LOG.debug(msg)
++                try:
++                    image.delete()
++                except exception.NotAuthenticated:
++                    # NOTE: Ignore this exception
++                    pass
++                raise webob.exc.HTTPUnauthorized(explanation=msg,
++                                                 request=req,
++                                                 content_type='text/plain')
+         except ValueError as e:
+             LOG.debug("Cannot save data for image %(id)s: %(e)s",
+                       {'id': image_id, 'e': utils.exception_to_str(e)})
+diff --git a/glance/tests/unit/v1/test_upload_utils.py b/glance/tests/unit/v1/test_upload_utils.py
+index 1afaf00..8d05515 100644
+--- a/glance/tests/unit/v1/test_upload_utils.py
++++ b/glance/tests/unit/v1/test_upload_utils.py
+@@ -323,3 +323,29 @@ class TestUploadUtils(base.StoreClearingUnitTest):
+                                   'metadata': {}}, image_meta['id'])
+                         mock_safe_kill.assert_called_once_with(
+                             req, image_meta['id'], 'saving')
++
++    @mock.patch.object(registry, 'update_image_metadata',
++                       side_effect=exception.NotAuthenticated)
++    @mock.patch.object(upload_utils, 'initiate_deletion')
++    def test_activate_image_with_expired_token(
++            self, mocked_delete, mocked_update):
++        """Test token expiration during image upload.
++
++        If users token expired before image was uploaded then if auth error
++        was caught from registry during changing image status from 'saving'
++        to 'active' then it's required to delete all image data.
++        """
++        context = mock.Mock()
++        req = mock.Mock()
++        req.context = context
++        with self._get_store_and_notifier() as (location, checksum, image_meta,
++                                                image_data, store, notifier,
++                                                update_data):
++            self.assertRaises(webob.exc.HTTPUnauthorized,
++                              upload_utils.upload_data_to_store,
++                              req, image_meta, image_data, store, notifier)
++            self.assertEqual(2, mocked_update.call_count)
++            mocked_delete.assert_called_once_with(
++                req,
++                {'url': 'file://foo/bar', 'status': 'active', 'metadata': {}},
++                'c80a1a6c-bd1f-41c5-90ee-81afedb1d58d')
+diff --git a/glance/tests/unit/v2/test_image_data_resource.py b/glance/tests/unit/v2/test_image_data_resource.py
+index bc8891e..7458eda 100644
+--- a/glance/tests/unit/v2/test_image_data_resource.py
++++ b/glance/tests/unit/v2/test_image_data_resource.py
+@@ -192,6 +192,23 @@ class TestImagesController(base.StoreClearingUnitTest):
+         self.assertRaises(webob.exc.HTTPBadRequest, self.controller.upload,
+                           request, unit_test_utils.UUID1, 'YYYY', 4)
+ 
++    def test_upload_with_expired_token(self):
++        def side_effect(image, from_state=None):
++            if from_state == 'saving':
++                raise exception.NotAuthenticated()
++
++        mocked_save = mock.Mock(side_effect=side_effect)
++        mocked_delete = mock.Mock()
++        request = unit_test_utils.get_fake_request()
++        image = FakeImage('abcd')
++        image.delete = mocked_delete
++        self.image_repo.result = image
++        self.image_repo.save = mocked_save
++        self.assertRaises(webob.exc.HTTPUnauthorized, self.controller.upload,
++                          request, unit_test_utils.UUID1, 'YYYY', 4)
++        self.assertEqual(3, mocked_save.call_count)
++        mocked_delete.assert_called_once_with()
++
+     def test_upload_non_existent_image_during_save_initiates_deletion(self):
+         def fake_save_not_found(self):
+             raise exception.NotFound()
+-- 
+cgit v0.10.2
+

diff --git a/app-admin/glance/glance-2015.1.1-r3.ebuild b/app-admin/glance/glance-2015.1.1-r3.ebuild
new file mode 100644
index 0000000..10eda7d
--- /dev/null
+++ b/app-admin/glance/glance-2015.1.1-r3.ebuild
@@ -0,0 +1,191 @@
+# Copyright 1999-2015 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id$
+
+EAPI=5
+PYTHON_COMPAT=( python2_7 )
+
+inherit distutils-r1 user
+
+DESCRIPTION="Provides services for discovering, registering, and retrieving
+virtual machine images"
+HOMEPAGE="https://launchpad.net/glance"
+SRC_URI="https://launchpad.net/${PN}/kilo/${PV}/+download/${P}.tar.gz"
+
+LICENSE="Apache-2.0"
+SLOT="0"
+KEYWORDS="~amd64 ~x86"
+IUSE="doc mysql postgres +sqlite +swift test"
+REQUIRED_USE="|| ( mysql postgres sqlite )"
+
+DEPEND="
+		dev-python/setuptools[${PYTHON_USEDEP}]
+		>=dev-python/pbr-0.8.0[${PYTHON_USEDEP}]
+		<dev-python/pbr-1.0[${PYTHON_USEDEP}]
+		test? (
+			${RDEPEND}
+			>=dev-python/hacking-0.10.0[${PYTHON_USEDEP}]
+			<dev-python/hacking-0.11[${PYTHON_USEDEP}]
+			>=dev-python/Babel-1.3[${PYTHON_USEDEP}]
+			>=dev-python/coverage-3.6[${PYTHON_USEDEP}]
+			>=dev-python/fixtures-0.3.14[${PYTHON_USEDEP}]
+			<dev-python/fixtures-1.3.0[${PYTHON_USEDEP}]
+			>=dev-python/mock-1.0[${PYTHON_USEDEP}]
+			<dev-python/mock-1.1.0[${PYTHON_USEDEP}]
+			>=dev-python/sphinx-1.1.2[${PYTHON_USEDEP}]
+			!~dev-python/sphinx-1.2.0[${PYTHON_USEDEP}]
+			<dev-python/sphinx-1.3[${PYTHON_USEDEP}]
+			>=dev-python/requests-2.2.0[${PYTHON_USEDEP}]
+			!~dev-python/requests-2.4.0[${PYTHON_USEDEP}]
+			>=dev-python/testrepository-0.0.18[${PYTHON_USEDEP}]
+			>=dev-python/testtools-0.9.36[${PYTHON_USEDEP}]
+			!~dev-python/testtools-1.2.0[${PYTHON_USEDEP}]
+			>=dev-python/psutil-1.1.1[${PYTHON_USEDEP}]
+			<dev-python/psutil-2.0.0[${PYTHON_USEDEP}]
+			>=dev-python/oslotest-1.5.1[${PYTHON_USEDEP}]
+			<dev-python/oslotest-1.6.0[${PYTHON_USEDEP}]
+			dev-python/mysql-python[${PYTHON_USEDEP}]
+			dev-python/psycopg[${PYTHON_USEDEP}]
+			~dev-python/pysendfile-2.0.1[${PYTHON_USEDEP}]
+			dev-python/qpid-python[${PYTHON_USEDEP}]
+			>=dev-python/pyxattr-0.5.0[${PYTHON_USEDEP}]
+			>=dev-python/oslo-sphinx-2.5.0[${PYTHON_USEDEP}]
+			<dev-python/oslo-sphinx-2.6.0[${PYTHON_USEDEP}]
+			>=dev-python/elasticsearch-py-1.3.0[${PYTHON_USEDEP}]
+		)"
+
+#note to self, wsgiref is a python builtin, no need to package it
+#>=dev-python/wsgiref-0.1.2[${PYTHON_USEDEP}]
+
+RDEPEND="
+	>=dev-python/greenlet-0.3.2[${PYTHON_USEDEP}]
+	sqlite? (
+		>=dev-python/sqlalchemy-0.9.7[sqlite,${PYTHON_USEDEP}]
+		<=dev-python/sqlalchemy-0.9.99[sqlite,${PYTHON_USEDEP}]
+	)
+	mysql? (
+		dev-python/mysql-python
+		>=dev-python/sqlalchemy-0.9.7[${PYTHON_USEDEP}]
+		<=dev-python/sqlalchemy-0.9.99[${PYTHON_USEDEP}]
+	)
+	postgres? (
+		dev-python/psycopg:2
+		>=dev-python/sqlalchemy-0.9.7[${PYTHON_USEDEP}]
+		<=dev-python/sqlalchemy-0.9.99[${PYTHON_USEDEP}]
+	)
+	>=dev-python/anyjson-0.3.3[${PYTHON_USEDEP}]
+	>=dev-python/eventlet-0.16.1[${PYTHON_USEDEP}]
+	!~dev-python/eventlet-0.17.0[${PYTHON_USEDEP}]
+	>=dev-python/pastedeploy-1.5.0[${PYTHON_USEDEP}]
+	>=dev-python/routes-1.12.3[${PYTHON_USEDEP}]
+	!~dev-python/routes-2.0[${PYTHON_USEDEP}]
+	>=dev-python/webob-1.2.3[${PYTHON_USEDEP}]
+	>=dev-python/sqlalchemy-migrate-0.9.5[${PYTHON_USEDEP}]
+	>=dev-python/httplib2-0.7.5[${PYTHON_USEDEP}]
+	>=dev-python/kombu-2.5.0[${PYTHON_USEDEP}]
+	>=dev-python/pycrypto-2.6[${PYTHON_USEDEP}]
+	>=dev-python/iso8601-0.1.9[${PYTHON_USEDEP}]
+	dev-python/ordereddict[${PYTHON_USEDEP}]
+	>=dev-python/oslo-config-1.9.3[${PYTHON_USEDEP}]
+	<dev-python/oslo-config-1.10.0[${PYTHON_USEDEP}]
+	>=dev-python/oslo-concurrency-1.8.0[${PYTHON_USEDEP}]
+	<dev-python/oslo-concurrency-1.9.0[${PYTHON_USEDEP}]
+	>=dev-python/oslo-context-0.2.0[${PYTHON_USEDEP}]
+	<dev-python/oslo-context-0.3.0[${PYTHON_USEDEP}]
+	>=dev-python/oslo-utils-1.4.0[${PYTHON_USEDEP}]
+	<dev-python/oslo-utils-1.5.0[${PYTHON_USEDEP}]
+	>=dev-python/stevedore-1.3.0[${PYTHON_USEDEP}]
+	<dev-python/stevedore-1.4.0[${PYTHON_USEDEP}]
+	>=dev-python/taskflow-0.7.1[${PYTHON_USEDEP}]
+	<dev-python/taskflow-0.8.0[${PYTHON_USEDEP}]
+	>=dev-python/keystonemiddleware-1.5.0[${PYTHON_USEDEP}]
+	<dev-python/keystonemiddleware-1.6.0[${PYTHON_USEDEP}]
+	>=dev-python/WSME-0.6[${PYTHON_USEDEP}]
+	<dev-python/WSME-0.7[${PYTHON_USEDEP}]
+	dev-python/posix_ipc[${PYTHON_USEDEP}]
+	swift? (
+		>=dev-python/python-swiftclient-2.2.0[${PYTHON_USEDEP}]
+		<dev-python/python-swiftclient-2.5.0[${PYTHON_USEDEP}]
+	)
+	>=dev-python/oslo-vmware-0.11.1[${PYTHON_USEDEP}]
+	<dev-python/oslo-vmware-0.12.0[${PYTHON_USEDEP}]
+	dev-python/paste[${PYTHON_USEDEP}]
+	>=dev-python/jsonschema-2.0.0[${PYTHON_USEDEP}]
+	<dev-python/jsonschema-3.0.0[${PYTHON_USEDEP}]
+	>=dev-python/python-keystoneclient-1.2.0[${PYTHON_USEDEP}]
+	<dev-python/python-keystoneclient-1.4.0[${PYTHON_USEDEP}]
+	>=dev-python/pyopenssl-0.11[${PYTHON_USEDEP}]
+	>=dev-python/six-1.9.0[${PYTHON_USEDEP}]
+	>=dev-python/oslo-db-1.7.0[${PYTHON_USEDEP}]
+	<dev-python/oslo-db-1.8.0[${PYTHON_USEDEP}]
+	>=dev-python/oslo-i18n-1.5.0[${PYTHON_USEDEP}]
+	<dev-python/oslo-i18n-1.6.0[${PYTHON_USEDEP}]
+	>=dev-python/oslo-log-1.0.0[${PYTHON_USEDEP}]
+	<dev-python/oslo-log-1.1.0[${PYTHON_USEDEP}]
+	>=dev-python/oslo-messaging-1.8.0[${PYTHON_USEDEP}]
+	<dev-python/oslo-messaging-1.9.0[${PYTHON_USEDEP}]
+	>=dev-python/oslo-policy-0.3.1[${PYTHON_USEDEP}]
+	<dev-python/oslo-policy-0.4.0[${PYTHON_USEDEP}]
+	>=dev-python/oslo-serialization-1.4.0[${PYTHON_USEDEP}]
+	<dev-python/oslo-serialization-1.5.0[${PYTHON_USEDEP}]
+	>=dev-python/retrying-1.2.3[${PYTHON_USEDEP}]
+	!~dev-python/retrying-1.3.0[${PYTHON_USEDEP}]
+	>=dev-python/osprofiler-0.3.0[${PYTHON_USEDEP}]
+	>=dev-python/glance_store-0.3.0[${PYTHON_USEDEP}]
+	<dev-python/glance_store-0.5.0[${PYTHON_USEDEP}]
+	>=dev-python/semantic_version-2.3.1[${PYTHON_USEDEP}]
+"
+
+PATCHES=(
+	"${FILESDIR}/cve-2015-5163-stable-kilo.patch"
+	"${FILESDIR}/cve-2015-5251-stable-kilo.patch"
+	"${FILESDIR}/CVE-2015-5286_2015.1.1.patch"
+)
+
+pkg_setup() {
+	enewgroup glance
+	enewuser glance -1 -1 /var/lib/glance glance
+}
+
+python_prepare_all() {
+	sed -i '/xattr/d' test-requirements.txt || die
+	sed -i '/pysendfile/d' test-requirements.txt || die
+	distutils-r1_python_prepare_all
+}
+
+python_compile_all() {
+	use doc && "${PYTHON}" setup.py build_sphinx
+}
+
+python_test() {
+	# https://bugs.launchpad.net/glance/+bug/1251105
+	# https://bugs.launchpad.net/glance/+bug/1242501
+	testr init
+	testr run --parallel || die "failed testsuite under python2.7"
+}
+
+python_install() {
+	distutils-r1_python_install
+
+	for svc in api registry scrubber; do
+		newinitd "${FILESDIR}/glance.initd" glance-${svc}
+	done
+
+	diropts -m 0750 -o glance -g glance
+	dodir /var/log/glance /var/lib/glance/images /var/lib/glance/scrubber
+	keepdir /etc/glance
+	keepdir /var/log/glance
+	keepdir /var/lib/glance/images
+	keepdir /var/lib/glance/scrubber
+
+	insinto /etc/glance
+	insopts -m 0640 -o glance -g glance
+	doins etc/*.ini
+	doins etc/*.conf
+	doins etc/*.sample
+}
+
+python_install_all() {
+	use doc && local HTML_DOCS=( doc/build/html/. )
+	distutils-r1_python_install_all
+}


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [gentoo-commits] repo/gentoo:master commit in: app-admin/glance/files/, app-admin/glance/
@ 2016-02-04 17:34 Matt Thode
  0 siblings, 0 replies; 5+ messages in thread
From: Matt Thode @ 2016-02-04 17:34 UTC (permalink / raw
  To: gentoo-commits

commit:     9923cf35ae299d9643c1122dfea857e5f76667f8
Author:     Matthew Thode <prometheanfire <AT> gentoo <DOT> org>
AuthorDate: Thu Feb  4 17:32:33 2016 +0000
Commit:     Matt Thode <prometheanfire <AT> gentoo <DOT> org>
CommitDate: Thu Feb  4 17:33:45 2016 +0000
URL:        https://gitweb.gentoo.org/repo/gentoo.git/commit/?id=9923cf35

app-admin/glance: fix bug 573844 CVE-2016-0757

Package-Manager: portage-2.2.26

 .../glance/files/CVE-2015-5286_2015.1.1.patch      | 137 ---------
 .../glance/files/cve-2015-5163-stable-kilo.patch   | 260 ----------------
 .../glance/files/cve-2015-5251-stable-kilo.patch   | 192 ------------
 .../files/cve-2016-0757-stable-liberty.patch       | 332 +++++++++++++++++++++
 .../files/glance-2013.2-sphinx_mapping.patch       |  12 -
 app-admin/glance/glance-11.0.1-r1.ebuild           | 229 ++++++++++++++
 6 files changed, 561 insertions(+), 601 deletions(-)

diff --git a/app-admin/glance/files/CVE-2015-5286_2015.1.1.patch b/app-admin/glance/files/CVE-2015-5286_2015.1.1.patch
deleted file mode 100644
index 0478135..0000000
--- a/app-admin/glance/files/CVE-2015-5286_2015.1.1.patch
+++ /dev/null
@@ -1,137 +0,0 @@
-From 5bebd513fa71edcdb84f7dec7b16f3523c0c1092 Mon Sep 17 00:00:00 2001
-From: Mike Fedosin <mfedosin@mirantis.com>
-Date: Sun, 20 Sep 2015 17:01:22 +0300
-Subject: Cleanup chunks for deleted image if token expired
-
-In patch I47229b366c25367ec1bd48aec684e0880f3dfe60 it was
-introduced the logic that if image was deleted during file
-upload when we want to update image status from 'saving'
-to 'active' it's expected to get Duplicate error and delete
-stale chunks after that. But if user's token is expired
-there will be Unathorized exception and chunks will stay
-in store and clog it.
-And when, the upload operation for such an image is
-completed the operator configured quota can be exceeded.
-
-This patch fixes the issue of left over chunks for an image
-which was deleted from saving status, by correctly handle
-auth exceptions from registry server.
-
-Partial-bug: #1498163
-
-Conflicts:
-	glance/api/v1/upload_utils.py
-        (Kilo catches NotFound instead of ImagenotFound)
-
-Change-Id: I17a66eca55bfb83107046910e69c4da01415deec
-(cherry picked from commit 98a8832777a0639a4031e52c69f0d565b3f500c5)
-
-diff --git a/glance/api/v1/upload_utils.py b/glance/api/v1/upload_utils.py
-index 7adb2dc..ad4f724 100644
---- a/glance/api/v1/upload_utils.py
-+++ b/glance/api/v1/upload_utils.py
-@@ -171,6 +171,14 @@ def upload_data_to_store(req, image_meta, image_data, store, notifier):
-                     raise exception.NotFound()
-                 else:
-                     raise
-+
-+        except exception.NotAuthenticated as e:
-+            # Delete image data due to possible token expiration.
-+            LOG.debug("Authentication error - the token may have "
-+                      "expired during file upload. Deleting image data for "
-+                      " %s " % image_id)
-+            initiate_deletion(req, location_data, image_id)
-+            raise webob.exc.HTTPUnauthorized(explanation=e.msg, request=req)
-         except exception.NotFound:
-             msg = _LI("Image %s could not be found after upload. The image may"
-                       " have been deleted during the upload.") % image_id
-diff --git a/glance/api/v2/image_data.py b/glance/api/v2/image_data.py
-index 4025eeb..9967662 100644
---- a/glance/api/v2/image_data.py
-+++ b/glance/api/v2/image_data.py
-@@ -88,7 +88,19 @@ class ImageDataController(object):
-                 raise webob.exc.HTTPGone(explanation=msg,
-                                          request=req,
-                                          content_type='text/plain')
--
-+            except exception.NotAuthenticated:
-+                msg = (_("Authentication error - the token may have "
-+                         "expired during file upload. Deleting image data for "
-+                         "%s.") % image_id)
-+                LOG.debug(msg)
-+                try:
-+                    image.delete()
-+                except exception.NotAuthenticated:
-+                    # NOTE: Ignore this exception
-+                    pass
-+                raise webob.exc.HTTPUnauthorized(explanation=msg,
-+                                                 request=req,
-+                                                 content_type='text/plain')
-         except ValueError as e:
-             LOG.debug("Cannot save data for image %(id)s: %(e)s",
-                       {'id': image_id, 'e': utils.exception_to_str(e)})
-diff --git a/glance/tests/unit/v1/test_upload_utils.py b/glance/tests/unit/v1/test_upload_utils.py
-index 1afaf00..8d05515 100644
---- a/glance/tests/unit/v1/test_upload_utils.py
-+++ b/glance/tests/unit/v1/test_upload_utils.py
-@@ -323,3 +323,29 @@ class TestUploadUtils(base.StoreClearingUnitTest):
-                                   'metadata': {}}, image_meta['id'])
-                         mock_safe_kill.assert_called_once_with(
-                             req, image_meta['id'], 'saving')
-+
-+    @mock.patch.object(registry, 'update_image_metadata',
-+                       side_effect=exception.NotAuthenticated)
-+    @mock.patch.object(upload_utils, 'initiate_deletion')
-+    def test_activate_image_with_expired_token(
-+            self, mocked_delete, mocked_update):
-+        """Test token expiration during image upload.
-+
-+        If users token expired before image was uploaded then if auth error
-+        was caught from registry during changing image status from 'saving'
-+        to 'active' then it's required to delete all image data.
-+        """
-+        context = mock.Mock()
-+        req = mock.Mock()
-+        req.context = context
-+        with self._get_store_and_notifier() as (location, checksum, image_meta,
-+                                                image_data, store, notifier,
-+                                                update_data):
-+            self.assertRaises(webob.exc.HTTPUnauthorized,
-+                              upload_utils.upload_data_to_store,
-+                              req, image_meta, image_data, store, notifier)
-+            self.assertEqual(2, mocked_update.call_count)
-+            mocked_delete.assert_called_once_with(
-+                req,
-+                {'url': 'file://foo/bar', 'status': 'active', 'metadata': {}},
-+                'c80a1a6c-bd1f-41c5-90ee-81afedb1d58d')
-diff --git a/glance/tests/unit/v2/test_image_data_resource.py b/glance/tests/unit/v2/test_image_data_resource.py
-index bc8891e..7458eda 100644
---- a/glance/tests/unit/v2/test_image_data_resource.py
-+++ b/glance/tests/unit/v2/test_image_data_resource.py
-@@ -192,6 +192,23 @@ class TestImagesController(base.StoreClearingUnitTest):
-         self.assertRaises(webob.exc.HTTPBadRequest, self.controller.upload,
-                           request, unit_test_utils.UUID1, 'YYYY', 4)
- 
-+    def test_upload_with_expired_token(self):
-+        def side_effect(image, from_state=None):
-+            if from_state == 'saving':
-+                raise exception.NotAuthenticated()
-+
-+        mocked_save = mock.Mock(side_effect=side_effect)
-+        mocked_delete = mock.Mock()
-+        request = unit_test_utils.get_fake_request()
-+        image = FakeImage('abcd')
-+        image.delete = mocked_delete
-+        self.image_repo.result = image
-+        self.image_repo.save = mocked_save
-+        self.assertRaises(webob.exc.HTTPUnauthorized, self.controller.upload,
-+                          request, unit_test_utils.UUID1, 'YYYY', 4)
-+        self.assertEqual(3, mocked_save.call_count)
-+        mocked_delete.assert_called_once_with()
-+
-     def test_upload_non_existent_image_during_save_initiates_deletion(self):
-         def fake_save_not_found(self):
-             raise exception.NotFound()
--- 
-cgit v0.10.2
-

diff --git a/app-admin/glance/files/cve-2015-5163-stable-kilo.patch b/app-admin/glance/files/cve-2015-5163-stable-kilo.patch
deleted file mode 100644
index 91507c9..0000000
--- a/app-admin/glance/files/cve-2015-5163-stable-kilo.patch
+++ /dev/null
@@ -1,260 +0,0 @@
-From eb99e45829a1b4c93db5692bdbf636a86faa56c4 Mon Sep 17 00:00:00 2001
-From: Flavio Percoco <flaper87@gmail.com>
-Date: Thu, 9 Jul 2015 14:44:04 +0200
-Subject: Don't import files with backed files
-
-There's a security issue where it'd be possible to import images with
-backed files using the task engine and then use/convert those to access
-system files or any other file in the system. An example of an attack
-would be to import an image with a backing file pointing to
-`/etc/passwd`, then convert it to raw and download the generated image.
-
-This patch forbids importing files with baking files entirely. It does
-that in the `_ImportToFS` task, which is the one that imports the image
-locally to then execute other tasks on it. It's not necessary for the
-`_ImportToStore` task because other tasks won't be executed when the
-image is imported in the final store.
-
-Change-Id: I35f43c3b3f326942fb53b7dadb94700ac4513494
-Closes-bug: #1471912
-(cherry picked from commit d529863a1e8d2307526bdb395b4aebe97f81603d)
-
-diff --git a/glance/async/flows/base_import.py b/glance/async/flows/base_import.py
-index 7656bde..d216aa8 100644
---- a/glance/async/flows/base_import.py
-+++ b/glance/async/flows/base_import.py
-@@ -13,12 +13,15 @@
- #    License for the specific language governing permissions and limitations
- #    under the License.
- 
-+import json
- import logging
- import os
- 
- import glance_store as store_api
- from glance_store import backend
-+from oslo_concurrency import processutils as putils
- from oslo_config import cfg
-+from oslo_utils import excutils
- import six
- from stevedore import named
- from taskflow.patterns import linear_flow as lf
-@@ -146,6 +149,29 @@ class _ImportToFS(task.Task):
-         data = script_utils.get_image_data_iter(self.uri)
- 
-         path = self.store.add(image_id, data, 0, context=None)[0]
-+
-+        try:
-+            # NOTE(flaper87): Consider moving this code to a common
-+            # place that other tasks can consume as well.
-+            stdout, stderr = putils.trycmd('qemu-img', 'info',
-+                                           '--output=json', path,
-+                                           log_errors=putils.LOG_ALL_ERRORS)
-+        except OSError as exc:
-+            with excutils.save_and_reraise_exception():
-+                msg = (_LE('Failed to execute security checks on the image '
-+                           '%(task_id)s: %(exc)s') %
-+                       {'task_id': self.task_id, 'exc': exc.message})
-+                LOG.error(msg)
-+
-+        metadata = json.loads(stdout)
-+
-+        backing_file = metadata.get('backing-filename')
-+        if backing_file is not None:
-+            msg = _("File %(path)s has invalid backing file "
-+                    "%(bfile)s, aborting.") % {'path': path,
-+                                               'bfile': backing_file}
-+            raise RuntimeError(msg)
-+
-         return path
- 
-     def revert(self, image_id, result=None, **kwargs):
-diff --git a/glance/tests/unit/async/flows/test_import.py b/glance/tests/unit/async/flows/test_import.py
-index 70f790c..4cf3d13 100644
---- a/glance/tests/unit/async/flows/test_import.py
-+++ b/glance/tests/unit/async/flows/test_import.py
-@@ -13,14 +13,17 @@
- #    License for the specific language governing permissions and limitations
- #    under the License.
- 
-+import json
- import mock
- import os
- import urllib2
- 
- import glance_store
-+from oslo_concurrency import processutils as putils
- from oslo_config import cfg
- from six.moves import cStringIO
- from taskflow import task
-+from taskflow.types import failure
- 
- import glance.async.flows.base_import as import_flow
- from glance.async import taskflow_executor
-@@ -106,16 +109,23 @@ class TestImportTask(test_utils.BaseTestCase):
- 
-         with mock.patch.object(script_utils, 'get_image_data_iter') as dmock:
-             dmock.return_value = cStringIO("TEST_IMAGE")
--            executor.begin_processing(self.task.task_id)
--            image_path = os.path.join(self.test_dir, self.image.image_id)
--            tmp_image_path = os.path.join(self.work_dir,
--                                          "%s.tasks_import" % image_path)
--            self.assertFalse(os.path.exists(tmp_image_path))
--            self.assertTrue(os.path.exists(image_path))
--            self.assertEqual(1, len(list(self.image.locations)))
--            self.assertEqual("file://%s/%s" % (self.test_dir,
--                                               self.image.image_id),
--                             self.image.locations[0]['url'])
-+
-+            with mock.patch.object(putils, 'trycmd') as tmock:
-+                tmock.return_value = (json.dumps({
-+                    'format': 'qcow2',
-+                }), None)
-+
-+                executor.begin_processing(self.task.task_id)
-+                image_path = os.path.join(self.test_dir, self.image.image_id)
-+                tmp_image_path = os.path.join(self.work_dir,
-+                                              "%s.tasks_import" % image_path)
-+
-+                self.assertFalse(os.path.exists(tmp_image_path))
-+                self.assertTrue(os.path.exists(image_path))
-+                self.assertEqual(1, len(list(self.image.locations)))
-+                self.assertEqual("file://%s/%s" % (self.test_dir,
-+                                                   self.image.image_id),
-+                                 self.image.locations[0]['url'])
- 
-     def test_import_flow_missing_work_dir(self):
-         self.config(engine_mode='serial', group='taskflow_executor')
-@@ -151,6 +161,54 @@ class TestImportTask(test_utils.BaseTestCase):
-                 self.assertFalse(os.path.exists(tmp_image_path))
-                 self.assertTrue(os.path.exists(image_path))
- 
-+    def test_import_flow_backed_file_import_to_fs(self):
-+        self.config(engine_mode='serial', group='taskflow_executor')
-+
-+        img_factory = mock.MagicMock()
-+
-+        executor = taskflow_executor.TaskExecutor(
-+            self.context,
-+            self.task_repo,
-+            self.img_repo,
-+            img_factory)
-+
-+        self.task_repo.get.return_value = self.task
-+
-+        def create_image(*args, **kwargs):
-+            kwargs['image_id'] = UUID1
-+            return self.img_factory.new_image(*args, **kwargs)
-+
-+        self.img_repo.get.return_value = self.image
-+        img_factory.new_image.side_effect = create_image
-+
-+        with mock.patch.object(script_utils, 'get_image_data_iter') as dmock:
-+            dmock.return_value = cStringIO("TEST_IMAGE")
-+
-+            with mock.patch.object(putils, 'trycmd') as tmock:
-+                tmock.return_value = (json.dumps({
-+                    'backing-filename': '/etc/password'
-+                }), None)
-+
-+                with mock.patch.object(import_flow._ImportToFS,
-+                                       'revert') as rmock:
-+                    self.assertRaises(RuntimeError,
-+                                      executor.begin_processing,
-+                                      self.task.task_id)
-+                    self.assertTrue(rmock.called)
-+                    self.assertIsInstance(rmock.call_args[1]['result'],
-+                                          failure.Failure)
-+
-+                    image_path = os.path.join(self.test_dir,
-+                                              self.image.image_id)
-+
-+                    fname = "%s.tasks_import" % image_path
-+                    tmp_image_path = os.path.join(self.work_dir, fname)
-+
-+                    self.assertFalse(os.path.exists(tmp_image_path))
-+                    # Note(sabari): The image should not have been uploaded to
-+                    # the store as the flow failed before ImportToStore Task.
-+                    self.assertFalse(os.path.exists(image_path))
-+
-     def test_import_flow_revert(self):
-         self.config(engine_mode='serial',
-                     group='taskflow_executor')
-@@ -175,20 +233,31 @@ class TestImportTask(test_utils.BaseTestCase):
-         with mock.patch.object(script_utils, 'get_image_data_iter') as dmock:
-             dmock.return_value = cStringIO("TEST_IMAGE")
- 
--            with mock.patch.object(import_flow, "_get_import_flows") as imock:
--                imock.return_value = (x for x in [_ErrorTask()])
--                self.assertRaises(RuntimeError,
--                                  executor.begin_processing, self.task.task_id)
--                image_path = os.path.join(self.test_dir, self.image.image_id)
--                tmp_image_path = os.path.join(self.work_dir,
--                                              "%s.tasks_import" % image_path)
--                self.assertFalse(os.path.exists(tmp_image_path))
--
--                # NOTE(flaper87): Eventually, we want this to be assertTrue.
--                # The current issue is there's no way to tell taskflow to
--                # continue on failures. That is, revert the subflow but keep
--                # executing the parent flow. Under discussion/development.
--                self.assertFalse(os.path.exists(image_path))
-+            with mock.patch.object(putils, 'trycmd') as tmock:
-+                tmock.return_value = (json.dumps({
-+                    'format': 'qcow2',
-+                }), None)
-+
-+                with mock.patch.object(import_flow,
-+                                       "_get_import_flows") as imock:
-+                    imock.return_value = (x for x in [_ErrorTask()])
-+                    self.assertRaises(RuntimeError,
-+                                      executor.begin_processing,
-+                                      self.task.task_id)
-+
-+                    image_path = os.path.join(self.test_dir,
-+                                              self.image.image_id)
-+                    tmp_image_path = os.path.join(self.work_dir,
-+                                                  ("%s.tasks_import" %
-+                                                   image_path))
-+                    self.assertFalse(os.path.exists(tmp_image_path))
-+
-+                    # NOTE(flaper87): Eventually, we want this to be assertTrue
-+                    # The current issue is there's no way to tell taskflow to
-+                    # continue on failures. That is, revert the subflow but
-+                    # keep executing the parent flow. Under
-+                    # discussion/development.
-+                    self.assertFalse(os.path.exists(image_path))
- 
-     def test_import_flow_no_import_flows(self):
-         self.config(engine_mode='serial',
-@@ -271,15 +340,20 @@ class TestImportTask(test_utils.BaseTestCase):
-         with mock.patch.object(script_utils, 'get_image_data_iter') as dmock:
-             dmock.return_value = "test"
- 
--            image_id = UUID1
--            path = import_fs.execute(image_id)
--            reader, size = glance_store.get_from_backend(path)
--            self.assertEqual(4, size)
--            self.assertEqual(dmock.return_value, "".join(reader))
-+            with mock.patch.object(putils, 'trycmd') as tmock:
-+                tmock.return_value = (json.dumps({
-+                    'format': 'qcow2',
-+                }), None)
-+
-+                image_id = UUID1
-+                path = import_fs.execute(image_id)
-+                reader, size = glance_store.get_from_backend(path)
-+                self.assertEqual(4, size)
-+                self.assertEqual(dmock.return_value, "".join(reader))
- 
--            image_path = os.path.join(self.work_dir, image_id)
--            tmp_image_path = os.path.join(self.work_dir, image_path)
--            self.assertTrue(os.path.exists(tmp_image_path))
-+                image_path = os.path.join(self.work_dir, image_id)
-+                tmp_image_path = os.path.join(self.work_dir, image_path)
-+                self.assertTrue(os.path.exists(tmp_image_path))
- 
-     def test_delete_from_fs(self):
-         delete_fs = import_flow._DeleteFromFS(self.task.task_id,
--- 
-cgit v0.10.2
-

diff --git a/app-admin/glance/files/cve-2015-5251-stable-kilo.patch b/app-admin/glance/files/cve-2015-5251-stable-kilo.patch
deleted file mode 100644
index f868645..0000000
--- a/app-admin/glance/files/cve-2015-5251-stable-kilo.patch
+++ /dev/null
@@ -1,192 +0,0 @@
-From 9beca533f42ae1fc87418de0c360e19bc59b24b5 Mon Sep 17 00:00:00 2001
-From: Stuart McLaren <stuart.mclaren@hp.com>
-Date: Tue, 11 Aug 2015 10:37:09 +0000
-Subject: [PATCH] Prevent image status being directly modified via v1
-
-Users shouldn't be able to change an image's status directly via the
-v1 API.
-
-Some existing consumers of Glance set the x-image-meta-status header in
-requests to the Glance API, eg:
-
-https://github.com/openstack/nova/blob/master/plugins/xenserver/xenapi/etc/xapi.d/plugins/glance#L184
-
-We should try to prevent users setting 'status' via v1, but without breaking
-existing benign API calls such as these.
-
-I've adopted the following approach (which has some prior art in 'protected properties').
-
-If a PUT request is received which contains an x-image-meta-status header:
-
-* The user provided status is ignored if it matches the current image
-  status (this prevents benign calls such as the nova one above from
-  breaking). The usual code (eg 200) will be returned.
-
-* If the user provided status doesn't match the current image status (ie
-  there is a real attempt to change the value) 403 will be returned. This
-  will break any calls which currently intentionally change the status.
-
-APIImpact
-
-Closes-bug: 1482371
-
-Change-Id: I44fadf32abb57c962b67467091c3f51c1ccc25e6
-(cherry picked from commit 4d08db5b6d42323ac1958ef3b7417d875e7bea8c)
----
- glance/api/v1/__init__.py                          |  3 +
- glance/api/v1/images.py                            |  9 +++
- glance/tests/functional/v1/test_api.py             | 89 ++++++++++++++++++++++
- .../integration/legacy_functional/test_v1_api.py   |  2 +
- 4 files changed, 103 insertions(+)
-
-diff --git a/glance/api/v1/__init__.py b/glance/api/v1/__init__.py
-index 74de9aa1411d8e926770b67f7d851cf14e794414..9306bbb4fe78f77a26bb539c717fdfd2b38767c8 100644
---- a/glance/api/v1/__init__.py
-+++ b/glance/api/v1/__init__.py
-@@ -21,3 +21,6 @@ SUPPORTED_PARAMS = ('limit', 'marker', 'sort_key', 'sort_dir')
- 
- # Metadata which only an admin can change once the image is active
- ACTIVE_IMMUTABLE = ('size', 'checksum')
-+
-+# Metadata which cannot be changed (irrespective of the current image state)
-+IMMUTABLE = ('status',)
-diff --git a/glance/api/v1/images.py b/glance/api/v1/images.py
-index e33b91fbca79377e78ccfd329fa542ad422f5ffc..95e32949d958d0f57a3b60c141b91784a5801f5a 100644
---- a/glance/api/v1/images.py
-+++ b/glance/api/v1/images.py
-@@ -57,6 +57,7 @@ _LW = i18n._LW
- SUPPORTED_PARAMS = glance.api.v1.SUPPORTED_PARAMS
- SUPPORTED_FILTERS = glance.api.v1.SUPPORTED_FILTERS
- ACTIVE_IMMUTABLE = glance.api.v1.ACTIVE_IMMUTABLE
-+IMMUTABLE = glance.api.v1.IMMUTABLE
- 
- CONF = cfg.CONF
- CONF.import_opt('disk_formats', 'glance.common.config', group='image_format')
-@@ -912,6 +913,14 @@ class Controller(controller.BaseController):
-                                         request=req,
-                                         content_type="text/plain")
- 
-+        for key in IMMUTABLE:
-+            if (image_meta.get(key) is not None and
-+                    image_meta.get(key) != orig_image_meta.get(key)):
-+                msg = _("Forbidden to modify '%s' of image.") % key
-+                raise HTTPForbidden(explanation=msg,
-+                                    request=req,
-+                                    content_type="text/plain")
-+
-         # The default behaviour for a PUT /images/<IMAGE_ID> is to
-         # override any properties that were previously set. This, however,
-         # leads to a number of issues for the common use case where a caller
-diff --git a/glance/tests/functional/v1/test_api.py b/glance/tests/functional/v1/test_api.py
-index 9fba3bb5e40c8742530691228c7b436b385fc2ca..6b3bfbb4270f1eb0f50418504e65be30ea23d10b 100644
---- a/glance/tests/functional/v1/test_api.py
-+++ b/glance/tests/functional/v1/test_api.py
-@@ -715,3 +715,92 @@ class TestApi(functional.FunctionalTest):
-         self.assertEqual(404, response.status)
- 
-         self.stop_servers()
-+
-+    def test_status_cannot_be_manipulated_directly(self):
-+        self.cleanup()
-+        self.start_servers(**self.__dict__.copy())
-+        headers = minimal_headers('Image1')
-+
-+        # Create a 'queued' image
-+        http = httplib2.Http()
-+        headers = {'Content-Type': 'application/octet-stream',
-+                   'X-Image-Meta-Disk-Format': 'raw',
-+                   'X-Image-Meta-Container-Format': 'bare'}
-+        path = "http://%s:%d/v1/images" % ("127.0.0.1", self.api_port)
-+        response, content = http.request(path, 'POST', headers=headers,
-+                                         body=None)
-+        self.assertEqual(201, response.status)
-+        image = jsonutils.loads(content)['image']
-+        self.assertEqual('queued', image['status'])
-+
-+        # Ensure status of 'queued' image can't be changed
-+        path = "http://%s:%d/v1/images/%s" % ("127.0.0.1", self.api_port,
-+                                              image['id'])
-+        http = httplib2.Http()
-+        headers = {'X-Image-Meta-Status': 'active'}
-+        response, content = http.request(path, 'PUT', headers=headers)
-+        self.assertEqual(403, response.status)
-+        response, content = http.request(path, 'HEAD')
-+        self.assertEqual(200, response.status)
-+        self.assertEqual('queued', response['x-image-meta-status'])
-+
-+        # We allow 'setting' to the same status
-+        http = httplib2.Http()
-+        headers = {'X-Image-Meta-Status': 'queued'}
-+        response, content = http.request(path, 'PUT', headers=headers)
-+        self.assertEqual(200, response.status)
-+        response, content = http.request(path, 'HEAD')
-+        self.assertEqual(200, response.status)
-+        self.assertEqual('queued', response['x-image-meta-status'])
-+
-+        # Make image active
-+        http = httplib2.Http()
-+        headers = {'Content-Type': 'application/octet-stream'}
-+        response, content = http.request(path, 'PUT', headers=headers,
-+                                         body='data')
-+        self.assertEqual(200, response.status)
-+        image = jsonutils.loads(content)['image']
-+        self.assertEqual('active', image['status'])
-+
-+        # Ensure status of 'active' image can't be changed
-+        http = httplib2.Http()
-+        headers = {'X-Image-Meta-Status': 'queued'}
-+        response, content = http.request(path, 'PUT', headers=headers)
-+        self.assertEqual(403, response.status)
-+        response, content = http.request(path, 'HEAD')
-+        self.assertEqual(200, response.status)
-+        self.assertEqual('active', response['x-image-meta-status'])
-+
-+        # We allow 'setting' to the same status
-+        http = httplib2.Http()
-+        headers = {'X-Image-Meta-Status': 'active'}
-+        response, content = http.request(path, 'PUT', headers=headers)
-+        self.assertEqual(200, response.status)
-+        response, content = http.request(path, 'HEAD')
-+        self.assertEqual(200, response.status)
-+        self.assertEqual('active', response['x-image-meta-status'])
-+
-+        # Create a 'queued' image, ensure 'status' header is ignored
-+        http = httplib2.Http()
-+        path = "http://%s:%d/v1/images" % ("127.0.0.1", self.api_port)
-+        headers = {'Content-Type': 'application/octet-stream',
-+                   'X-Image-Meta-Status': 'active'}
-+        response, content = http.request(path, 'POST', headers=headers,
-+                                         body=None)
-+        self.assertEqual(201, response.status)
-+        image = jsonutils.loads(content)['image']
-+        self.assertEqual('queued', image['status'])
-+
-+        # Create an 'active' image, ensure 'status' header is ignored
-+        http = httplib2.Http()
-+        path = "http://%s:%d/v1/images" % ("127.0.0.1", self.api_port)
-+        headers = {'Content-Type': 'application/octet-stream',
-+                   'X-Image-Meta-Disk-Format': 'raw',
-+                   'X-Image-Meta-Status': 'queued',
-+                   'X-Image-Meta-Container-Format': 'bare'}
-+        response, content = http.request(path, 'POST', headers=headers,
-+                                         body='data')
-+        self.assertEqual(201, response.status)
-+        image = jsonutils.loads(content)['image']
-+        self.assertEqual('active', image['status'])
-+        self.stop_servers()
-diff --git a/glance/tests/integration/legacy_functional/test_v1_api.py b/glance/tests/integration/legacy_functional/test_v1_api.py
-index dff436465919569480bdbac537d20a6d61c98f46..511d46dfe18028bb430504784cc9d24c58736c3b 100644
---- a/glance/tests/integration/legacy_functional/test_v1_api.py
-+++ b/glance/tests/integration/legacy_functional/test_v1_api.py
-@@ -358,6 +358,8 @@ class TestApi(base.ApiTest):
-         path = "/v1/images"
-         response, content = self.http.request(path, 'POST', headers=headers)
-         self.assertEqual(201, response.status)
-+        image = jsonutils.loads(content)['image']
-+        self.assertEqual('active', image['status'])
- 
-         # 2. HEAD image-location
-         # Verify image size is zero and the status is active
--- 
-2.5.0
-

diff --git a/app-admin/glance/files/cve-2016-0757-stable-liberty.patch b/app-admin/glance/files/cve-2016-0757-stable-liberty.patch
new file mode 100644
index 0000000..19c8365
--- /dev/null
+++ b/app-admin/glance/files/cve-2016-0757-stable-liberty.patch
@@ -0,0 +1,332 @@
+From c6021e9b3642340036347026a3f251e066e53094 Mon Sep 17 00:00:00 2001
+From: Erno Kuvaja <jokke@usr.fi>
+Date: Tue, 19 Jan 2016 13:37:05 +0000
+Subject: [PATCH] Prevent user to remove last location of the image
+
+If the last location of the image is removed, image transitions back to queued.
+This allows user to upload new data into the existing image record. By
+preventing removal of the last location we prevent the image transition back to
+queued.
+
+This change also prevents doing the same operation via replacing the locations
+with empty list.
+
+SecurityImpact
+DocImpact
+APIImpact
+
+Conflicts:
+	glance/tests/unit/v2/test_images_resource.py
+
+Change-Id: Ieb03aaba887492819f9c58aa67f7acfcea81720e
+Closes-Bug: #1525915
+(cherry picked from commit 2f4504da2149697bcdb93ed855e15025d2a08f8c)
+---
+ glance/api/v2/images.py                            |  19 +++-
+ glance/tests/functional/v2/test_images.py          |  14 ---
+ glance/tests/unit/v2/test_images_resource.py       | 122 ++++-----------------
+ ...oving-last-image-location-d5ee3e00efe14f34.yaml |  10 ++
+ 4 files changed, 44 insertions(+), 121 deletions(-)
+ create mode 100644 releasenotes/notes/Prevent-removing-last-image-location-d5ee3e00efe14f34.yaml
+
+diff --git a/glance/api/v2/images.py b/glance/api/v2/images.py
+index 17678f2..cf667bf 100644
+--- a/glance/api/v2/images.py
++++ b/glance/api/v2/images.py
+@@ -181,7 +181,10 @@ class ImagesController(object):
+         path = change['path']
+         path_root = path[0]
+         value = change['value']
+-        if path_root == 'locations':
++        if path_root == 'locations' and value == []:
++            msg = _("Cannot set locations to empty list.")
++            raise webob.exc.HTTPForbidden(message=msg)
++        elif path_root == 'locations' and value != []:
+             self._do_replace_locations(image, value)
+         elif path_root == 'owner' and req.context.is_admin == False:
+             msg = _("Owner can't be updated by non admin.")
+@@ -217,7 +220,10 @@ class ImagesController(object):
+         path = change['path']
+         path_root = path[0]
+         if path_root == 'locations':
+-            self._do_remove_locations(image, path[1])
++            try:
++                self._do_remove_locations(image, path[1])
++            except exception.Forbidden as e:
++                raise webob.exc.HTTPForbidden(e.msg)
+         else:
+             if hasattr(image, path_root):
+                 msg = _("Property %s may not be removed.")
+@@ -306,6 +312,11 @@ class ImagesController(object):
+                 explanation=encodeutils.exception_to_unicode(ve))
+ 
+     def _do_remove_locations(self, image, path_pos):
++        if len(image.locations) == 1:
++            LOG.debug("User forbidden to remove last location of image %s",
++                      image.image_id)
++            msg = _("Cannot remove last location in the image.")
++            raise exception.Forbidden(message=msg)
+         pos = self._get_locations_op_pos(path_pos,
+                                          len(image.locations), False)
+         if pos is None:
+@@ -315,11 +326,11 @@ class ImagesController(object):
+             # NOTE(zhiyan): this actually deletes the location
+             # from the backend store.
+             image.locations.pop(pos)
++        # TODO(jokke): Fix this, we should catch what store throws and
++        # provide definitely something else than IternalServerError to user.
+         except Exception as e:
+             raise webob.exc.HTTPInternalServerError(
+                 explanation=encodeutils.exception_to_unicode(e))
+-        if len(image.locations) == 0 and image.status == 'active':
+-            image.status = 'queued'
+ 
+ 
+ class RequestDeserializer(wsgi.JSONRequestDeserializer):
+diff --git a/glance/tests/functional/v2/test_images.py b/glance/tests/functional/v2/test_images.py
+index aabc567..f199787 100644
+--- a/glance/tests/functional/v2/test_images.py
++++ b/glance/tests/functional/v2/test_images.py
+@@ -522,20 +522,6 @@ class TestImages(functional.FunctionalTest):
+         response = requests.patch(path, headers=headers, data=data)
+         self.assertEqual(200, response.status_code, response.text)
+ 
+-        # Remove all locations of the image then the image size shouldn't be
+-        # able to access
+-        path = self._url('/v2/images/%s' % image2_id)
+-        media_type = 'application/openstack-images-v2.1-json-patch'
+-        headers = self._headers({'content-type': media_type})
+-        doc = [{'op': 'replace', 'path': '/locations', 'value': []}]
+-        data = jsonutils.dumps(doc)
+-        response = requests.patch(path, headers=headers, data=data)
+-        self.assertEqual(200, response.status_code, response.text)
+-        image = jsonutils.loads(response.text)
+-        self.assertIsNone(image['size'])
+-        self.assertIsNone(image['virtual_size'])
+-        self.assertEqual('queued', image['status'])
+-
+         # Deletion should work. Deleting image-1
+         path = self._url('/v2/images/%s' % image_id)
+         response = requests.delete(path, headers=self._headers())
+diff --git a/glance/tests/unit/v2/test_images_resource.py b/glance/tests/unit/v2/test_images_resource.py
+index 698c284..ee09ee7 100644
+--- a/glance/tests/unit/v2/test_images_resource.py
++++ b/glance/tests/unit/v2/test_images_resource.py
+@@ -1417,26 +1417,6 @@ class TestImagesController(base.IsolatedUnitTest):
+         self.assertRaises(webob.exc.HTTPConflict, self.controller.update,
+                           another_request, created_image.image_id, changes)
+ 
+-    def test_update_replace_locations(self):
+-        self.stubs.Set(store, 'get_size_from_backend',
+-                       unit_test_utils.fake_get_size_from_backend)
+-        request = unit_test_utils.get_fake_request()
+-        changes = [{'op': 'replace', 'path': ['locations'], 'value': []}]
+-        output = self.controller.update(request, UUID1, changes)
+-        self.assertEqual(UUID1, output.image_id)
+-        self.assertEqual(0, len(output.locations))
+-        self.assertEqual('queued', output.status)
+-        self.assertIsNone(output.size)
+-
+-        new_location = {'url': '%s/fake_location' % BASE_URI, 'metadata': {}}
+-        changes = [{'op': 'replace', 'path': ['locations'],
+-                    'value': [new_location]}]
+-        output = self.controller.update(request, UUID1, changes)
+-        self.assertEqual(UUID1, output.image_id)
+-        self.assertEqual(1, len(output.locations))
+-        self.assertEqual(new_location, output.locations[0])
+-        self.assertEqual('active', output.status)
+-
+     def test_update_replace_locations_non_empty(self):
+         new_location = {'url': '%s/fake_location' % BASE_URI, 'metadata': {}}
+         request = unit_test_utils.get_fake_request()
+@@ -1448,35 +1428,9 @@ class TestImagesController(base.IsolatedUnitTest):
+     def test_update_replace_locations_invalid(self):
+         request = unit_test_utils.get_fake_request()
+         changes = [{'op': 'replace', 'path': ['locations'], 'value': []}]
+-        output = self.controller.update(request, UUID1, changes)
+-        self.assertEqual(UUID1, output.image_id)
+-        self.assertEqual(0, len(output.locations))
+-        self.assertEqual('queued', output.status)
+-
+-        request = unit_test_utils.get_fake_request()
+-        changes = [{'op': 'replace', 'path': ['locations'],
+-                    'value': [{'url': 'unknow://foo', 'metadata': {}}]}]
+-        self.assertRaises(webob.exc.HTTPBadRequest, self.controller.update,
++        self.assertRaises(webob.exc.HTTPForbidden, self.controller.update,
+                           request, UUID1, changes)
+ 
+-    def test_update_replace_locations_status_exception(self):
+-        self.stubs.Set(store, 'get_size_from_backend',
+-                       unit_test_utils.fake_get_size_from_backend)
+-        request = unit_test_utils.get_fake_request()
+-        changes = [{'op': 'replace', 'path': ['locations'], 'value': []}]
+-        output = self.controller.update(request, UUID2, changes)
+-        self.assertEqual(UUID2, output.image_id)
+-        self.assertEqual(0, len(output.locations))
+-        self.assertEqual('queued', output.status)
+-
+-        self.db.image_update(None, UUID2, {'disk_format': None})
+-
+-        new_location = {'url': '%s/fake_location' % BASE_URI, 'metadata': {}}
+-        changes = [{'op': 'replace', 'path': ['locations'],
+-                    'value': [new_location]}]
+-        self.assertRaises(webob.exc.HTTPBadRequest, self.controller.update,
+-                          request, UUID2, changes)
+-
+     def test_update_add_property(self):
+         request = unit_test_utils.get_fake_request()
+ 
+@@ -1600,24 +1554,6 @@ class TestImagesController(base.IsolatedUnitTest):
+         self.assertRaises(webob.exc.HTTPBadRequest, self.controller.update,
+                           request, UUID1, changes)
+ 
+-    def test_update_add_locations_status_exception(self):
+-        self.stubs.Set(store, 'get_size_from_backend',
+-                       unit_test_utils.fake_get_size_from_backend)
+-        request = unit_test_utils.get_fake_request()
+-        changes = [{'op': 'replace', 'path': ['locations'], 'value': []}]
+-        output = self.controller.update(request, UUID2, changes)
+-        self.assertEqual(UUID2, output.image_id)
+-        self.assertEqual(0, len(output.locations))
+-        self.assertEqual('queued', output.status)
+-
+-        self.db.image_update(None, UUID2, {'disk_format': None})
+-
+-        new_location = {'url': '%s/fake_location' % BASE_URI, 'metadata': {}}
+-        changes = [{'op': 'add', 'path': ['locations', '-'],
+-                    'value': new_location}]
+-        self.assertRaises(webob.exc.HTTPBadRequest, self.controller.update,
+-                          request, UUID2, changes)
+-
+     def test_update_add_duplicate_locations(self):
+         new_location = {'url': '%s/fake_location' % BASE_URI, 'metadata': {}}
+         request = unit_test_utils.get_fake_request()
+@@ -1631,23 +1567,6 @@ class TestImagesController(base.IsolatedUnitTest):
+         self.assertRaises(webob.exc.HTTPBadRequest, self.controller.update,
+                           request, UUID1, changes)
+ 
+-    def test_update_replace_duplicate_locations(self):
+-        self.stubs.Set(store, 'get_size_from_backend',
+-                       unit_test_utils.fake_get_size_from_backend)
+-        request = unit_test_utils.get_fake_request()
+-        changes = [{'op': 'replace', 'path': ['locations'], 'value': []}]
+-        output = self.controller.update(request, UUID1, changes)
+-        self.assertEqual(UUID1, output.image_id)
+-        self.assertEqual(0, len(output.locations))
+-        self.assertEqual('queued', output.status)
+-
+-        new_location = {'url': '%s/fake_location' % BASE_URI, 'metadata': {}}
+-        changes = [{'op': 'replace', 'path': ['locations'],
+-                    'value': [new_location, new_location]}]
+-
+-        self.assertRaises(webob.exc.HTTPBadRequest, self.controller.update,
+-                          request, UUID1, changes)
+-
+     def test_update_add_too_many_locations(self):
+         self.config(image_location_quota=1)
+         request = unit_test_utils.get_fake_request()
+@@ -1748,9 +1667,12 @@ class TestImagesController(base.IsolatedUnitTest):
+             {'op': 'add', 'path': ['locations', '-'],
+              'value': {'url': '%s/fake_location_1' % BASE_URI,
+                        'metadata': {}}},
++            {'op': 'add', 'path': ['locations', '-'],
++             'value': {'url': '%s/fake_location_2' % BASE_URI,
++                       'metadata': {}}},
+         ]
+         self.controller.update(request, UUID1, changes)
+-        self.config(image_location_quota=1)
++        self.config(image_location_quota=2)
+ 
+         # We must remove two properties to avoid being
+         # over the limit of 1 property
+@@ -1763,8 +1685,8 @@ class TestImagesController(base.IsolatedUnitTest):
+         ]
+         output = self.controller.update(request, UUID1, changes)
+         self.assertEqual(UUID1, output.image_id)
+-        self.assertEqual(1, len(output.locations))
+-        self.assertIn('fake_location_3', output.locations[0]['url'])
++        self.assertEqual(2, len(output.locations))
++        self.assertIn('fake_location_3', output.locations[1]['url'])
+         self.assertNotEqual(output.created_at, output.updated_at)
+ 
+     def test_update_remove_base_property(self):
+@@ -1805,24 +1727,23 @@ class TestImagesController(base.IsolatedUnitTest):
+                        unit_test_utils.fake_get_size_from_backend)
+ 
+         request = unit_test_utils.get_fake_request()
+-        changes = [{'op': 'remove', 'path': ['locations', '0']}]
+-        output = self.controller.update(request, UUID1, changes)
+-        self.assertEqual(output.image_id, UUID1)
+-        self.assertEqual(0, len(output.locations))
+-        self.assertEqual('queued', output.status)
+-        self.assertIsNone(output.size)
+-
+         new_location = {'url': '%s/fake_location' % BASE_URI, 'metadata': {}}
+         changes = [{'op': 'add', 'path': ['locations', '-'],
+                     'value': new_location}]
++        self.controller.update(request, UUID1, changes)
++        changes = [{'op': 'remove', 'path': ['locations', '0']}]
+         output = self.controller.update(request, UUID1, changes)
+         self.assertEqual(UUID1, output.image_id)
+         self.assertEqual(1, len(output.locations))
+-        self.assertEqual(new_location, output.locations[0])
+         self.assertEqual('active', output.status)
+ 
+     def test_update_remove_location_invalid_pos(self):
+         request = unit_test_utils.get_fake_request()
++        changes = [
++            {'op': 'add', 'path': ['locations', '-'],
++             'value': {'url': '%s/fake_location' % BASE_URI,
++                       'metadata': {}}}]
++        self.controller.update(request, UUID1, changes)
+         changes = [{'op': 'remove', 'path': ['locations', None]}]
+         self.assertRaises(webob.exc.HTTPBadRequest, self.controller.update,
+                           request, UUID1, changes)
+@@ -1844,6 +1765,11 @@ class TestImagesController(base.IsolatedUnitTest):
+                        fake_delete_image_location_from_backend)
+ 
+         request = unit_test_utils.get_fake_request()
++        changes = [
++            {'op': 'add', 'path': ['locations', '-'],
++             'value': {'url': '%s/fake_location' % BASE_URI,
++                       'metadata': {}}}]
++        self.controller.update(request, UUID1, changes)
+         changes = [{'op': 'remove', 'path': ['locations', '0']}]
+         self.assertRaises(webob.exc.HTTPInternalServerError,
+                           self.controller.update, request, UUID1, changes)
+@@ -2137,16 +2063,6 @@ class TestImagesControllerPolicies(base.IsolatedUnitTest):
+         self.assertRaises(webob.exc.HTTPForbidden, self.controller.update,
+                           request, UUID1, changes)
+ 
+-        self.stubs.Set(self.store_utils, 'delete_image_location_from_backend',
+-                       fake_delete_image_location_from_backend)
+-
+-        changes = [{'op': 'replace', 'path': ['locations'], 'value': []}]
+-        self.controller.update(request, UUID1, changes)
+-        changes = [{'op': 'replace', 'path': ['locations'],
+-                    'value': [new_location]}]
+-        self.assertRaises(webob.exc.HTTPForbidden, self.controller.update,
+-                          request, UUID1, changes)
+-
+     def test_update_delete_image_location_unauthorized(self):
+         rules = {"delete_image_location": False}
+         self.policy.set_rules(rules)
+diff --git a/releasenotes/notes/Prevent-removing-last-image-location-d5ee3e00efe14f34.yaml b/releasenotes/notes/Prevent-removing-last-image-location-d5ee3e00efe14f34.yaml
+new file mode 100644
+index 0000000..344e6e5
+--- /dev/null
++++ b/releasenotes/notes/Prevent-removing-last-image-location-d5ee3e00efe14f34.yaml
+@@ -0,0 +1,10 @@
++---
++security:
++  - Fixing bug 1525915; image might be transitioning
++    from active to queued by regular user by removing
++    last location of image (or replacing locations
++    with empty list). This allows user to re-upload
++    data to the image breaking Glance's promise of
++    image data immutability. From now on, last
++    location cannot be removed and locations cannot
++    be replaced with empty list.
+-- 
+1.9.1
+

diff --git a/app-admin/glance/files/glance-2013.2-sphinx_mapping.patch b/app-admin/glance/files/glance-2013.2-sphinx_mapping.patch
deleted file mode 100644
index 0a0f575..0000000
--- a/app-admin/glance/files/glance-2013.2-sphinx_mapping.patch
+++ /dev/null
@@ -1,12 +0,0 @@
-diff -ur glance-2013.2.orig/doc/source/conf.py glance-2013.2/doc/source/conf.py
---- doc/source/conf.py	2013-10-17 21:39:46.000000000 +0800
-+++ doc/source/conf.py	2013-11-13 18:51:29.099839976 +0800
-@@ -250,8 +250,3 @@
- 
- # If false, no module index is generated.
- #latex_use_modindex = True
--
--# Example configuration for intersphinx: refer to the Python standard library.
--intersphinx_mapping = {'python': ('http://docs.python.org/', None),
--                       'nova': ('http://nova.openstack.org', None),
--                       'swift': ('http://swift.openstack.org', None)}

diff --git a/app-admin/glance/glance-11.0.1-r1.ebuild b/app-admin/glance/glance-11.0.1-r1.ebuild
new file mode 100644
index 0000000..1126feb
--- /dev/null
+++ b/app-admin/glance/glance-11.0.1-r1.ebuild
@@ -0,0 +1,229 @@
+# Copyright 1999-2016 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id$
+
+EAPI=5
+PYTHON_COMPAT=( python2_7 )
+
+inherit distutils-r1 user
+
+DESCRIPTION="Services for discovering, registering, and retrieving VM images"
+HOMEPAGE="https://launchpad.net/glance"
+SRC_URI="https://tarballs.openstack.org/${PN}/${P}.tar.gz"
+
+LICENSE="Apache-2.0"
+SLOT="0"
+KEYWORDS="~amd64 ~x86"
+IUSE="doc mysql postgres +sqlite +swift test"
+REQUIRED_USE="|| ( mysql postgres sqlite )"
+
+CDEPEND=">=dev-python/pbr-1.6.0[${PYTHON_USEDEP}]"
+DEPEND="
+	dev-python/setuptools[${PYTHON_USEDEP}]
+	${CDEPEND}
+	test? (
+		${RDEPEND}
+		>=dev-python/Babel-1.3[${PYTHON_USEDEP}]
+		<=dev-python/Babel-2.1.1[${PYTHON_USEDEP}]
+		>=dev-python/coverage-3.6[${PYTHON_USEDEP}]
+		<=dev-python/coverage-4.0.3[${PYTHON_USEDEP}]
+		>=dev-python/fixtures-1.3.1[${PYTHON_USEDEP}]
+		<=dev-python/fixtures-1.4.0-r9999[${PYTHON_USEDEP}]
+		>=dev-python/mox3-0.7.0[${PYTHON_USEDEP}]
+		<=dev-python/mox3-0.12.0[${PYTHON_USEDEP}]
+		>=dev-python/mock-1.2[${PYTHON_USEDEP}]
+		<=dev-python/mock-1.3.0[${PYTHON_USEDEP}]
+		>=dev-python/sphinx-1.1.2[${PYTHON_USEDEP}]
+		!~dev-python/sphinx-1.2.0[${PYTHON_USEDEP}]
+		<dev-python/sphinx-1.3[${PYTHON_USEDEP}]
+		>=dev-python/requests-2.5.2[${PYTHON_USEDEP}]
+		!~dev-python/requests-2.8.0[${PYTHON_USEDEP}]
+		<=dev-python/requests-2.8.1[${PYTHON_USEDEP}]
+		>=dev-python/testrepository-0.0.18[${PYTHON_USEDEP}]
+		<=dev-python/testrepository-0.0.20[${PYTHON_USEDEP}]
+		>=dev-python/testresources-0.2.4[${PYTHON_USEDEP}]
+		<=dev-python/testresources-1.0.0-r9999[${PYTHON_USEDEP}]
+		>=dev-python/testscenarios-0.4[${PYTHON_USEDEP}]
+		<=dev-python/testscenarios-0.5[${PYTHON_USEDEP}]
+		>=dev-python/testtools-1.4.0[${PYTHON_USEDEP}]
+		<=dev-python/testtools-1.8.1[${PYTHON_USEDEP}]
+		>=dev-python/psutil-1.1.1[${PYTHON_USEDEP}]
+		<dev-python/psutil-2.0.0[${PYTHON_USEDEP}]
+		>=dev-python/oslotest-1.10.0[${PYTHON_USEDEP}]
+		<=dev-python/oslotest-2.0.0[${PYTHON_USEDEP}]
+		>=dev-python/pymysql-0.6.2[${PYTHON_USEDEP}]
+		<=dev-python/pymysql-0.6.7[${PYTHON_USEDEP}]
+		>=dev-python/psycopg-2.5[${PYTHON_USEDEP}]
+		<=dev-python/psycopg-2.6.1[${PYTHON_USEDEP}]
+		>=dev-python/pysendfile-2.0.0[${PYTHON_USEDEP}]
+		<=dev-python/pysendfile-2.0.1[${PYTHON_USEDEP}]
+		<=dev-python/qpid-python-0.32[$(python_gen_usedep 'python2_7')]
+		>=dev-python/pyxattr-0.5.0[${PYTHON_USEDEP}]
+		>=dev-python/python-swiftclient-2.2.0[${PYTHON_USEDEP}]
+		<=dev-python/python-swiftclient-2.7.0[${PYTHON_USEDEP}]
+		>=dev-python/oslo-sphinx-2.5.0[${PYTHON_USEDEP}]
+		<=dev-python/oslo-sphinx-4.1.0[${PYTHON_USEDEP}]
+		>=dev-python/reno-0.1.1[${PYTHON_USEDEP}]
+	)"
+
+#note to self, wsgiref is a python builtin, no need to package it
+#>=dev-python/wsgiref-0.1.2[${PYTHON_USEDEP}]
+
+RDEPEND="
+	${CDEPEND}
+	sqlite? (
+		>=dev-python/sqlalchemy-0.9.9[sqlite,${PYTHON_USEDEP}]
+		<dev-python/sqlalchemy-1.0.10[sqlite,${PYTHON_USEDEP}]
+	)
+	mysql? (
+		dev-python/mysql-python
+		>=dev-python/sqlalchemy-0.9.9[${PYTHON_USEDEP}]
+		<dev-python/sqlalchemy-1.0.10[${PYTHON_USEDEP}]
+	)
+	postgres? (
+		dev-python/psycopg:2[${PYTHON_USEDEP}]
+		>=dev-python/sqlalchemy-0.9.9[${PYTHON_USEDEP}]
+		<dev-python/sqlalchemy-1.0.10[${PYTHON_USEDEP}]
+	)
+	~dev-python/anyjson-0.3.3[${PYTHON_USEDEP}]
+	~dev-python/eventlet-0.17.4[${PYTHON_USEDEP}]
+	>=dev-python/pastedeploy-1.5.0[${PYTHON_USEDEP}]
+	<=dev-python/pastedeploy-1.5.2[${PYTHON_USEDEP}]
+	>=dev-python/routes-1.12.3[${PYTHON_USEDEP}]
+	!~dev-python/routes-2.0[${PYTHON_USEDEP}]
+	!~dev-python/routes-2.1[$(python_gen_usedep 'python2_7')]
+	<=dev-python/routes-2.2[${PYTHON_USEDEP}]
+	>=dev-python/webob-1.2.3[${PYTHON_USEDEP}]
+	<=dev-python/webob-1.5.1[${PYTHON_USEDEP}]
+	>=dev-python/sqlalchemy-migrate-0.9.6[${PYTHON_USEDEP}]
+	<=dev-python/sqlalchemy-migrate-0.10.0[${PYTHON_USEDEP}]
+	>=dev-python/httplib2-0.7.5[${PYTHON_USEDEP}]
+	<=dev-python/httplib2-0.9.2[${PYTHON_USEDEP}]
+	>=dev-python/pycrypto-2.6[${PYTHON_USEDEP}]
+	<=dev-python/pycrypto-2.6.1[${PYTHON_USEDEP}]
+	>=dev-python/iso8601-0.1.9[${PYTHON_USEDEP}]
+	<=dev-python/iso8601-0.1.11[${PYTHON_USEDEP}]
+	>=dev-python/oslo-config-2.3.0[${PYTHON_USEDEP}]
+	<=dev-python/oslo-config-3.1.0[${PYTHON_USEDEP}]
+	>=dev-python/oslo-concurrency-2.3.0[${PYTHON_USEDEP}]
+	<=dev-python/oslo-concurrency-3.1.0[${PYTHON_USEDEP}]
+	>=dev-python/oslo-context-0.2.0[${PYTHON_USEDEP}]
+	<=dev-python/oslo-context-1.0.0[${PYTHON_USEDEP}]
+	>=dev-python/oslo-service-0.7.0[${PYTHON_USEDEP}]
+	<=dev-python/oslo-service-1.1.0[${PYTHON_USEDEP}]
+	>=dev-python/oslo-utils-2.0.0[${PYTHON_USEDEP}]
+	!~dev-python/oslo-utils-2.6.0[${PYTHON_USEDEP}]
+	<=dev-python/oslo-utils-3.2.0[${PYTHON_USEDEP}]
+	>=dev-python/stevedore-1.5.0[${PYTHON_USEDEP}]
+	<=dev-python/stevedore-1.10.0[${PYTHON_USEDEP}]
+	>=dev-python/futurist-0.1.2[${PYTHON_USEDEP}]
+	<=dev-python/futurist-0.8.0[${PYTHON_USEDEP}]
+	>=dev-python/taskflow-1.16.0[${PYTHON_USEDEP}]
+	<=dev-python/taskflow-1.25.0[${PYTHON_USEDEP}]
+	>=dev-python/keystonemiddleware-2.0.0[${PYTHON_USEDEP}]
+	!~dev-python/keystonemiddleware-2.4.0[${PYTHON_USEDEP}]
+	<=dev-python/keystonemiddleware-4.0.0[${PYTHON_USEDEP}]
+	>=dev-python/WSME-0.7[${PYTHON_USEDEP}]
+	<=dev-python/WSME-0.8.0[${PYTHON_USEDEP}]
+	<=dev-python/paste-2.0.2[${PYTHON_USEDEP}]
+	>=dev-python/jsonschema-2.0.0[${PYTHON_USEDEP}]
+	!~dev-python/jsonschema-2.5.0[${PYTHON_USEDEP}]
+	<dev-python/jsonschema-3.0.0[${PYTHON_USEDEP}]
+	>=dev-python/python-keystoneclient-1.6.0[${PYTHON_USEDEP}]
+	!~dev-python/python-keystoneclient-1.8.0[${PYTHON_USEDEP}]
+	<=dev-python/python-keystoneclient-2.0.0-r9999[${PYTHON_USEDEP}]
+	>=dev-python/pyopenssl-0.14[${PYTHON_USEDEP}]
+	<=dev-python/pyopenssl-0.15.1-r9999[${PYTHON_USEDEP}]
+	>=dev-python/six-1.9.0[${PYTHON_USEDEP}]
+	<=dev-python/six-1.10.0[${PYTHON_USEDEP}]
+	>=dev-python/oslo-db-2.4.1[${PYTHON_USEDEP}]
+	<=dev-python/oslo-db-4.1.0[${PYTHON_USEDEP}]
+	>=dev-python/oslo-i18n-1.5.0[${PYTHON_USEDEP}]
+	<=dev-python/oslo-i18n-3.1.0[${PYTHON_USEDEP}]
+	>=dev-python/oslo-log-1.8.0[${PYTHON_USEDEP}]
+	<=dev-python/oslo-log-2.1.0[${PYTHON_USEDEP}]
+	>=dev-python/oslo-messaging-1.16.0[${PYTHON_USEDEP}]
+	!~dev-python/oslo-messaging-1.17.0[${PYTHON_USEDEP}]
+	!~dev-python/oslo-messaging-1.17.1[${PYTHON_USEDEP}]
+	!~dev-python/oslo-messaging-2.6.0[${PYTHON_USEDEP}]
+	!~dev-python/oslo-messaging-2.6.1[${PYTHON_USEDEP}]
+	!~dev-python/oslo-messaging-2.7.0[${PYTHON_USEDEP}]
+	!~dev-python/oslo-messaging-2.8.0[${PYTHON_USEDEP}]
+	!~dev-python/oslo-messaging-2.8.1[${PYTHON_USEDEP}]
+	!~dev-python/oslo-messaging-2.9.0[${PYTHON_USEDEP}]
+	!~dev-python/oslo-messaging-3.1.0[${PYTHON_USEDEP}]
+	<=dev-python/oslo-messaging-3.0.0[${PYTHON_USEDEP}]
+	>=dev-python/oslo-middleware-2.8.0[${PYTHON_USEDEP}]
+	<=dev-python/oslo-middleware-3.3.0[${PYTHON_USEDEP}]
+	>=dev-python/oslo-policy-0.5.0[${PYTHON_USEDEP}]
+	<=dev-python/oslo-policy-1.1.0[${PYTHON_USEDEP}]
+	>=dev-python/oslo-serialization-1.4.0[${PYTHON_USEDEP}]
+	<=dev-python/oslo-serialization-2.1.0[${PYTHON_USEDEP}]
+	>=dev-python/retrying-1.2.3[${PYTHON_USEDEP}]
+	!~dev-python/retrying-1.3.0[${PYTHON_USEDEP}]
+	<=dev-python/retrying-1.3.3[${PYTHON_USEDEP}]
+	>=dev-python/osprofiler-0.3.0[${PYTHON_USEDEP}]
+	<=dev-python/osprofiler-0.3.1[${PYTHON_USEDEP}]
+	>=dev-python/glance_store-0.7.1[${PYTHON_USEDEP}]
+	!~dev-python/glance_store-0.9.0[${PYTHON_USEDEP}]
+	<=dev-python/glance_store-0.9.1[${PYTHON_USEDEP}]
+	>=dev-python/semantic_version-2.3.1[${PYTHON_USEDEP}]
+	<=dev-python/semantic_version-2.4.2[${PYTHON_USEDEP}]
+	>=dev-python/castellan-0.2.0[${PYTHON_USEDEP}]
+	<=dev-python/castellan-0.3.1[${PYTHON_USEDEP}]
+	>=dev-python/cryptography-1.0[${PYTHON_USEDEP}]
+	<=dev-python/cryptography-1.1.2-r9999[${PYTHON_USEDEP}]
+"
+
+PATCHES=(
+	"${FILESDIR}/cve-2016-0757-stable-liberty.patch"
+)
+
+pkg_setup() {
+	enewgroup glance
+	enewuser glance -1 -1 /var/lib/glance glance
+}
+
+python_prepare_all() {
+	sed -i '/xattr/d' test-requirements.txt || die
+	sed -i '/pysendfile/d' test-requirements.txt || die
+	sed -i '/^hacking/d' test-requirements.txt || die
+	distutils-r1_python_prepare_all
+}
+
+python_compile_all() {
+	use doc && "${PYTHON}" setup.py build_sphinx
+}
+
+python_test() {
+	# https://bugs.launchpad.net/glance/+bug/1251105
+	# https://bugs.launchpad.net/glance/+bug/1242501
+	testr init
+	testr run --parallel || die "failed testsuite under python2.7"
+}
+
+python_install() {
+	distutils-r1_python_install
+
+	for svc in api registry scrubber; do
+		newinitd "${FILESDIR}/glance.initd" glance-${svc}
+	done
+
+	diropts -m 0750 -o glance -g glance
+	dodir /var/log/glance /var/lib/glance/images /var/lib/glance/scrubber
+	keepdir /etc/glance
+	keepdir /var/log/glance
+	keepdir /var/lib/glance/images
+	keepdir /var/lib/glance/scrubber
+
+	insinto /etc/glance
+	insopts -m 0640 -o glance -g glance
+	doins etc/*.ini
+	doins etc/*.conf
+	doins etc/*.sample
+}
+
+python_install_all() {
+	use doc && local HTML_DOCS=( doc/build/html/. )
+	distutils-r1_python_install_all
+}


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [gentoo-commits] repo/gentoo:master commit in: app-admin/glance/files/, app-admin/glance/
@ 2018-01-28  4:13 Matt Thode
  0 siblings, 0 replies; 5+ messages in thread
From: Matt Thode @ 2018-01-28  4:13 UTC (permalink / raw
  To: gentoo-commits

commit:     99aaee53d4f3f580b511255ae8cd5181211be32d
Author:     Matthew Thode <prometheanfire <AT> gentoo <DOT> org>
AuthorDate: Sun Jan 28 03:49:54 2018 +0000
Commit:     Matt Thode <prometheanfire <AT> gentoo <DOT> org>
CommitDate: Sun Jan 28 04:13:05 2018 +0000
URL:        https://gitweb.gentoo.org/repo/gentoo.git/commit/?id=99aaee53

app-admin/glance: remove ocata

Package-Manager: Portage-2.3.19, Repoman-2.3.6

 app-admin/glance/Manifest                  |   1 -
 app-admin/glance/files/glance.initd        |  16 ++--
 app-admin/glance/files/glance.initd-2      |  15 ----
 app-admin/glance/files/glance.initd-r2     |  17 ----
 app-admin/glance/glance-14.0.0-r1.ebuild   | 135 ----------------------------
 app-admin/glance/glance-14.0.0.ebuild      | 135 ----------------------------
 app-admin/glance/glance-15.0.0.ebuild      |   4 +-
 app-admin/glance/glance-2017.1.9999.ebuild | 136 -----------------------------
 app-admin/glance/glance-2017.2.9999.ebuild |   4 +-
 9 files changed, 9 insertions(+), 454 deletions(-)

diff --git a/app-admin/glance/Manifest b/app-admin/glance/Manifest
index 4f6beea940c..0824f911194 100644
--- a/app-admin/glance/Manifest
+++ b/app-admin/glance/Manifest
@@ -1,2 +1 @@
-DIST glance-14.0.0.tar.gz 1788173 BLAKE2B 91834050aea925325a61f99c817e9d289270de30b88c53430b6b9c5845dbfc943678db734b9592657eb7ab8c49d5d6a7c110411c45c1fd82d8c829db67ef174b SHA512 4d0b6654dc6a9848e164422d138d4f6c1ec3711a7eb56a3c437202aa5c8cf86bf341201c9007b2f12173189f18beb73eadbaaade936ececf705a31e8b6eac155
 DIST glance-15.0.0.tar.gz 1803491 BLAKE2B 70e0f1f7eab6aa0066d16e30e9325ac45d9c0eb9df875e3b26e90463e10299d6c7c272c0b070137f27332bdfcb33abeda68e3375e2562c83942ca72fcb24de38 SHA512 beb5744f9e8b296356cb731c79f1efd7b60408c1282e8a64ab7d414929c447c4f2ff0562a0d59c0a05f828d420ba190946866543a37dbd2df73ae322cbcabab5

diff --git a/app-admin/glance/files/glance.initd b/app-admin/glance/files/glance.initd
index 1ece1ad58f8..57274ac2dfe 100644
--- a/app-admin/glance/files/glance.initd
+++ b/app-admin/glance/files/glance.initd
@@ -1,21 +1,15 @@
 #!/sbin/openrc-run
-# Copyright 1999-2014 Gentoo Foundation
+# Copyright 1999-2018 Gentoo Foundation
 # Distributed under the terms of the GNU General Public License v2
 
 description="Starts ${SVCNAME} service for OpenStack"
 
-command=/usr/bin/${SVCNAME}
+command=/usr/bin/${RC_SVCNAME}
+command_user="${GLANCE_USER:-glance}"
 command_background=yes
-pidfile=/var/run/glance/${SVCNAME}.pid
-required_files=/etc/glance/${SVCNAME}.conf
-
-start_stop_daemon_args="--quiet --user ${GLANCE_USER:-glance}"
+pidfile=/run/${RC_SVCNAME}.pid
+required_files=/etc/glance/${RC_SVCNAME}.conf
 
 depend() {
 	need net
 }
-
-start_pre() {
-	checkpath --directory --owner ${GLANCE_USER:-glance}:${GLANCE_GROUP:-glance} --mode 0755 ${GLANCE_RUN:-/var/run/glance}
-}
-

diff --git a/app-admin/glance/files/glance.initd-2 b/app-admin/glance/files/glance.initd-2
deleted file mode 100644
index 4d4849f77e7..00000000000
--- a/app-admin/glance/files/glance.initd-2
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/sbin/openrc-run
-# Copyright 1999-2017 Gentoo Foundation
-# Distributed under the terms of the GNU General Public License v2
-
-description="Starts ${SVCNAME} service for OpenStack"
-
-command=/usr/bin/${RC_SVCNAME}
-command_user="${GLANCE_USER:-glance}"
-command_background=yes
-pidfile=/run/${RC_SVCNAME}.pid
-required_files=/etc/glance/${RC_SVCNAME}.conf
-
-depend() {
-	need net
-}

diff --git a/app-admin/glance/files/glance.initd-r2 b/app-admin/glance/files/glance.initd-r2
deleted file mode 100644
index 338de069750..00000000000
--- a/app-admin/glance/files/glance.initd-r2
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/sbin/openrc-run
-# Copyright 1999-2017 Gentoo Foundation
-# Distributed under the terms of the GNU General Public License v2
-
-description="Starts ${RC_SVCNAME} service for OpenStack"
-
-command=/usr/bin/${RC_SVCNAME}
-command_user="${GLANCE_USER:-glance}"
-command_background=yes
-pidfile=/run/${RC_SVCNAME}.pid
-required_files=/etc/glance/${RC_SVCNAME}.conf
-
-start_stop_daemon_args="--quiet"
-
-depend() {
-	need net
-}

diff --git a/app-admin/glance/glance-14.0.0-r1.ebuild b/app-admin/glance/glance-14.0.0-r1.ebuild
deleted file mode 100644
index 02f04305b64..00000000000
--- a/app-admin/glance/glance-14.0.0-r1.ebuild
+++ /dev/null
@@ -1,135 +0,0 @@
-# Copyright 1999-2017 Gentoo Foundation
-# Distributed under the terms of the GNU General Public License v2
-
-EAPI=6
-PYTHON_COMPAT=( python2_7 python3_4 python3_5 )
-
-inherit distutils-r1 user
-
-DESCRIPTION="Services for discovering, registering, and retrieving VM images"
-HOMEPAGE="https://launchpad.net/glance"
-SRC_URI="https://tarballs.openstack.org/${PN}/${P}.tar.gz"
-
-LICENSE="Apache-2.0"
-SLOT="0"
-KEYWORDS="~amd64 ~arm64 ~x86"
-IUSE="doc mysql postgres +sqlite +swift"
-REQUIRED_USE="|| ( mysql postgres sqlite )"
-
-CDEPEND=">=dev-python/pbr-1.8.0[${PYTHON_USEDEP}]"
-DEPEND="
-	dev-python/setuptools[${PYTHON_USEDEP}]
-	${CDEPEND}"
-
-#note to self, wsgiref is a python builtin, no need to package it
-#>=dev-python/wsgiref-0.1.2[${PYTHON_USEDEP}]
-
-RDEPEND="
-	${CDEPEND}
-	sqlite? (
-		>=dev-python/sqlalchemy-1.0.10[sqlite,${PYTHON_USEDEP}]
-		<dev-python/sqlalchemy-1.1.0[sqlite,${PYTHON_USEDEP}]
-	)
-	mysql? (
-		>=dev-python/pymysql-0.7.6[${PYTHON_USEDEP}]
-		!~dev-python/pymysql-0.7.7[${PYTHON_USEDEP}]
-		>=dev-python/sqlalchemy-1.0.10[${PYTHON_USEDEP}]
-		<dev-python/sqlalchemy-1.1.0[${PYTHON_USEDEP}]
-	)
-	postgres? (
-		>=dev-python/psycopg-2.5.0[${PYTHON_USEDEP}]
-		>=dev-python/sqlalchemy-1.0.10[${PYTHON_USEDEP}]
-		<dev-python/sqlalchemy-1.1.0[${PYTHON_USEDEP}]
-	)
-	>=dev-python/eventlet-0.18.4[${PYTHON_USEDEP}]
-	>=dev-python/pastedeploy-1.5.0[${PYTHON_USEDEP}]
-	>=dev-python/routes-1.12.3[${PYTHON_USEDEP}]
-	!~dev-python/routes-2.0[${PYTHON_USEDEP}]
-	!~dev-python/routes-2.1[$(python_gen_usedep 'python2_7')]
-	!~dev-python/routes-2.3[${PYTHON_USEDEP}]
-	>=dev-python/webob-1.6.0[${PYTHON_USEDEP}]
-	>=dev-python/sqlalchemy-migrate-0.9.6[${PYTHON_USEDEP}]
-	>=dev-python/python-sqlparse-0.2.2[${PYTHON_USEDEP}]
-	>=dev-python/alembic-0.8.10[${PYTHON_USEDEP}]
-	>=dev-python/httplib2-0.7.5[${PYTHON_USEDEP}]
-	>=dev-python/pycrypto-2.6[${PYTHON_USEDEP}]
-	>=dev-python/oslo-config-3.14.0[${PYTHON_USEDEP}]
-	!~dev-python/oslo-config-3.18.0[${PYTHON_USEDEP}]
-	>=dev-python/oslo-concurrency-3.8.0[${PYTHON_USEDEP}]
-	>=dev-python/oslo-context-2.9.0[${PYTHON_USEDEP}]
-	>=dev-python/oslo-utils-3.18.0[${PYTHON_USEDEP}]
-	>=dev-python/stevedore-1.17.1[${PYTHON_USEDEP}]
-	>=dev-python/futurist-0.11.0[${PYTHON_USEDEP}]
-	!~dev-python/futurist-0.15.0[${PYTHON_USEDEP}]
-	>=dev-python/taskflow-2.7.0.0[${PYTHON_USEDEP}]
-	>=dev-python/keystoneauth-2.18.0[${PYTHON_USEDEP}]
-	>=dev-python/keystonemiddleware-4.12.0[${PYTHON_USEDEP}]
-	>=dev-python/WSME-0.8.0[${PYTHON_USEDEP}]
-	>=dev-python/prettytable-0.7.0[${PYTHON_USEDEP}]
-	<dev-python/prettytable-0.8.0[${PYTHON_USEDEP}]
-	dev-python/paste[${PYTHON_USEDEP}]
-	>=dev-python/jsonschema-2.0.0[${PYTHON_USEDEP}]
-	!~dev-python/jsonschema-2.5.0[${PYTHON_USEDEP}]
-	<dev-python/jsonschema-3.0.0[${PYTHON_USEDEP}]
-	>=dev-python/python-keystoneclient-3.8.0[${PYTHON_USEDEP}]
-	>=dev-python/pyopenssl-0.14[${PYTHON_USEDEP}]
-	>=dev-python/six-1.9.0[${PYTHON_USEDEP}]
-	>=dev-python/oslo-db-4.15.0[${PYTHON_USEDEP}]
-	>=dev-python/oslo-i18n-2.1.0[${PYTHON_USEDEP}]
-	>=dev-python/oslo-log-3.11.0[${PYTHON_USEDEP}]
-	>=dev-python/oslo-messaging-5.14.0[${PYTHON_USEDEP}]
-	>=dev-python/oslo-middleware-3.0.0[${PYTHON_USEDEP}]
-	>=dev-python/oslo-policy-1.17.0[${PYTHON_USEDEP}]
-	>=dev-python/retrying-1.2.3[${PYTHON_USEDEP}]
-	!~dev-python/retrying-1.3.0[${PYTHON_USEDEP}]
-	>=dev-python/osprofiler-1.4.0[${PYTHON_USEDEP}]
-	>=dev-python/glance_store-0.18.0[${PYTHON_USEDEP}]
-	>=dev-python/semantic_version-2.3.1[${PYTHON_USEDEP}]
-	>=dev-python/debtcollector-1.2.0[${PYTHON_USEDEP}]
-	>=dev-python/cryptography-1.0[${PYTHON_USEDEP}]
-	!~dev-python/cryptography-1.3.0[${PYTHON_USEDEP}]
-	>=dev-python/cursive-0.1.1[${PYTHON_USEDEP}]
-	>=dev-python/iso8601-0.1.11[${PYTHON_USEDEP}]
-	>=dev-python/monotonic-0.6[${PYTHON_USEDEP}]
-"
-
-#PATCHES=(
-#)
-
-pkg_setup() {
-	enewgroup glance
-	enewuser glance -1 -1 /var/lib/glance glance
-}
-
-python_prepare_all() {
-	sed -i '/xattr/d' test-requirements.txt || die
-	sed -i '/pysendfile/d' test-requirements.txt || die
-	sed -i '/^hacking/d' test-requirements.txt || die
-	distutils-r1_python_prepare_all
-}
-
-python_compile_all() {
-	use doc && "${PYTHON}" setup.py build_sphinx
-}
-
-python_install_all() {
-	distutils-r1_python_install_all
-
-	for svc in api glare registry scrubber; do
-		newinitd "${FILESDIR}/glance.initd" glance-${svc}
-	done
-
-	diropts -m 0750 -o glance -g glance
-	dodir /var/log/glance /var/lib/glance/images /var/lib/glance/scrubber
-	keepdir /etc/glance
-	keepdir /var/log/glance
-	keepdir /var/lib/glance/images
-	keepdir /var/lib/glance/scrubber
-
-	insinto /etc/glance
-	insopts -m 0640 -o glance -g glance
-	doins -r etc/*.ini etc/*.conf etc/*.sample etc/*.json etc/meta*
-
-	use doc && local HTML_DOCS=( doc/build/html/. )
-	distutils-r1_python_install_all
-}

diff --git a/app-admin/glance/glance-14.0.0.ebuild b/app-admin/glance/glance-14.0.0.ebuild
deleted file mode 100644
index d968f2a9e32..00000000000
--- a/app-admin/glance/glance-14.0.0.ebuild
+++ /dev/null
@@ -1,135 +0,0 @@
-# Copyright 1999-2017 Gentoo Foundation
-# Distributed under the terms of the GNU General Public License v2
-
-EAPI=6
-PYTHON_COMPAT=( python2_7 python3_4 python3_5 )
-
-inherit distutils-r1 user
-
-DESCRIPTION="Services for discovering, registering, and retrieving VM images"
-HOMEPAGE="https://launchpad.net/glance"
-SRC_URI="https://tarballs.openstack.org/${PN}/${P}.tar.gz"
-
-LICENSE="Apache-2.0"
-SLOT="0"
-KEYWORDS="amd64 ~arm64 x86"
-IUSE="doc mysql postgres +sqlite +swift"
-REQUIRED_USE="|| ( mysql postgres sqlite )"
-
-CDEPEND=">=dev-python/pbr-1.8.0[${PYTHON_USEDEP}]"
-DEPEND="
-	dev-python/setuptools[${PYTHON_USEDEP}]
-	${CDEPEND}"
-
-#note to self, wsgiref is a python builtin, no need to package it
-#>=dev-python/wsgiref-0.1.2[${PYTHON_USEDEP}]
-
-RDEPEND="
-	${CDEPEND}
-	sqlite? (
-		>=dev-python/sqlalchemy-1.0.10[sqlite,${PYTHON_USEDEP}]
-		<dev-python/sqlalchemy-1.1.0[sqlite,${PYTHON_USEDEP}]
-	)
-	mysql? (
-		>=dev-python/pymysql-0.7.6[${PYTHON_USEDEP}]
-		!~dev-python/pymysql-0.7.7[${PYTHON_USEDEP}]
-		>=dev-python/sqlalchemy-1.0.10[${PYTHON_USEDEP}]
-		<dev-python/sqlalchemy-1.1.0[${PYTHON_USEDEP}]
-	)
-	postgres? (
-		>=dev-python/psycopg-2.5.0[${PYTHON_USEDEP}]
-		>=dev-python/sqlalchemy-1.0.10[${PYTHON_USEDEP}]
-		<dev-python/sqlalchemy-1.1.0[${PYTHON_USEDEP}]
-	)
-	>=dev-python/eventlet-0.18.4[${PYTHON_USEDEP}]
-	>=dev-python/pastedeploy-1.5.0[${PYTHON_USEDEP}]
-	>=dev-python/routes-1.12.3[${PYTHON_USEDEP}]
-	!~dev-python/routes-2.0[${PYTHON_USEDEP}]
-	!~dev-python/routes-2.1[$(python_gen_usedep 'python2_7')]
-	!~dev-python/routes-2.3[${PYTHON_USEDEP}]
-	>=dev-python/webob-1.6.0[${PYTHON_USEDEP}]
-	>=dev-python/sqlalchemy-migrate-0.9.6[${PYTHON_USEDEP}]
-	>=dev-python/python-sqlparse-0.2.2[${PYTHON_USEDEP}]
-	>=dev-python/alembic-0.8.10[${PYTHON_USEDEP}]
-	>=dev-python/httplib2-0.7.5[${PYTHON_USEDEP}]
-	>=dev-python/pycrypto-2.6[${PYTHON_USEDEP}]
-	>=dev-python/oslo-config-3.14.0[${PYTHON_USEDEP}]
-	!~dev-python/oslo-config-3.18.0[${PYTHON_USEDEP}]
-	>=dev-python/oslo-concurrency-3.8.0[${PYTHON_USEDEP}]
-	>=dev-python/oslo-context-2.9.0[${PYTHON_USEDEP}]
-	>=dev-python/oslo-utils-3.18.0[${PYTHON_USEDEP}]
-	>=dev-python/stevedore-1.17.1[${PYTHON_USEDEP}]
-	>=dev-python/futurist-0.11.0[${PYTHON_USEDEP}]
-	!~dev-python/futurist-0.15.0[${PYTHON_USEDEP}]
-	>=dev-python/taskflow-2.7.0.0[${PYTHON_USEDEP}]
-	>=dev-python/keystoneauth-2.18.0[${PYTHON_USEDEP}]
-	>=dev-python/keystonemiddleware-4.12.0[${PYTHON_USEDEP}]
-	>=dev-python/WSME-0.8.0[${PYTHON_USEDEP}]
-	>=dev-python/prettytable-0.7.0[${PYTHON_USEDEP}]
-	<dev-python/prettytable-0.8.0[${PYTHON_USEDEP}]
-	dev-python/paste[${PYTHON_USEDEP}]
-	>=dev-python/jsonschema-2.0.0[${PYTHON_USEDEP}]
-	!~dev-python/jsonschema-2.5.0[${PYTHON_USEDEP}]
-	<dev-python/jsonschema-3.0.0[${PYTHON_USEDEP}]
-	>=dev-python/python-keystoneclient-3.8.0[${PYTHON_USEDEP}]
-	>=dev-python/pyopenssl-0.14[${PYTHON_USEDEP}]
-	>=dev-python/six-1.9.0[${PYTHON_USEDEP}]
-	>=dev-python/oslo-db-4.15.0[${PYTHON_USEDEP}]
-	>=dev-python/oslo-i18n-2.1.0[${PYTHON_USEDEP}]
-	>=dev-python/oslo-log-3.11.0[${PYTHON_USEDEP}]
-	>=dev-python/oslo-messaging-5.14.0[${PYTHON_USEDEP}]
-	>=dev-python/oslo-middleware-3.0.0[${PYTHON_USEDEP}]
-	>=dev-python/oslo-policy-1.17.0[${PYTHON_USEDEP}]
-	>=dev-python/retrying-1.2.3[${PYTHON_USEDEP}]
-	!~dev-python/retrying-1.3.0[${PYTHON_USEDEP}]
-	>=dev-python/osprofiler-1.4.0[${PYTHON_USEDEP}]
-	>=dev-python/glance_store-0.18.0[${PYTHON_USEDEP}]
-	>=dev-python/semantic_version-2.3.1[${PYTHON_USEDEP}]
-	>=dev-python/debtcollector-1.2.0[${PYTHON_USEDEP}]
-	>=dev-python/cryptography-1.0[${PYTHON_USEDEP}]
-	!~dev-python/cryptography-1.3.0[${PYTHON_USEDEP}]
-	>=dev-python/cursive-0.1.1[${PYTHON_USEDEP}]
-	>=dev-python/iso8601-0.1.11[${PYTHON_USEDEP}]
-	>=dev-python/monotonic-0.6[${PYTHON_USEDEP}]
-"
-
-#PATCHES=(
-#)
-
-pkg_setup() {
-	enewgroup glance
-	enewuser glance -1 -1 /var/lib/glance glance
-}
-
-python_prepare_all() {
-	sed -i '/xattr/d' test-requirements.txt || die
-	sed -i '/pysendfile/d' test-requirements.txt || die
-	sed -i '/^hacking/d' test-requirements.txt || die
-	distutils-r1_python_prepare_all
-}
-
-python_compile_all() {
-	use doc && "${PYTHON}" setup.py build_sphinx
-}
-
-python_install_all() {
-	distutils-r1_python_install_all
-
-	for svc in api glare registry scrubber; do
-		newinitd "${FILESDIR}/glance.initd" glance-${svc}
-	done
-
-	diropts -m 0750 -o glance -g glance
-	dodir /var/log/glance /var/lib/glance/images /var/lib/glance/scrubber
-	keepdir /etc/glance
-	keepdir /var/log/glance
-	keepdir /var/lib/glance/images
-	keepdir /var/lib/glance/scrubber
-
-	insinto /etc/glance
-	insopts -m 0640 -o glance -g glance
-	doins -r etc/*.ini etc/*.conf etc/*.sample etc/*.json etc/meta*
-
-	use doc && local HTML_DOCS=( doc/build/html/. )
-	distutils-r1_python_install_all
-}

diff --git a/app-admin/glance/glance-15.0.0.ebuild b/app-admin/glance/glance-15.0.0.ebuild
index b32fcd4c7e8..56945afeb41 100644
--- a/app-admin/glance/glance-15.0.0.ebuild
+++ b/app-admin/glance/glance-15.0.0.ebuild
@@ -1,4 +1,4 @@
-# Copyright 1999-2017 Gentoo Foundation
+# Copyright 1999-2018 Gentoo Foundation
 # Distributed under the terms of the GNU General Public License v2
 
 EAPI=6
@@ -125,7 +125,7 @@ python_compile_all() {
 python_install_all() {
 	distutils-r1_python_install_all
 
-	newinitd "${FILESDIR}/glance.initd-2" glance-api
+	newinitd "${FILESDIR}/glance.initd" glance-api
 
 	diropts -m 0750 -o glance -g glance
 	dodir /var/log/glance /var/lib/glance/images /var/lib/glance/scrubber

diff --git a/app-admin/glance/glance-2017.1.9999.ebuild b/app-admin/glance/glance-2017.1.9999.ebuild
deleted file mode 100644
index abe2dce6724..00000000000
--- a/app-admin/glance/glance-2017.1.9999.ebuild
+++ /dev/null
@@ -1,136 +0,0 @@
-# Copyright 1999-2017 Gentoo Foundation
-# Distributed under the terms of the GNU General Public License v2
-
-EAPI=6
-PYTHON_COMPAT=( python2_7 python3_4 python3_5 )
-
-inherit distutils-r1 git-r3 user
-
-DESCRIPTION="Services for discovering, registering, and retrieving VM images"
-HOMEPAGE="https://launchpad.net/glance"
-EGIT_REPO_URI="https://github.com/openstack/glance.git"
-EGIT_BRANCH="stable/ocata"
-
-LICENSE="Apache-2.0"
-SLOT="0"
-KEYWORDS=""
-IUSE="doc mysql postgres +sqlite +swift"
-REQUIRED_USE="|| ( mysql postgres sqlite )"
-
-CDEPEND=">=dev-python/pbr-1.8.0[${PYTHON_USEDEP}]"
-DEPEND="
-	dev-python/setuptools[${PYTHON_USEDEP}]
-	${CDEPEND}"
-
-#note to self, wsgiref is a python builtin, no need to package it
-#>=dev-python/wsgiref-0.1.2[${PYTHON_USEDEP}]
-
-RDEPEND="
-	${CDEPEND}
-	sqlite? (
-		>=dev-python/sqlalchemy-1.0.10[sqlite,${PYTHON_USEDEP}]
-		<dev-python/sqlalchemy-1.1.0[sqlite,${PYTHON_USEDEP}]
-	)
-	mysql? (
-		>=dev-python/pymysql-0.7.6[${PYTHON_USEDEP}]
-		!~dev-python/pymysql-0.7.7[${PYTHON_USEDEP}]
-		>=dev-python/sqlalchemy-1.0.10[${PYTHON_USEDEP}]
-		<dev-python/sqlalchemy-1.1.0[${PYTHON_USEDEP}]
-	)
-	postgres? (
-		>=dev-python/psycopg-2.5.0[${PYTHON_USEDEP}]
-		>=dev-python/sqlalchemy-1.0.10[${PYTHON_USEDEP}]
-		<dev-python/sqlalchemy-1.1.0[${PYTHON_USEDEP}]
-	)
-	>=dev-python/eventlet-0.18.4[${PYTHON_USEDEP}]
-	>=dev-python/pastedeploy-1.5.0[${PYTHON_USEDEP}]
-	>=dev-python/routes-1.12.3[${PYTHON_USEDEP}]
-	!~dev-python/routes-2.0[${PYTHON_USEDEP}]
-	!~dev-python/routes-2.1[$(python_gen_usedep 'python2_7')]
-	!~dev-python/routes-2.3[${PYTHON_USEDEP}]
-	>=dev-python/webob-1.6.0[${PYTHON_USEDEP}]
-	>=dev-python/sqlalchemy-migrate-0.9.6[${PYTHON_USEDEP}]
-	>=dev-python/python-sqlparse-0.2.2[${PYTHON_USEDEP}]
-	>=dev-python/alembic-0.8.10[${PYTHON_USEDEP}]
-	>=dev-python/httplib2-0.7.5[${PYTHON_USEDEP}]
-	>=dev-python/pycrypto-2.6[${PYTHON_USEDEP}]
-	>=dev-python/oslo-config-3.14.0[${PYTHON_USEDEP}]
-	!~dev-python/oslo-config-3.18.0[${PYTHON_USEDEP}]
-	>=dev-python/oslo-concurrency-3.8.0[${PYTHON_USEDEP}]
-	>=dev-python/oslo-context-2.9.0[${PYTHON_USEDEP}]
-	>=dev-python/oslo-utils-3.18.0[${PYTHON_USEDEP}]
-	>=dev-python/stevedore-1.17.1[${PYTHON_USEDEP}]
-	>=dev-python/futurist-0.11.0[${PYTHON_USEDEP}]
-	!~dev-python/futurist-0.15.0[${PYTHON_USEDEP}]
-	>=dev-python/taskflow-2.7.0.0[${PYTHON_USEDEP}]
-	>=dev-python/keystoneauth-2.18.0[${PYTHON_USEDEP}]
-	>=dev-python/keystonemiddleware-4.12.0[${PYTHON_USEDEP}]
-	>=dev-python/WSME-0.8.0[${PYTHON_USEDEP}]
-	>=dev-python/prettytable-0.7.0[${PYTHON_USEDEP}]
-	<dev-python/prettytable-0.8.0[${PYTHON_USEDEP}]
-	dev-python/paste[${PYTHON_USEDEP}]
-	>=dev-python/jsonschema-2.0.0[${PYTHON_USEDEP}]
-	!~dev-python/jsonschema-2.5.0[${PYTHON_USEDEP}]
-	<dev-python/jsonschema-3.0.0[${PYTHON_USEDEP}]
-	>=dev-python/python-keystoneclient-3.8.0[${PYTHON_USEDEP}]
-	>=dev-python/pyopenssl-0.14[${PYTHON_USEDEP}]
-	>=dev-python/six-1.9.0[${PYTHON_USEDEP}]
-	>=dev-python/oslo-db-4.15.0[${PYTHON_USEDEP}]
-	>=dev-python/oslo-i18n-2.1.0[${PYTHON_USEDEP}]
-	>=dev-python/oslo-log-3.11.0[${PYTHON_USEDEP}]
-	>=dev-python/oslo-messaging-5.14.0[${PYTHON_USEDEP}]
-	>=dev-python/oslo-middleware-3.0.0[${PYTHON_USEDEP}]
-	>=dev-python/oslo-policy-1.17.0[${PYTHON_USEDEP}]
-	>=dev-python/retrying-1.2.3[${PYTHON_USEDEP}]
-	!~dev-python/retrying-1.3.0[${PYTHON_USEDEP}]
-	>=dev-python/osprofiler-1.4.0[${PYTHON_USEDEP}]
-	>=dev-python/glance_store-0.18.0[${PYTHON_USEDEP}]
-	>=dev-python/semantic_version-2.3.1[${PYTHON_USEDEP}]
-	>=dev-python/debtcollector-1.2.0[${PYTHON_USEDEP}]
-	>=dev-python/cryptography-1.0[${PYTHON_USEDEP}]
-	!~dev-python/cryptography-1.3.0[${PYTHON_USEDEP}]
-	>=dev-python/cursive-0.1.1[${PYTHON_USEDEP}]
-	>=dev-python/iso8601-0.1.11[${PYTHON_USEDEP}]
-	>=dev-python/monotonic-0.6[${PYTHON_USEDEP}]
-"
-
-#PATCHES=(
-#)
-
-pkg_setup() {
-	enewgroup glance
-	enewuser glance -1 -1 /var/lib/glance glance
-}
-
-python_prepare_all() {
-	sed -i '/xattr/d' test-requirements.txt || die
-	sed -i '/pysendfile/d' test-requirements.txt || die
-	sed -i '/^hacking/d' test-requirements.txt || die
-	distutils-r1_python_prepare_all
-}
-
-python_compile_all() {
-	use doc && "${PYTHON}" setup.py build_sphinx
-}
-
-python_install_all() {
-	distutils-r1_python_install_all
-
-	for svc in api glare registry scrubber; do
-		newinitd "${FILESDIR}/glance.initd-r2" glance-${svc}
-	done
-
-	diropts -m 0750 -o glance -g glance
-	dodir /var/log/glance /var/lib/glance/images /var/lib/glance/scrubber
-	keepdir /etc/glance
-	keepdir /var/log/glance
-	keepdir /var/lib/glance/images
-	keepdir /var/lib/glance/scrubber
-
-	insinto /etc/glance
-	insopts -m 0640 -o glance -g glance
-	doins -r etc/*.ini etc/*.conf etc/*.sample etc/*.json etc/meta*
-
-	use doc && local HTML_DOCS=( doc/build/html/. )
-	distutils-r1_python_install_all
-}

diff --git a/app-admin/glance/glance-2017.2.9999.ebuild b/app-admin/glance/glance-2017.2.9999.ebuild
index 71b923e6de6..34a29aa8cf5 100644
--- a/app-admin/glance/glance-2017.2.9999.ebuild
+++ b/app-admin/glance/glance-2017.2.9999.ebuild
@@ -1,4 +1,4 @@
-# Copyright 1999-2017 Gentoo Foundation
+# Copyright 1999-2018 Gentoo Foundation
 # Distributed under the terms of the GNU General Public License v2
 
 EAPI=6
@@ -126,7 +126,7 @@ python_compile_all() {
 python_install_all() {
 	distutils-r1_python_install_all
 
-	newinitd "${FILESDIR}/glance.initd-2" glance-api
+	newinitd "${FILESDIR}/glance.initd" glance-api
 
 	diropts -m 0750 -o glance -g glance
 	dodir /var/log/glance /var/lib/glance/images /var/lib/glance/scrubber


^ permalink raw reply related	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2018-01-28  4:13 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-08-14  5:21 [gentoo-commits] repo/gentoo:master commit in: app-admin/glance/files/, app-admin/glance/ Matt Thode
  -- strict thread matches above, loose matches on Subject: below --
2015-09-22 17:46 Matt Thode
2015-10-03 19:14 Matt Thode
2016-02-04 17:34 Matt Thode
2018-01-28  4:13 Matt Thode

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox