hobo/hobo/multitenant/management/commands/create_tenant.py

89 lines
3.9 KiB
Python

import os
import sys
from django.core.management.base import BaseCommand, CommandError
from django.db import connection, transaction
from hobo.multitenant.middleware import TenantMiddleware, get_tenant_model
class Command(BaseCommand):
help = 'Create tenant(s) by hostname(s)'
def add_arguments(self, parser):
parser.add_argument('hostnames', metavar='HOSTNAME', nargs='+')
parser.add_argument('--legacy-hostname', dest='legacy_hostname')
def handle(self, hostnames, legacy_hostname, **options):
verbosity = int(options.get('verbosity'))
if not hostnames:
raise CommandError('you must give at least one tenant hostname')
if '-' in hostnames: # get additional list of hostnames from stdin
hostnames = list(hostnames)
hostnames.remove('-')
hostnames.extend([x.strip() for x in sys.stdin.readlines()])
if legacy_hostname and len(hostnames) > 1:
raise CommandError('You must specify only hostname when using --legacy-hostname')
for hostname in hostnames:
try:
tenant_base = TenantMiddleware.base()
except AttributeError:
raise CommandError('you must configure TENANT_BASE in your settings')
if not tenant_base:
raise CommandError('you must set a value to TENANT_BASE in your settings')
tenant_dir = os.path.join(tenant_base, hostname)
if os.path.exists(tenant_dir):
raise CommandError('tenant already exists')
tenant_dir_tmp = os.path.join(tenant_base, hostname + '__CREATION_IN_PROGRESS.invalid')
if legacy_hostname:
legacy_tenant_dir = os.path.join(tenant_base, legacy_hostname)
if not os.path.exists(legacy_tenant_dir):
raise CommandError('legacy tenant does not exists')
try:
os.rename(legacy_tenant_dir, tenant_dir_tmp)
except OSError as e:
raise CommandError('cannot change legacy tenant (%s)' % str(e))
else:
try:
os.mkdir(tenant_dir_tmp, 0o755)
except OSError as e:
raise CommandError('cannot start tenant creation (%s)' % str(e))
# tenant creation in database
try:
connection.set_schema_to_public()
schema = TenantMiddleware.hostname2schema(hostname)
legacy_schema = None
if legacy_hostname:
legacy_schema = TenantMiddleware.hostname2schema(legacy_hostname)
tenant = get_tenant_model()(schema_name=schema, domain_url=hostname)
if verbosity >= 1:
msg = self.style.NOTICE('=== Creating schema ') + self.style.SQL_TABLE(tenant.schema_name)
if legacy_schema:
msg = (
self.style.NOTICE('=== Renamin schema ')
+ self.style.SQL_TABLE(legacy_schema)
+ ' to '
+ self.style.SQL_TABLE(tenant.schema_name)
)
print()
print(msg)
with transaction.atomic():
tenant.create_schema(check_if_exists=True, legacy_schema_name=legacy_schema)
except Exception as e:
if legacy_hostname:
os.rename(tenant_dir_tmp, legacy_tenant_dir)
else:
os.rmdir(tenant_dir_tmp)
raise CommandError('tenant creation failed (%s)' % str(e))
if not legacy_hostname:
for folder in ('media', 'static', 'templates'):
path = os.path.join(tenant_dir_tmp, folder)
os.mkdir(path, 0o755)
# activate the tenant by creating its directory
os.rename(tenant_dir_tmp, tenant_dir)