pull/1727/head
Piero Toffanin 2025-08-16 16:52:18 -04:00
rodzic c350576c68
commit d3e9b627fa
5 zmienionych plików z 107 dodań i 12 usunięć

Wyświetl plik

@ -17,6 +17,7 @@ from app.models import PluginDatum
from app.models import Preset
from app.models import Plugin
from app.models import Profile
from app.models import Redirect
from app.plugins import get_plugin_by_name, enable_plugin, disable_plugin, delete_plugin, valid_plugin, \
get_plugins_persistent_path, clear_plugins_cache, init_plugins
from .models import Project, Task, Setting, Theme
@ -96,6 +97,9 @@ class ThemeAdmin(admin.ModelAdmin):
admin.site.register(Theme, ThemeAdmin)
admin.site.register(PluginDatum, admin.ModelAdmin)
if settings.CLUSTER_ID is not None:
admin.site.register(Redirect, admin.ModelAdmin)
class PluginAdmin(admin.ModelAdmin):
list_display = ("name", "description", "version", "author", "enabled", "plugin_actions")

Wyświetl plik

@ -4,7 +4,7 @@ import math
import shutil
from django.core.management.base import BaseCommand
from django.core.management import call_command
from app.models import Project, Task, Preset, PluginDatum
from app.models import Project, Task, Preset, PluginDatum, Redirect
from webodm import settings
from django.db import connection
from django.contrib.auth.models import User
@ -330,26 +330,58 @@ def importexport_user(action, username, dry_run=False, cluster_export_dir=None,
# Cleanup
remove_dir(user_import_dir)
def redirect(username, to_cluster, dry_run=False):
if settings.CLUSTER_ID == to_cluster:
die("Cannot redirect to itself (this server's cluster ID is %s)" % to_cluster)
try:
user = User.objects.get(username=username)
except User.DoesNotExist:
die("User does not exist")
print("Setting up redirects for: %s" % user.username)
user_projects = Project.objects.filter(owner=user).order_by('created_at')
user_tasks = Task.objects.filter(project__owner=user).order_by('created_at')
print("Target cluster: %s" % to_cluster)
print("Projects: %s" % len(user_projects))
print("Tasks: %s" % len(user_tasks))
try:
count = 0
with transaction.atomic():
for p in user_projects:
Redirect.objects.create(project_id=p.id, project_public_id=p.public_id, cluster_id=to_cluster)
count += 1
for p in user_tasks:
Redirect.objects.create(task_id=p.id, cluster_id=to_cluster)
count += 1
print("Setup %s redirects" % count)
if dry_run:
raise DryRunException()
except DryRunException:
print("Dry run, rolling back")
class Command(BaseCommand):
requires_system_checks = []
def add_arguments(self, parser):
parser.add_argument("action", type=str, choices=['stagger', 'getref', 'export', 'import'])
parser.add_argument("action", type=str, choices=['stagger', 'getref', 'export', 'import', 'redirect', 'delete'])
parser.add_argument("--refs", required=False, help="JSON array of reference dictionaries")
parser.add_argument("--id-buffer", required=False, default=1000, help="ID increment buffer when assigning next seq IDs")
parser.add_argument("--dry-run", required=False, action="store_true", help="Don't actually modify tables, just test")
parser.add_argument("--user", required=False, default=None, help="User ID to migrate")
parser.add_argument("--cluster-export-dir", required=False, default=None, help="Override default export cluster dir")
parser.add_argument("--merge", required=False, action="store_true", help="Try to merge imported results for a user if the user already exist")
parser.add_argument("--to-cluster", required=False, default=-1, help="Cluster ID to redirect to")
super(Command, self).add_arguments(parser)
def handle(self, **options):
if settings.CLUSTER_ID is None:
print("CLUSTER_ID is not set")
exit(1)
die("CLUSTER_ID is not set")
dry_run = options.get('dry_run', False)
action = options.get('action')
@ -359,11 +391,9 @@ class Command(BaseCommand):
id_buffer = int(options.get('id_buffer'))
if not isinstance(refs, list):
print("Invalid refs, must be an array")
exit(1)
die("Invalid refs, must be an array")
if len(refs) <= 1:
print("Invalid refs, must have 2 or more items")
exit(1)
die("Invalid refs, must have 2 or more items")
max_project_id = max([r['next_project_id'] for r in refs])
start_project_id = max_project_id + id_buffer
@ -402,10 +432,18 @@ class Command(BaseCommand):
elif action == 'export' or action == 'import':
user = options.get('user')
if user is None:
print("--user <username> is required")
exit(1)
die("--user <username> is required")
importexport_user(action, user, dry_run=dry_run, cluster_export_dir=options.get('cluster_export_dir'), merge=options.get('merge'))
elif action == 'redirect':
user = options.get('user')
if user is None:
die("--user <username> is required")
to_cluster = options.get('to_cluster')
if to_cluster is None or to_cluster == -1:
die("--to-cluster <id> is required")
to_cluster = int(to_cluster)
redirect(user, to_cluster, dry_run=dry_run)
else:
print("Invalid action %s" % options.get('action'))

Wyświetl plik

@ -0,0 +1,27 @@
# Generated by Django 2.2.27 on 2025-08-16 20:28
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('app', '0044_task_console_link'),
]
operations = [
migrations.CreateModel(
name='Redirect',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('project_id', models.IntegerField(blank=True, db_index=True, default=None, help_text='Project Id', null=True, unique=True, verbose_name='Project Id')),
('project_public_id', models.UUIDField(blank=True, db_index=True, default=None, help_text='Public identifier of the project', null=True, unique=True, verbose_name='Public Id')),
('task_id', models.UUIDField(blank=True, db_index=True, default=None, help_text='Task Id', null=True, unique=True, verbose_name='Task Id')),
('cluster_id', models.IntegerField(help_text='Cluster Id to redirect to', verbose_name='Cluster Id')),
],
options={
'verbose_name': 'Redirect',
'verbose_name_plural': 'Redirects',
},
),
]

Wyświetl plik

@ -6,6 +6,7 @@ from .setting import Setting
from .plugin_datum import PluginDatum
from .plugin import Plugin
from .profile import Profile
from .redirect import Redirect
# deprecated
def image_directory_path(image_upload, filename):

Wyświetl plik

@ -0,0 +1,25 @@
from django.conf import settings
from django.db import models
from django.utils.translation import gettext_lazy as _
class Redirect(models.Model):
project_id = models.IntegerField(db_index=True, default=None, unique=True, blank=True, null=True, help_text=_("Project Id"), verbose_name=_("Project Id"))
project_public_id = models.UUIDField(db_index=True, default=None, unique=True, blank=True, null=True, help_text=_("Public identifier of the project"), verbose_name=_("Public Id"))
task_id = models.UUIDField(db_index=True, default=None, unique=True, blank=True, null=True, help_text=_("Task Id"), verbose_name=_("Task Id"))
cluster_id = models.IntegerField(blank=False, null=False, help_text=_("Cluster Id to redirect to"), verbose_name=_("Cluster Id"))
def __str__(self):
parts = []
if self.project_id is not None:
parts.append("P:%s" % self.project_id)
if self.project_public_id is not None:
parts.append("PP:%s" % self.project_public_id)
if self.task_id is not None:
parts.append("T:%s" % self.task_id)
return "|".join(parts) + " --> %s" % self.cluster_id
class Meta:
verbose_name = _("Redirect")
verbose_name_plural = _("Redirects")