mirror of
https://github.com/netbox-community/netbox.git
synced 2024-05-10 07:54:54 +00:00
Implement storage configuration as suggested by @jeremystretch
This commit is contained in:
@ -611,21 +611,20 @@ class ImageAttachment(models.Model):
|
|||||||
@property
|
@property
|
||||||
def size(self):
|
def size(self):
|
||||||
"""
|
"""
|
||||||
Wrapper around `image.size` to suppress an OSError in case the file is inaccessible. When S3 storage is used
|
Wrapper around `image.size` to suppress an OSError in case the file is inaccessible. Also opportunistically
|
||||||
ClientError is suppressed instead.
|
catch other exceptions that we know other storage back-ends to throw.
|
||||||
"""
|
"""
|
||||||
from django.conf import settings
|
expected_exceptions = [OSError]
|
||||||
if settings.MEDIA_STORAGE and settings.MEDIA_STORAGE['BACKEND'] == 'S3':
|
|
||||||
# For S3 we need to handle a different exception
|
|
||||||
from botocore.exceptions import ClientError
|
|
||||||
try:
|
try:
|
||||||
return self.image.size
|
from botocore.exceptions import ClientError
|
||||||
except ClientError:
|
expected_exceptions.append(ClientError)
|
||||||
return None
|
except ImportError:
|
||||||
|
pass
|
||||||
|
|
||||||
try:
|
try:
|
||||||
return self.image.size
|
return self.image.size
|
||||||
except OSError:
|
except tuple(expected_exceptions):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
@ -141,26 +141,14 @@ MAX_PAGE_SIZE = 1000
|
|||||||
# the default value of this setting is derived from the installed location.
|
# the default value of this setting is derived from the installed location.
|
||||||
# MEDIA_ROOT = '/opt/netbox/netbox/media'
|
# MEDIA_ROOT = '/opt/netbox/netbox/media'
|
||||||
|
|
||||||
# By default uploaded media is stored on the local filesystem. Use the following configuration to store media on
|
# By default uploaded media is stored on the local filesystem. Using Django-storages is also supported. Provide the
|
||||||
# AWS S3 or compatible service.
|
# class path of the storage driver in STORAGE_BACKEND and any configuration options in STORAGE_CONFIG. For example:
|
||||||
# MEDIA_STORAGE = {
|
# STORAGE_BACKEND = 'storages.backends.s3boto3.S3Boto3Storage'
|
||||||
# # Required configuration
|
# STORAGE_CONFIG = {
|
||||||
# 'BACKEND': 'S3',
|
# 'AWS_ACCESS_KEY_ID': 'Key ID',
|
||||||
# 'ACCESS_KEY_ID': 'Key ID',
|
# 'AWS_SECRET_ACCESS_KEY': 'Secret',
|
||||||
# 'SECRET_ACCESS_KEY': 'Secret',
|
# 'AWS_STORAGE_BUCKET_NAME': 'netbox',
|
||||||
# 'BUCKET_NAME': 'netbox',
|
# 'AWS_S3_REGION_NAME': 'eu-west-1',
|
||||||
#
|
|
||||||
# # Optional configuration, defaults are shown
|
|
||||||
# 'REGION_NAME': '',
|
|
||||||
# 'ENDPOINT_URL': None,
|
|
||||||
# 'AUTO_CREATE_BUCKET': False,
|
|
||||||
# 'BUCKET_ACL': 'public-read',
|
|
||||||
# 'DEFAULT_ACL': 'public-read',
|
|
||||||
# 'OBJECT_PARAMETERS': {
|
|
||||||
# 'CacheControl': 'max-age=86400',
|
|
||||||
# },
|
|
||||||
# 'QUERYSTRING_AUTH': True,
|
|
||||||
# 'QUERYSTRING_EXPIRE': 3600,
|
|
||||||
# }
|
# }
|
||||||
|
|
||||||
# Expose Prometheus monitoring metrics at the HTTP endpoint '/metrics'
|
# Expose Prometheus monitoring metrics at the HTTP endpoint '/metrics'
|
||||||
|
@ -83,7 +83,8 @@ LOGIN_TIMEOUT = getattr(configuration, 'LOGIN_TIMEOUT', None)
|
|||||||
MAINTENANCE_MODE = getattr(configuration, 'MAINTENANCE_MODE', False)
|
MAINTENANCE_MODE = getattr(configuration, 'MAINTENANCE_MODE', False)
|
||||||
MAX_PAGE_SIZE = getattr(configuration, 'MAX_PAGE_SIZE', 1000)
|
MAX_PAGE_SIZE = getattr(configuration, 'MAX_PAGE_SIZE', 1000)
|
||||||
MEDIA_ROOT = getattr(configuration, 'MEDIA_ROOT', os.path.join(BASE_DIR, 'media')).rstrip('/')
|
MEDIA_ROOT = getattr(configuration, 'MEDIA_ROOT', os.path.join(BASE_DIR, 'media')).rstrip('/')
|
||||||
MEDIA_STORAGE = getattr(configuration, 'MEDIA_STORAGE', None)
|
STORAGE_BACKEND = getattr(configuration, 'STORAGE_BACKEND', None)
|
||||||
|
STORAGE_CONFIG = getattr(configuration, 'STORAGE_CONFIG', {})
|
||||||
METRICS_ENABLED = getattr(configuration, 'METRICS_ENABLED', False)
|
METRICS_ENABLED = getattr(configuration, 'METRICS_ENABLED', False)
|
||||||
NAPALM_ARGS = getattr(configuration, 'NAPALM_ARGS', {})
|
NAPALM_ARGS = getattr(configuration, 'NAPALM_ARGS', {})
|
||||||
NAPALM_PASSWORD = getattr(configuration, 'NAPALM_PASSWORD', '')
|
NAPALM_PASSWORD = getattr(configuration, 'NAPALM_PASSWORD', '')
|
||||||
@ -123,46 +124,19 @@ DATABASES = {
|
|||||||
# Media storage
|
# Media storage
|
||||||
#
|
#
|
||||||
|
|
||||||
if MEDIA_STORAGE:
|
if STORAGE_BACKEND is not None:
|
||||||
if 'BACKEND' not in MEDIA_STORAGE:
|
DEFAULT_FILE_STORAGE = STORAGE_BACKEND
|
||||||
raise ImproperlyConfigured(
|
|
||||||
"Required parameter BACKEND is missing from MEDIA_STORAGE in configuration.py."
|
|
||||||
)
|
|
||||||
|
|
||||||
if MEDIA_STORAGE['BACKEND'] == 'S3':
|
if STORAGE_BACKEND.startswith('storages.'):
|
||||||
# Enforce required configuration parameters
|
# Monkey-patch Django-storages to also fetch settings from STORAGE_CONFIG
|
||||||
for parameter in ['ACCESS_KEY_ID', 'SECRET_ACCESS_KEY', 'BUCKET_NAME']:
|
import storages.utils
|
||||||
if parameter not in MEDIA_STORAGE:
|
|
||||||
raise ImproperlyConfigured(
|
|
||||||
"Required parameter {} is missing from MEDIA_STORAGE in configuration.py.".format(parameter)
|
|
||||||
)
|
|
||||||
|
|
||||||
# Check that django-storages is installed
|
def _setting(name, default=None):
|
||||||
try:
|
if name in STORAGE_CONFIG:
|
||||||
import storages
|
return STORAGE_CONFIG[name]
|
||||||
except ImportError:
|
return globals().get(name, default)
|
||||||
raise ImproperlyConfigured(
|
|
||||||
"S3 storage has been configured, but django-storages is not installed."
|
|
||||||
)
|
|
||||||
|
|
||||||
DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
|
storages.utils.setting = _setting
|
||||||
AWS_ACCESS_KEY_ID = MEDIA_STORAGE['ACCESS_KEY_ID']
|
|
||||||
AWS_SECRET_ACCESS_KEY = MEDIA_STORAGE['SECRET_ACCESS_KEY']
|
|
||||||
AWS_STORAGE_BUCKET_NAME = MEDIA_STORAGE['BUCKET_NAME']
|
|
||||||
AWS_S3_REGION_NAME = MEDIA_STORAGE.get('REGION_NAME', None)
|
|
||||||
AWS_S3_ENDPOINT_URL = MEDIA_STORAGE.get('ENDPOINT_URL', None)
|
|
||||||
AWS_AUTO_CREATE_BUCKET = MEDIA_STORAGE.get('AUTO_CREATE_BUCKET', False)
|
|
||||||
AWS_BUCKET_ACL = MEDIA_STORAGE.get('BUCKET_ACL', 'public-read')
|
|
||||||
AWS_DEFAULT_ACL = MEDIA_STORAGE.get('DEFAULT_ACL', 'public-read')
|
|
||||||
AWS_S3_OBJECT_PARAMETERS = MEDIA_STORAGE.get('OBJECT_PARAMETERS', {
|
|
||||||
'CacheControl': 'max-age=86400',
|
|
||||||
})
|
|
||||||
AWS_QUERYSTRING_AUTH = MEDIA_STORAGE.get('QUERYSTRING_AUTH', True)
|
|
||||||
AWS_QUERYSTRING_EXPIRE = MEDIA_STORAGE.get('QUERYSTRING_EXPIRE', 3600)
|
|
||||||
else:
|
|
||||||
raise ImproperlyConfigured(
|
|
||||||
"Unknown storage back-end '{}'".format(MEDIA_STORAGE['BACKEND'])
|
|
||||||
)
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Redis
|
# Redis
|
||||||
|
Reference in New Issue
Block a user