mirror of
https://github.com/camptocamp/odoo-cloud-platform.git
synced 2026-06-24 08:47:40 +00:00
[IMP] attachment_azure: Add support for DB operations
This commit is contained in:
committed by
Maxime Chambreuil
co-authored by
Maxime Chambreuil
parent
4b61f43f85
commit
1c25f1c1a8
@@ -13,20 +13,44 @@ Activate Azure Blob storage:
|
|||||||
* Create or set the system parameter with the key ``ir_attachment.location``
|
* Create or set the system parameter with the key ``ir_attachment.location``
|
||||||
and the value in the form ``azure``.
|
and the value in the form ``azure``.
|
||||||
|
|
||||||
Configure accesses with environment variables:
|
* Configure accesses with the following environment variables:
|
||||||
|
|
||||||
* ``AZURE_STORAGE_CONNECTION_STRING`` or
|
.. list-table::
|
||||||
* ``AZURE_STORAGE_ACCOUNT_NAME``
|
:header-rows: 1
|
||||||
* ``AZURE_STORAGE_ACCOUNT_URL``
|
|
||||||
* ``AZURE_STORAGE_ACCOUNT_KEY``
|
* - Name
|
||||||
|
- Description
|
||||||
|
- Values
|
||||||
|
* - ``AZURE_STORAGE_CONNECTION_STRING``
|
||||||
|
- Connection string.
|
||||||
|
- Required if using the connection string authentication method.
|
||||||
|
* - ``AZURE_STORAGE_ACCOUNT_NAME``
|
||||||
|
- Name of the storage account.
|
||||||
|
- Required if using the storage account authentication method.
|
||||||
|
* - ``AZURE_STORAGE_ACCOUNT_URL``
|
||||||
|
- URL of the storage account
|
||||||
|
-
|
||||||
|
* - ``AZURE_STORAGE_ACCOUNT_KEY``
|
||||||
|
- Key of the storage account
|
||||||
|
-
|
||||||
|
* - ``AZURE_STORAGE_NAME``
|
||||||
|
- Name of the container within the blob storage. 1 container per database will be
|
||||||
|
created.
|
||||||
|
- Optional. The strings ``{db}`` and ``{env}`` can be used inside that variable
|
||||||
|
and the values will be replaced respectively by the database name and environment
|
||||||
|
name.
|
||||||
|
* - ``AZURE_DUPLICATE``
|
||||||
|
- If set, the blob storage and all its objects will be copied when the database is
|
||||||
|
duplicated.
|
||||||
|
- True
|
||||||
|
* - ``AZURE_DELETE_ON_DBDROP``
|
||||||
|
- If set, the container and all its objects will be deleted when the database is
|
||||||
|
dropped.
|
||||||
|
- True
|
||||||
|
|
||||||
One container will be created per database using the `RUNNING_ENV` environment variable
|
One container will be created per database using the `RUNNING_ENV` environment variable
|
||||||
and the name of the database. By default, `RUNNING_ENV` is set to `dev`.
|
and the name of the database. By default, `RUNNING_ENV` is set to `dev`.
|
||||||
|
|
||||||
The container name can be overridden with environment variable ``AZURE_STORAGE_NAME``.
|
|
||||||
The strings ``{db}`` and ``{env}`` can be used inside that variable and the values
|
|
||||||
will be replaced respectively by the database name and environment name.
|
|
||||||
|
|
||||||
This addon must be added in the server wide addons with (``--load`` option):
|
This addon must be added in the server wide addons with (``--load`` option):
|
||||||
|
|
||||||
``--load=web,attachment_azure``
|
``--load=web,attachment_azure``
|
||||||
|
|||||||
@@ -1,4 +1,20 @@
|
|||||||
# Copyright 2016-2019 Camptocamp SA
|
# Copyright 2016-2019 Camptocamp SA
|
||||||
# Copyright 2021 Open Source Integrators
|
# Copyright 2021 Open Source Integrators
|
||||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
|
||||||
|
import os
|
||||||
|
|
||||||
from . import models
|
from . import models
|
||||||
|
from . import controllers
|
||||||
|
|
||||||
|
from odoo import api, SUPERUSER_ID
|
||||||
|
|
||||||
|
|
||||||
|
def _post_init_hook(cr, registry):
|
||||||
|
# create the S3 bucket after module installation
|
||||||
|
if os.environ.get("AZURE_STORAGE_CONNECTION_STRING", False):
|
||||||
|
env = api.Environment(cr, SUPERUSER_ID, {})
|
||||||
|
env["ir.attachment"]._get_azure_container()
|
||||||
|
env["ir.config_parameter"].create(
|
||||||
|
{"key": "ir_attachment.location", "value": "azure"}
|
||||||
|
)
|
||||||
|
env["ir.attachment"].force_storage()
|
||||||
|
|||||||
@@ -18,5 +18,6 @@
|
|||||||
"website": "https://github.com/camptocamp/odoo-cloud-platform",
|
"website": "https://github.com/camptocamp/odoo-cloud-platform",
|
||||||
"installable": True,
|
"installable": True,
|
||||||
"development_status": "Beta",
|
"development_status": "Beta",
|
||||||
|
"post_init_hook": "_post_init_hook",
|
||||||
"maintainers": ["max3903"],
|
"maintainers": ["max3903"],
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
from . import main
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
import logging
|
||||||
|
import os
|
||||||
|
|
||||||
|
from odoo.addons.web.controllers.main import Database
|
||||||
|
from odoo import http
|
||||||
|
from odoo import exceptions
|
||||||
|
from odoo.http import request
|
||||||
|
|
||||||
|
_logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class Database(Database):
|
||||||
|
@http.route()
|
||||||
|
def drop(self, master_pwd, name):
|
||||||
|
res = super().drop(master_pwd, name)
|
||||||
|
delete = os.environ.get("AZURE_DELETE_ON_DBDROP", False)
|
||||||
|
if delete:
|
||||||
|
attachment_obj = request.env["ir.attachment"]
|
||||||
|
try:
|
||||||
|
container_name = attachment_obj._get_container_name()
|
||||||
|
blob_service_client = attachment_obj._get_blob_service_client()
|
||||||
|
container_client = blob_service_client.get_container_client(
|
||||||
|
container_name
|
||||||
|
)
|
||||||
|
container_client.delete_container()
|
||||||
|
except exceptions.UserError:
|
||||||
|
_logger.exception("Error deleting attachments from object storage.")
|
||||||
|
return res
|
||||||
|
|
||||||
|
@http.route()
|
||||||
|
def duplicate(self, master_pwd, name, new_name):
|
||||||
|
res = super().duplicate(master_pwd, name, new_name)
|
||||||
|
duplicate = os.environ.get("AWS_DUPLICATE", False)
|
||||||
|
if duplicate:
|
||||||
|
attachment_obj = request.env["ir.attachment"]
|
||||||
|
try:
|
||||||
|
copy_from_container = attachment_obj._get_container_name()
|
||||||
|
copy_to_container = attachment_obj._get_container_name(new_name)
|
||||||
|
blob_service = attachment_obj._get_blob_service_client()
|
||||||
|
container_client = blob_service.get_container_client(
|
||||||
|
copy_from_container
|
||||||
|
)
|
||||||
|
|
||||||
|
blobs_list = container_client.list_blobs()
|
||||||
|
for blob in blobs_list:
|
||||||
|
blob_url = container_client.make_blob_url(
|
||||||
|
copy_from_container, blob.name
|
||||||
|
)
|
||||||
|
container_client.copy_blob(copy_to_container, blob.name, blob_url)
|
||||||
|
except exceptions.UserError:
|
||||||
|
_logger.exception("Error writing attachments to object storage.")
|
||||||
|
return res
|
||||||
|
|
||||||
|
@http.route()
|
||||||
|
def restore(self, master_pwd, backup_file, name, copy=False):
|
||||||
|
res = super().restore(master_pwd, backup_file, name, copy)
|
||||||
|
attachment_obj = request.env["ir.attachment"]
|
||||||
|
try:
|
||||||
|
attachment_obj._get_azure_container()
|
||||||
|
request.env["ir.config_parameter"].create(
|
||||||
|
{"key": "ir_attachment.location", "value": "azure"}
|
||||||
|
)
|
||||||
|
attachment_obj.force_storage()
|
||||||
|
except exceptions.UserError:
|
||||||
|
_logger.exception("Error writing attachments to object storage.")
|
||||||
|
return res
|
||||||
@@ -111,16 +111,15 @@ class IrAttachment(models.Model):
|
|||||||
return blob_service_client
|
return blob_service_client
|
||||||
|
|
||||||
@api.model
|
@api.model
|
||||||
def _get_container_name(self):
|
def _get_container_name(self, db_name=None):
|
||||||
"""
|
"""
|
||||||
Container naming rules:
|
Container naming rules:
|
||||||
https://docs.microsoft.com/en-us/rest/api/storageservices/naming-and-referencing-containers--blobs--and-metadata#container-names
|
https://docs.microsoft.com/en-us/rest/api/storageservices/naming-and-referencing-containers--blobs--and-metadata#container-names
|
||||||
"""
|
"""
|
||||||
running_env = os.environ.get("RUNNING_ENV", "dev")
|
running_env = os.environ.get("RUNNING_ENV", "dev")
|
||||||
storage_name = os.environ.get('AZURE_STORAGE_NAME', r'{env}-{db}')
|
storage_name = os.environ.get("AZURE_STORAGE_NAME", r"{env}-{db}")
|
||||||
storage_name = storage_name.format(
|
storage_name = storage_name.format(
|
||||||
env=running_env,
|
env=running_env, db=db_name or self.env.cr.dbname
|
||||||
db=self.env.cr.dbname
|
|
||||||
)
|
)
|
||||||
# replace invalid characters by _
|
# replace invalid characters by _
|
||||||
storage_name = re.sub(r"[\W_]+", "-", storage_name)
|
storage_name = re.sub(r"[\W_]+", "-", storage_name)
|
||||||
|
|||||||
Reference in New Issue
Block a user