From 84a6a5780a2bcd68d7d43eea9a64139f4fd85e2b Mon Sep 17 00:00:00 2001 From: Jared Kipe Date: Tue, 2 Jul 2019 13:30:36 -0700 Subject: [PATCH 01/11] Initial commit of `attachment_minio` for 11.0 --- attachment_minio/__init__.py | 2 + attachment_minio/__manifest__.py | 51 +++++++++++ attachment_minio/models/__init__.py | 1 + attachment_minio/models/ir_attachment.py | 103 +++++++++++++++++++++++ attachment_minio/s3uri.py | 22 +++++ 5 files changed, 179 insertions(+) create mode 100755 attachment_minio/__init__.py create mode 100755 attachment_minio/__manifest__.py create mode 100644 attachment_minio/models/__init__.py create mode 100644 attachment_minio/models/ir_attachment.py create mode 100644 attachment_minio/s3uri.py diff --git a/attachment_minio/__init__.py b/attachment_minio/__init__.py new file mode 100755 index 00000000..899bcc97 --- /dev/null +++ b/attachment_minio/__init__.py @@ -0,0 +1,2 @@ +from . import models + diff --git a/attachment_minio/__manifest__.py b/attachment_minio/__manifest__.py new file mode 100755 index 00000000..8bd4e98b --- /dev/null +++ b/attachment_minio/__manifest__.py @@ -0,0 +1,51 @@ +{ + "name": "Attachment MinIO", + "version": "11.0.1.0.0", + "depends": [ + "base_attachment_object_storage", + ], + "author": "Hibou Corp.", + "license": "AGPL-3", + "description": """ +# Use MinIO (or Amazon S3) for Attachment/filestore + +MinIO provides S3 API compatible storage to scale out without a shared filesystem like NFS. + + +## Setup details + +Before installing this app, you should add several System Parameters. + +Key : Example Value : Default Value + +ir_attachment.location.host : minio.yourdomain.com : _ + +ir_attachment.location.bucket : odoo_prod : _ + +ir_attachment.location.region : us-west-1 : us-west-1 + +ir_attachment.location.access_key : odoo : _ + +ir_attachment.location.secret_key : 123456 : _ + +ir_attachment.location.secure : 1 : _ + + +In general, they should all be specified other than "region" (if you are not using AWS S3) +and "secure" which should be set if the "host" needs to be accessed over SSL/TLS. + +Install `attachment_minio` and during the installation `base_attachment_object_storage` should move +your existing filestore attachment files into the database or object storage. + """, + "summary": "", + "website": "", + "category": 'Tools', + "auto_install": False, + "installable": True, + "application": False, + "external_dependencies": { + "python": [ + "minio", + ], + }, +} diff --git a/attachment_minio/models/__init__.py b/attachment_minio/models/__init__.py new file mode 100644 index 00000000..aaf38a16 --- /dev/null +++ b/attachment_minio/models/__init__.py @@ -0,0 +1 @@ +from . import ir_attachment diff --git a/attachment_minio/models/ir_attachment.py b/attachment_minio/models/ir_attachment.py new file mode 100644 index 00000000..ba987899 --- /dev/null +++ b/attachment_minio/models/ir_attachment.py @@ -0,0 +1,103 @@ +import io +import base64 +import logging +from minio import Minio +from minio.error import NoSuchKey + +from odoo import api, exceptions, models, tools +from ..s3uri import S3Uri + +_logger = logging.getLogger(__name__) + + +class MinioAttachment(models.Model): + _inherit = 'ir.attachment' + + @api.model + def _get_minio_client(self): + params = self.env['ir.config_parameter'].sudo() + host = params.get_param('ir_attachment.location.host') + region = params.get_param('ir_attachment.location.region', 'us-west-1') + access_key = params.get_param('ir_attachment.location.access_key') + secret_key = params.get_param('ir_attachment.location.secret_key') + secure = params.get_param('ir_attachment.location.secure') + if not all((host, access_key, secret_key)): + raise exceptions.UserError('Incorrect configuration of attachment_minio.') + return Minio(host, + access_key=access_key, + secret_key=secret_key, + region=region, + secure=bool(secure)) + + @api.model + def _get_minio_bucket(self, client, name=None): + params = self.env['ir.config_parameter'].sudo() + bucket = name or params.get_param('ir_attachment.location.bucket') + if not bucket: + raise exceptions.UserError('Incorrect configuration of attachment_minio -- Missing bucket.') + if not client.bucket_exists(bucket): + client.make_bucket(bucket) + return bucket + + @api.model + def _get_minio_key(self, sha): + # scatter files across 256 dirs + # This mirrors Odoo's own object storage so that it is easier to migrate + # to or from external storage. + fname = sha[:2] + '/' + sha + return fname + + @api.model + def _get_minio_fname(self, bucket, key): + return 's3://%s/%s' % (bucket, key) + + # core API methods from base_attachment_object_storage + + def _get_stores(self): + res = super(MinioAttachment, self)._get_stores() + res.append('s3') + return res + + @api.model + def _store_file_read(self, fname, bin_size=False): + if fname.startswith('s3://'): + client = self._get_minio_client() + s3uri = S3Uri(fname) + bucket = self._get_minio_bucket(client, name=s3uri.bucket()) + try: + response = client.get_object(bucket, s3uri.item()) + return base64.b64encode(response.read()) + except NoSuchKey: + _logger.info('attachment "%s" missing from remote object storage', (fname, )) + return '' + return super(MinioAttachment, self)._store_file_read(fname, bin_size=bin_size) + + @api.model + def _store_file_write(self, key, bin_data): + if self._storage() == 's3': + client = self._get_minio_client() + bucket = self._get_minio_bucket(client) + minio_key = self._get_minio_key(key) + client.put_object(bucket, minio_key, io.BytesIO(bin_data), len(bin_data)) + return self._get_minio_fname(bucket, minio_key) + return super(MinioAttachment, self)._store_file_write(key, bin_data) + + @api.model + def _store_file_delete(self, fname): + if fname.startswith('s3://'): + client = self._get_minio_client() + try: + s3uri = S3Uri(fname) + except ValueError: + # Cannot delete unparsable file + return True + bucket_name = s3uri.bucket() + if bucket_name == self._get_s3_bucket(client): + try: + client.remove_object(bucket_name, s3uri.item()) + except NoSuchKey: + _logger.info('unable to remove missing attachment "%s" from remote object storage', (fname, )) + else: + _logger.info('skip delete "%s" because of bucket-mismatch', (fname, )) + return + return super(MinioAttachment, self)._store_file_delete(fname) diff --git a/attachment_minio/s3uri.py b/attachment_minio/s3uri.py new file mode 100644 index 00000000..f94df79e --- /dev/null +++ b/attachment_minio/s3uri.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2016 Camptocamp SA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html) + +import re + + +class S3Uri(object): + + _url_re = re.compile("^s3:///*([^/]*)/?(.*)", re.IGNORECASE | re.UNICODE) + + def __init__(self, uri): + match = self._url_re.match(uri) + if not match: + raise ValueError("%s: is not a valid S3 URI" % (uri,)) + self._bucket, self._item = match.groups() + + def bucket(self): + return self._bucket + + def item(self): + return self._item From 4fc1dd693b947c4049a844fca3c2ccfeba6ef3fe Mon Sep 17 00:00:00 2001 From: Jared Kipe Date: Tue, 2 Jul 2019 14:44:30 -0700 Subject: [PATCH 02/11] IMP `attachment_minio` improve requested parameters and bucket creation per testing. --- attachment_minio/__manifest__.py | 4 +++- attachment_minio/models/ir_attachment.py | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/attachment_minio/__manifest__.py b/attachment_minio/__manifest__.py index 8bd4e98b..89d7402b 100755 --- a/attachment_minio/__manifest__.py +++ b/attachment_minio/__manifest__.py @@ -18,9 +18,11 @@ Before installing this app, you should add several System Parameters. Key : Example Value : Default Value +ir_attachment.location : s3 : _ + ir_attachment.location.host : minio.yourdomain.com : _ -ir_attachment.location.bucket : odoo_prod : _ +ir_attachment.location.bucket : odoo-prod : _ ir_attachment.location.region : us-west-1 : us-west-1 diff --git a/attachment_minio/models/ir_attachment.py b/attachment_minio/models/ir_attachment.py index ba987899..8e5dbba5 100644 --- a/attachment_minio/models/ir_attachment.py +++ b/attachment_minio/models/ir_attachment.py @@ -36,7 +36,8 @@ class MinioAttachment(models.Model): if not bucket: raise exceptions.UserError('Incorrect configuration of attachment_minio -- Missing bucket.') if not client.bucket_exists(bucket): - client.make_bucket(bucket) + region = params.get_param('ir_attachment.location.region', 'us-west-1') + client.make_bucket(bucket, region) return bucket @api.model From f7f881e8b8dd838cced72f72da5906f147b1243b Mon Sep 17 00:00:00 2001 From: Jared Kipe Date: Sun, 7 Jul 2019 06:37:17 -0700 Subject: [PATCH 03/11] FIX `attachment_minio` Cannot delete attachments. --- attachment_minio/__manifest__.py | 7 +++++-- attachment_minio/models/ir_attachment.py | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/attachment_minio/__manifest__.py b/attachment_minio/__manifest__.py index 89d7402b..5b7c2f32 100755 --- a/attachment_minio/__manifest__.py +++ b/attachment_minio/__manifest__.py @@ -7,12 +7,15 @@ "author": "Hibou Corp.", "license": "AGPL-3", "description": """ -# Use MinIO (or Amazon S3) for Attachment/filestore +################################################# +Use MinIO (or Amazon S3) for Attachment/filestore +################################################# MinIO provides S3 API compatible storage to scale out without a shared filesystem like NFS. -## Setup details +Setup details +############# Before installing this app, you should add several System Parameters. diff --git a/attachment_minio/models/ir_attachment.py b/attachment_minio/models/ir_attachment.py index 8e5dbba5..599c3d83 100644 --- a/attachment_minio/models/ir_attachment.py +++ b/attachment_minio/models/ir_attachment.py @@ -93,7 +93,7 @@ class MinioAttachment(models.Model): # Cannot delete unparsable file return True bucket_name = s3uri.bucket() - if bucket_name == self._get_s3_bucket(client): + if bucket_name == self._get_minio_bucket(client): try: client.remove_object(bucket_name, s3uri.item()) except NoSuchKey: From 9fbd27d0aa6c524a48d8e33bc49c0fb9f4937831 Mon Sep 17 00:00:00 2001 From: Jared Kipe Date: Thu, 10 Oct 2019 15:50:12 -0700 Subject: [PATCH 04/11] MIG `attachment_minio` to 12.0 --- attachment_minio/__manifest__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/attachment_minio/__manifest__.py b/attachment_minio/__manifest__.py index 5b7c2f32..cdf2d0e3 100755 --- a/attachment_minio/__manifest__.py +++ b/attachment_minio/__manifest__.py @@ -1,6 +1,6 @@ { "name": "Attachment MinIO", - "version": "11.0.1.0.0", + "version": "12.0.1.0.0", "depends": [ "base_attachment_object_storage", ], From 48e6d8f608b4d18a3d19726b5573928a6cd53aac Mon Sep 17 00:00:00 2001 From: Jared Kipe Date: Fri, 11 Oct 2019 13:55:05 -0700 Subject: [PATCH 05/11] IMP `attachment_minio` Allow configuration via config file and improve documentation. --- attachment_minio/README.md | 52 +++++++++++++++++++++ attachment_minio/__manifest__.py | 57 ++++++++++++++++-------- attachment_minio/models/ir_attachment.py | 14 +++--- 3 files changed, 98 insertions(+), 25 deletions(-) create mode 100644 attachment_minio/README.md diff --git a/attachment_minio/README.md b/attachment_minio/README.md new file mode 100644 index 00000000..1e32a8e0 --- /dev/null +++ b/attachment_minio/README.md @@ -0,0 +1,52 @@ +# Use MinIO (or Amazon S3) for Attachment/filestore + +MinIO provides S3 API compatible storage to scale out without a shared filesystem like NFS. + +This module will store the bucket used in the attachment database object, thus allowing +you to retain read-only access to the filestore by simply overriding the bucket. + +## Setup details + +Before installing this app, you should add several System Parameters (the most important of +which is `ir_attachment.location`), OR set them through the config file as described later. + +**The in database System Parameters will act as overrides to the Config File versions.** + +| Key | Example Value | Default Value | +|-----------------------------------|---------------|---------------| +| ir_attachment.location | s3 | | +| ir_attachment.location.host | minio:9000 | | +| ir_attachment.location.bucket | odoo | | +| ir_attachment.location.region | us-west-1 | us-west-1 | +| ir_attachment.location.access_key | minio | | +| ir_attachment.location.secret_key | minio_secret | | +| ir_attachment.location.secure | 1 | | + +**Config File:** + +``` +attachment_minio_host = minio:9000 +attachment_minio_region = us-west-1 +attachment_minio_access_key = minio +attachment_minio_secret_key = minio_secret +attachment_minio_bucket = odoo +attachment_minio_secure = False +``` + +In general, they should all be specified other than "region" (if you are not using AWS S3) +and "secure" which should be set if the "host" needs to be accessed over SSL/TLS. + +Install `attachment_minio` and during the installation `base_attachment_object_storage` should move +your existing filestore attachment files into the database or object storage. + +For example, you can run a shell command like the following to set the parameter: + +``` +env['ir.config_parameter'].set_param('ir_attachment.location', 's3') +# If already installed... +# env['ir.attachment'].force_storage() +env.cr.commit() +``` + +If `attachment_minio` is not already installed, you can then install it and the migration +should be noted in the logs. **Ensure that the timeouts are long enough that the migration can finish.** diff --git a/attachment_minio/__manifest__.py b/attachment_minio/__manifest__.py index cdf2d0e3..973a8b1d 100755 --- a/attachment_minio/__manifest__.py +++ b/attachment_minio/__manifest__.py @@ -7,40 +7,59 @@ "author": "Hibou Corp.", "license": "AGPL-3", "description": """ -################################################# -Use MinIO (or Amazon S3) for Attachment/filestore -################################################# +# Use MinIO (or Amazon S3) for Attachment/filestore MinIO provides S3 API compatible storage to scale out without a shared filesystem like NFS. +This module will store the bucket used in the attachment database object, thus allowing +you to retain read-only access to the filestore by simply overriding the bucket. -Setup details -############# +## Setup details -Before installing this app, you should add several System Parameters. +Before installing this app, you should add several System Parameters (the most important of +which is `ir_attachment.location`), OR set them through the config file as described later. -Key : Example Value : Default Value +**The in database System Parameters will act as overrides to the Config File versions.** -ir_attachment.location : s3 : _ +| Key | Example Value | Default Value | +|-----------------------------------|---------------|---------------| +| ir_attachment.location | s3 | | +| ir_attachment.location.host | minio:9000 | | +| ir_attachment.location.bucket | odoo | | +| ir_attachment.location.region | us-west-1 | us-west-1 | +| ir_attachment.location.access_key | minio | | +| ir_attachment.location.secret_key | minio_secret | | +| ir_attachment.location.secure | 1 | | -ir_attachment.location.host : minio.yourdomain.com : _ - -ir_attachment.location.bucket : odoo-prod : _ - -ir_attachment.location.region : us-west-1 : us-west-1 - -ir_attachment.location.access_key : odoo : _ - -ir_attachment.location.secret_key : 123456 : _ - -ir_attachment.location.secure : 1 : _ +**Config File:** +``` +attachment_minio_host = minio:9000 +attachment_minio_region = us-west-1 +attachment_minio_access_key = minio +attachment_minio_secret_key = minio_secret +attachment_minio_bucket = odoo +attachment_minio_secure = False +``` In general, they should all be specified other than "region" (if you are not using AWS S3) and "secure" which should be set if the "host" needs to be accessed over SSL/TLS. Install `attachment_minio` and during the installation `base_attachment_object_storage` should move your existing filestore attachment files into the database or object storage. + +For example, you can run a shell command like the following to set the parameter: + +``` +env['ir.config_parameter'].set_param('ir_attachment.location', 's3') +# If already installed... +# env['ir.attachment'].force_storage() +env.cr.commit() +``` + +If `attachment_minio` is not already installed, you can then install it and the migration +should be noted in the logs. **Ensure that the timeouts are long enough that the migration can finish.** + """, "summary": "", "website": "", diff --git a/attachment_minio/models/ir_attachment.py b/attachment_minio/models/ir_attachment.py index 599c3d83..08122566 100644 --- a/attachment_minio/models/ir_attachment.py +++ b/attachment_minio/models/ir_attachment.py @@ -15,12 +15,13 @@ class MinioAttachment(models.Model): @api.model def _get_minio_client(self): + config = tools.config params = self.env['ir.config_parameter'].sudo() - host = params.get_param('ir_attachment.location.host') - region = params.get_param('ir_attachment.location.region', 'us-west-1') - access_key = params.get_param('ir_attachment.location.access_key') - secret_key = params.get_param('ir_attachment.location.secret_key') - secure = params.get_param('ir_attachment.location.secure') + host = params.get_param('ir_attachment.location.host') or config.get('attachment_minio_host') + region = params.get_param('ir_attachment.location.region') or config.get('attachment_minio_region', 'us-west-1') + access_key = params.get_param('ir_attachment.location.access_key') or config.get('attachment_minio_access_key') + secret_key = params.get_param('ir_attachment.location.secret_key') or config.get('attachment_minio_secret_key') + secure = params.get_param('ir_attachment.location.secure') or config.get('attachment_minio_secure') if not all((host, access_key, secret_key)): raise exceptions.UserError('Incorrect configuration of attachment_minio.') return Minio(host, @@ -31,8 +32,9 @@ class MinioAttachment(models.Model): @api.model def _get_minio_bucket(self, client, name=None): + config = tools.config params = self.env['ir.config_parameter'].sudo() - bucket = name or params.get_param('ir_attachment.location.bucket') + bucket = name or params.get_param('ir_attachment.location.bucket') or config.get('attachment_minio_bucket') if not bucket: raise exceptions.UserError('Incorrect configuration of attachment_minio -- Missing bucket.') if not client.bucket_exists(bucket): From b807f6a0d26e44eec99891e72320a20336196010 Mon Sep 17 00:00:00 2001 From: Jared Kipe Date: Fri, 13 Mar 2020 08:47:45 -0700 Subject: [PATCH 06/11] FIX `attachment_minio` add copyright header to ir_attachment.py --- attachment_minio/models/ir_attachment.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/attachment_minio/models/ir_attachment.py b/attachment_minio/models/ir_attachment.py index 08122566..7a50ad16 100644 --- a/attachment_minio/models/ir_attachment.py +++ b/attachment_minio/models/ir_attachment.py @@ -1,3 +1,7 @@ +# Copyright 2020 Hibou Corp. +# Copyright 2016 Camptocamp SA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html) + import io import base64 import logging From 8197607dab60ca4cbdae07f9ff66ac112a0ceede Mon Sep 17 00:00:00 2001 From: Jared Kipe Date: Wed, 1 Jul 2020 15:29:21 -0700 Subject: [PATCH 07/11] [MIG] attachment_minio: odoo 13, additionally include mime-type per GITHUB#12 --- attachment_minio/README.md | 8 ++++++++ attachment_minio/__manifest__.py | 2 +- attachment_minio/models/ir_attachment.py | 4 +++- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/attachment_minio/README.md b/attachment_minio/README.md index 1e32a8e0..3a81269c 100644 --- a/attachment_minio/README.md +++ b/attachment_minio/README.md @@ -50,3 +50,11 @@ env.cr.commit() If `attachment_minio` is not already installed, you can then install it and the migration should be noted in the logs. **Ensure that the timeouts are long enough that the migration can finish.** + +### Base Setup + +This module utilizes `base_attachment_object_storage` + +The System Parameter `ir_attachment.storage.force.database` can be customized to +force storage of files in the database. See the documentation of the module +`base_attachment_object_storage`. diff --git a/attachment_minio/__manifest__.py b/attachment_minio/__manifest__.py index 973a8b1d..fe230ae8 100755 --- a/attachment_minio/__manifest__.py +++ b/attachment_minio/__manifest__.py @@ -1,6 +1,6 @@ { "name": "Attachment MinIO", - "version": "12.0.1.0.0", + "version": "13.0.1.0.0", "depends": [ "base_attachment_object_storage", ], diff --git a/attachment_minio/models/ir_attachment.py b/attachment_minio/models/ir_attachment.py index 7a50ad16..70ba2640 100644 --- a/attachment_minio/models/ir_attachment.py +++ b/attachment_minio/models/ir_attachment.py @@ -85,7 +85,9 @@ class MinioAttachment(models.Model): client = self._get_minio_client() bucket = self._get_minio_bucket(client) minio_key = self._get_minio_key(key) - client.put_object(bucket, minio_key, io.BytesIO(bin_data), len(bin_data)) + with io.BytesIO(bin_data) as bin_data_io: + client.put_object(bucket, minio_key, bin_data_io, len(bin_data), + content_type=self.mimetype) return self._get_minio_fname(bucket, minio_key) return super(MinioAttachment, self)._store_file_write(key, bin_data) From 24b4ba6ffac97e8950bd823e8d7afc4a98cb7616 Mon Sep 17 00:00:00 2001 From: Jared Kipe Date: Thu, 9 Jul 2020 15:22:16 -0700 Subject: [PATCH 08/11] [IMP] attachment_minio: add post migration script to move some views out of attachment storage Every database I've run the search (for s3 attachments for specific fields or models) on has not returned any attachments, but it seems safe enough in general, and presumably happens when migrating from older versions. --- .../migrations/13.0.0.0.1/post-migration.py | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 attachment_minio/migrations/13.0.0.0.1/post-migration.py diff --git a/attachment_minio/migrations/13.0.0.0.1/post-migration.py b/attachment_minio/migrations/13.0.0.0.1/post-migration.py new file mode 100644 index 00000000..fefe6dbf --- /dev/null +++ b/attachment_minio/migrations/13.0.0.0.1/post-migration.py @@ -0,0 +1,60 @@ +# Copyright 2020 Hibou Corp. +# Copyright 2016-2019 Camptocamp SA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html) + +import logging + +from contextlib import closing + +import odoo + +_logger = logging.getLogger(__name__) + + +def migrate(cr, version): + if not version: + return + cr.execute(""" + SELECT value FROM ir_config_parameter + WHERE key = 'ir_attachment.location' + """) + row = cr.fetchone() + + if row[0] == 's3': + uid = odoo.SUPERUSER_ID + registry = odoo.modules.registry.RegistryManager.get(cr.dbname) + new_cr = registry.cursor() + with closing(new_cr): + with odoo.api.Environment.manage(): + env = odoo.api.Environment(new_cr, uid, {}) + store_local = env['ir.attachment'].search( + [('store_fname', '=like', 's3://%'), + '|', ('res_model', '=', 'ir.ui.view'), + ('res_field', 'in', ['image_small', + 'image_medium', + 'web_icon_data']) + ], + ) + + _logger.info( + 'Moving %d attachments from S3 to DB for fast access', + len(store_local) + ) + for attachment_id in store_local.ids: + # force re-storing the document, will move + # it from the object storage to the database + + # This is a trick to avoid having the 'datas' function + # fields computed for every attachment on each + # iteration of the loop. The former issue being that + # it reads the content of the file of ALL the + # attachments on each loop. + try: + env.clear() + attachment = env['ir.attachment'].browse(attachment_id) + _logger.info('Moving attachment %s (id: %s)', + attachment.name, attachment.id) + attachment.write({'datas': attachment.datas}) + new_cr.commit() + except: + new_cr.rollback() From e84e86d11c0da7f4b0f7f7433b55826156918c81 Mon Sep 17 00:00:00 2001 From: Jared Kipe Date: Thu, 27 Aug 2020 09:06:04 -0700 Subject: [PATCH 09/11] [FIX] attachment_minio: Odoo registry class name change --- attachment_minio/migrations/13.0.0.0.1/post-migration.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/attachment_minio/migrations/13.0.0.0.1/post-migration.py b/attachment_minio/migrations/13.0.0.0.1/post-migration.py index fefe6dbf..068cdab0 100644 --- a/attachment_minio/migrations/13.0.0.0.1/post-migration.py +++ b/attachment_minio/migrations/13.0.0.0.1/post-migration.py @@ -22,7 +22,7 @@ def migrate(cr, version): if row[0] == 's3': uid = odoo.SUPERUSER_ID - registry = odoo.modules.registry.RegistryManager.get(cr.dbname) + registry = odoo.modules.registry.Registry(cr.dbname) new_cr = registry.cursor() with closing(new_cr): with odoo.api.Environment.manage(): From c7d5170f41994e2cf59d3c0f0f4de8d1f596632b Mon Sep 17 00:00:00 2001 From: Jared Kipe Date: Thu, 3 Sep 2020 13:05:00 -0700 Subject: [PATCH 10/11] [IMP] attachment_minio: Handle migrated `image.mixin` field `image_128` --- attachment_minio/migrations/13.0.0.0.1/post-migration.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/attachment_minio/migrations/13.0.0.0.1/post-migration.py b/attachment_minio/migrations/13.0.0.0.1/post-migration.py index 068cdab0..b8a62e3a 100644 --- a/attachment_minio/migrations/13.0.0.0.1/post-migration.py +++ b/attachment_minio/migrations/13.0.0.0.1/post-migration.py @@ -32,7 +32,14 @@ def migrate(cr, version): '|', ('res_model', '=', 'ir.ui.view'), ('res_field', 'in', ['image_small', 'image_medium', - 'web_icon_data']) + 'web_icon_data', + # image.mixin sizes + # image_128 is essentially image_medium + 'image_128', + # depending on use case, these may need migrated/moved + # 'image_256', + # 'image_512', + ]) ], ) From a717f9c4bf495b510e4ed103f7e42af1328cf029 Mon Sep 17 00:00:00 2001 From: Jared Kipe Date: Sun, 21 Mar 2021 13:19:30 -0700 Subject: [PATCH 11/11] [MIG] attachment_minio: for Odoo 14.0 --- attachment_minio/__manifest__.py | 2 +- .../migrations/{13.0.0.0.1 => 14.0.0.0.1}/post-migration.py | 0 attachment_minio/models/ir_attachment.py | 3 +-- 3 files changed, 2 insertions(+), 3 deletions(-) rename attachment_minio/migrations/{13.0.0.0.1 => 14.0.0.0.1}/post-migration.py (100%) diff --git a/attachment_minio/__manifest__.py b/attachment_minio/__manifest__.py index fe230ae8..495041dc 100755 --- a/attachment_minio/__manifest__.py +++ b/attachment_minio/__manifest__.py @@ -1,6 +1,6 @@ { "name": "Attachment MinIO", - "version": "13.0.1.0.0", + "version": "14.0.1.0.0", "depends": [ "base_attachment_object_storage", ], diff --git a/attachment_minio/migrations/13.0.0.0.1/post-migration.py b/attachment_minio/migrations/14.0.0.0.1/post-migration.py similarity index 100% rename from attachment_minio/migrations/13.0.0.0.1/post-migration.py rename to attachment_minio/migrations/14.0.0.0.1/post-migration.py diff --git a/attachment_minio/models/ir_attachment.py b/attachment_minio/models/ir_attachment.py index 70ba2640..2d963f8f 100644 --- a/attachment_minio/models/ir_attachment.py +++ b/attachment_minio/models/ir_attachment.py @@ -3,7 +3,6 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html) import io -import base64 import logging from minio import Minio from minio.error import NoSuchKey @@ -73,7 +72,7 @@ class MinioAttachment(models.Model): bucket = self._get_minio_bucket(client, name=s3uri.bucket()) try: response = client.get_object(bucket, s3uri.item()) - return base64.b64encode(response.read()) + return response.read() except NoSuchKey: _logger.info('attachment "%s" missing from remote object storage', (fname, )) return ''