From e2f9855954fefc91c96611874c06fa7c2cb11297 Mon Sep 17 00:00:00 2001 From: Cayo Puigdefabregas Date: Thu, 11 Jul 2024 17:40:45 +0200 Subject: [PATCH] up snapshots from command line --- dashboard/templates/base.html | 2 +- ..._dhid_bk_remove_device_phid_bk_and_more.py | 46 +++++++ device/models.py | 8 +- dhub/settings.py | 2 + dhub/urls.py | 1 + snapshot/management/__init__.py | 0 snapshot/management/commands/__init__.py | 0 snapshot/management/commands/up_snapshots.py | 50 ++++++++ .../migrations/0002_alter_snapshot_uuid.py | 18 +++ .../0003_remove_snapshot_start_time.py | 17 +++ snapshot/models.py | 3 +- snapshot/parse.py | 116 +++++++++++++++++- snapshot/templates/snapshots.html | 40 ++++++ snapshot/urls.py | 20 ++- snapshot/views.py | 18 ++- 15 files changed, 324 insertions(+), 17 deletions(-) create mode 100644 device/migrations/0004_remove_device_dhid_bk_remove_device_phid_bk_and_more.py create mode 100644 snapshot/management/__init__.py create mode 100644 snapshot/management/commands/__init__.py create mode 100644 snapshot/management/commands/up_snapshots.py create mode 100644 snapshot/migrations/0002_alter_snapshot_uuid.py create mode 100644 snapshot/migrations/0003_remove_snapshot_start_time.py create mode 100644 snapshot/templates/snapshots.html diff --git a/dashboard/templates/base.html b/dashboard/templates/base.html index 359130a..8134c90 100644 --- a/dashboard/templates/base.html +++ b/dashboard/templates/base.html @@ -132,7 +132,7 @@ diff --git a/device/migrations/0004_remove_device_dhid_bk_remove_device_phid_bk_and_more.py b/device/migrations/0004_remove_device_dhid_bk_remove_device_phid_bk_and_more.py new file mode 100644 index 0000000..fefff1d --- /dev/null +++ b/device/migrations/0004_remove_device_dhid_bk_remove_device_phid_bk_and_more.py @@ -0,0 +1,46 @@ +# Generated by Django 5.0.6 on 2024-07-11 13:58 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("device", "0003_remove_component_type_remove_computer_type_and_more"), + ] + + operations = [ + migrations.RemoveField( + model_name="device", + name="dhid_bk", + ), + migrations.RemoveField( + model_name="device", + name="phid_bk", + ), + migrations.AddField( + model_name="computer", + name="erasure_server", + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name="device", + name="reliable", + field=models.BooleanField(default=True), + ), + migrations.AlterField( + model_name="component", + name="computer", + field=models.ForeignKey( + null=True, + on_delete=django.db.models.deletion.CASCADE, + to="device.computer", + ), + ), + migrations.AlterField( + model_name="computer", + name="system_uuid", + field=models.UUIDField(blank=True, null=True), + ), + ] diff --git a/device/models.py b/device/models.py index 50d5f8c..3b87247 100644 --- a/device/models.py +++ b/device/models.py @@ -33,12 +33,11 @@ class Device(models.Model): production_date = models.DateTimeField(blank=True, null=True) variant = models.CharField(max_length=STR_SIZE, blank=True, null=True) devicehub_id = models.CharField(max_length=STR_SIZE, unique=True, blank=True, null=True) - dhid_bk = models.CharField(max_length=STR_SIZE, blank=True, null=True) - phid_bk = models.CharField(max_length=STR_SIZE, blank=True, null=True) family = models.CharField(max_length=STR_SIZE, blank=True, null=True) hid = models.CharField(max_length=STR_SIZE, blank=True, null=True) chid = models.CharField(max_length=STR_SIZE, blank=True, null=True) active = models.BooleanField(default=True) + reliable = models.BooleanField(default=True) owner = models.ForeignKey(User, on_delete=models.CASCADE) def has_physical_properties(self): @@ -80,13 +79,14 @@ class Computer(models.Model): max_length=STR_SM_SIZE, choices=Chassis ) - system_uuid = models.UUIDField() + system_uuid = models.UUIDField(blank=True, null=True) sku = models.CharField(max_length=STR_SM_SIZE, blank=True, null=True) + erasure_server = models.BooleanField(default=False) class Component(models.Model): device = models.OneToOneField(Device, models.CASCADE, primary_key=True) - computer = models.OneToOneField(Computer, models.CASCADE, null=True) + computer = models.ForeignKey(Computer, on_delete=models.CASCADE, null=True) class GraphicCard(models.Model): diff --git a/dhub/settings.py b/dhub/settings.py index 7feb8c6..0dc2788 100644 --- a/dhub/settings.py +++ b/dhub/settings.py @@ -168,3 +168,5 @@ LOGGING = { "level": "DEBUG", } } + +SNAPSHOT_PATH="/tmp/" diff --git a/dhub/urls.py b/dhub/urls.py index 6305b93..9c77ee8 100644 --- a/dhub/urls.py +++ b/dhub/urls.py @@ -21,6 +21,7 @@ urlpatterns = [ # path('api/', include('snapshot.urls')), path("", include("login.urls")), path("dashboard/", include("dashboard.urls")), + path("snapshot/", include("snapshot.urls")), path("device/", include("device.urls")), path("lot/", include("lot.urls")), ] diff --git a/snapshot/management/__init__.py b/snapshot/management/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/snapshot/management/commands/__init__.py b/snapshot/management/commands/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/snapshot/management/commands/up_snapshots.py b/snapshot/management/commands/up_snapshots.py new file mode 100644 index 0000000..f8cf0ce --- /dev/null +++ b/snapshot/management/commands/up_snapshots.py @@ -0,0 +1,50 @@ + +import os +import json + +from django.core.management.base import BaseCommand +from django.contrib.auth import get_user_model +from snapshot.parse import Build + + +User = get_user_model() + + +class Command(BaseCommand): + help = "Insert Snapshots" + snapshots = [] + files = [] + devices = [] + + def add_arguments(self, parser): + parser.add_argument('path', type=str, help='Path to snapshots') + parser.add_argument('email', type=str, help='Email of user') + + + def handle(self, *args, **kwargs): + path = kwargs['path'] + email = kwargs['email'] + self.user = User.objects.get(email=email) + + if os.path.isfile(path): + self.open(path) + + elif os.path.isdir(path): + self.read_directory(path) + + self.parsing() + + def read_directory(self, directory): + for filename in os.listdir(directory): + filepath = os.path.join(directory, filename) + if os.path.isfile(filepath): + self.open(filepath) + + def open(self, filepath): + with open(filepath, 'r') as file: + content = json.loads(file.read()) + self.snapshots.append(content) + + def parsing(self): + for s in self.snapshots: + self.devices.append(Build(s, self.user)) diff --git a/snapshot/migrations/0002_alter_snapshot_uuid.py b/snapshot/migrations/0002_alter_snapshot_uuid.py new file mode 100644 index 0000000..e833d88 --- /dev/null +++ b/snapshot/migrations/0002_alter_snapshot_uuid.py @@ -0,0 +1,18 @@ +# Generated by Django 5.0.6 on 2024-07-11 14:16 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("snapshot", "0001_initial"), + ] + + operations = [ + migrations.AlterField( + model_name="snapshot", + name="uuid", + field=models.UUIDField(unique=True), + ), + ] diff --git a/snapshot/migrations/0003_remove_snapshot_start_time.py b/snapshot/migrations/0003_remove_snapshot_start_time.py new file mode 100644 index 0000000..cedcccc --- /dev/null +++ b/snapshot/migrations/0003_remove_snapshot_start_time.py @@ -0,0 +1,17 @@ +# Generated by Django 5.0.6 on 2024-07-11 14:18 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ("snapshot", "0002_alter_snapshot_uuid"), + ] + + operations = [ + migrations.RemoveField( + model_name="snapshot", + name="start_time", + ), + ] diff --git a/snapshot/models.py b/snapshot/models.py index 252cb98..72919ee 100644 --- a/snapshot/models.py +++ b/snapshot/models.py @@ -18,13 +18,12 @@ class Snapshot(models.Model): created = models.DateTimeField(auto_now_add=True) software = models.CharField(max_length=STR_SM_SIZE, choices=SoftWare, default=SoftWare.WORKBENCH) - uuid = models.UUIDField() + uuid = models.UUIDField(unique=True) version = models.CharField(max_length=STR_SM_SIZE) sid = models.CharField(max_length=STR_SM_SIZE) settings_version = models.CharField(max_length=STR_SM_SIZE) is_server_erase = models.BooleanField(default=False) severity = models.SmallIntegerField(choices=Severity, default=Severity.Info) - start_time = models.DateTimeField() end_time = models.DateTimeField() owner = models.ForeignKey(User, on_delete=models.CASCADE) computer = models.ForeignKey(Computer, on_delete=models.CASCADE) diff --git a/snapshot/parse.py b/snapshot/parse.py index 403afc3..b09c5fa 100644 --- a/snapshot/parse.py +++ b/snapshot/parse.py @@ -1,9 +1,119 @@ -# from dmidecode import DMIParse +import os +import json +import shutil +import hashlib + +from datetime import datetime +from django.conf import settings +from device.models import Device, Computer +from snapshot.models import Snapshot -class Parse: - def __init__(self, snapshot_json): +HID = [ + "manufacturer", + "model", + "chassis", + "serialNumber", + "sku" +] + + +class Build: + def __init__(self, snapshot_json, user): self.json = snapshot_json + self.user = user + self.hid = None + self.result = False + + self.save_disk() + self.json_device = self.json["device"] + self.json_components = self.json["components"] + self.uuid = self.json["uuid"] + self.get_hid() + self.gen_computer() + self.gen_components() + self.gen_actions() + self.gen_snapshot() + + self.result = True + self.move_json() + + def save_disk(self): + snapshot_path = settings.SNAPSHOT_PATH + user = self.user.email + uuid = self.json.get("uuid", "") + now = datetime.now().strftime("%Y-%m-%d-%H-%M") + filename = f"{now}_{user}_{uuid}.json" + path_dir_base = os.path.join(snapshot_path, user) + path_upload = os.path.join(path_dir_base, 'upload') + path_name = os.path.join(path_upload, filename) + self.filename = path_name + self.path_dir_base = path_dir_base + + if not os.path.isdir(path_dir_base): + os.system(f'mkdir -p {path_upload}') + + with open(path_name, 'w') as file: + file.write(json.dumps(self.json)) + + def move_json(self): + if not self.result: + return + + shutil.copy(self.filename, self.path_dir_base) + os.remove(self.filename) + + def get_hid(self): + hid = "" + for f in HID: + hid += "-" + self.json_device[f] + self.hid = hid + + def gen_computer(self): + self.device = Device.objects.filter( + hid=self.hid, + active=True, + reliable=True, + owner=self.user + ).first() + + if self.device: + return + + chid = hashlib.sha3_256(self.hid.encode()).hexdigest() + self.device = Device.objects.create( + serial_number=self.json_device["serialNumber"], + manufacturer=self.json_device["manufacturer"], + version=self.json_device["version"], + model=self.json_device["model"], + type=self.json_device["type"], + hid=self.hid, + chid=chid, + owner=self.user + ) + + Computer.objects.create( + device=self.device, + sku=self.json_device["sku"], + chassis=self.json_device["chassis"] + ) + + def gen_snapshot(self): + self.snapshot = Snapshot.objects.create( + uuid = self.uuid, + version = self.json["version"], + computer = self.device.computer, + sid = self.json.get("sid", ""), + settings_version = self.json.get("settings_version", ""), + end_time = self.json.get("endTime"), + owner=self.user + ) + + def gen_components(self): + pass + + def gen_actions(self): + pass # class ParseSnapshot: diff --git a/snapshot/templates/snapshots.html b/snapshot/templates/snapshots.html new file mode 100644 index 0000000..c1fdb39 --- /dev/null +++ b/snapshot/templates/snapshots.html @@ -0,0 +1,40 @@ +{% extends "base.html" %} +{% load i18n %} + +{% block content %} +
+
+

{{ subtitle }}

+
+
+ +
+
+ {% csrf_token %} + + + + + + + {% for snap in snapshots %} + + + + + + + + {% endfor %} +
+ Title +
+ + + {{ snap.uuid }} {{ snap.sid }} {{ snap.version }} + + {{ snap.computer.device.manufacturer }} {{ snap.computer.device.model }} +
+
+
+{% endblock %} diff --git a/snapshot/urls.py b/snapshot/urls.py index 784f557..b3e00f9 100644 --- a/snapshot/urls.py +++ b/snapshot/urls.py @@ -1,10 +1,18 @@ -from django.urls import path, include -from rest_framework.routers import DefaultRouter -from snapshot.views import SnapshotViewSet +# from django.urls import path, include +# from rest_framework.routers import DefaultRouter +# from snapshot.views import SnapshotViewSet -router = DefaultRouter() -router.register(r'snapshots', SnapshotViewSet) +# router = DefaultRouter() +# router.register(r'snapshots', SnapshotViewSet) + +# urlpatterns = [ +# path('', include(router.urls)), +# ] +from django.urls import path +from snapshot import views + +app_name = 'snapshot' urlpatterns = [ - path('', include(router.urls)), + path("", views.ListSnapshotsView.as_view(), name="list"), ] diff --git a/snapshot/views.py b/snapshot/views.py index 0ce4c01..8202bc3 100644 --- a/snapshot/views.py +++ b/snapshot/views.py @@ -1,6 +1,9 @@ +from django.utils.translation import gettext_lazy as _ +from django.views.generic.base import TemplateView +from dashboard.mixins import DashboardView +from snapshot.models import Snapshot # from django.shortcuts import render # from rest_framework import viewsets -# from snapshot.models import Snapshot # from snapshot.serializers import SnapshotSerializer @@ -9,3 +12,16 @@ # serializer_class = SnapshotSerializer +class ListSnapshotsView(DashboardView, TemplateView): + template_name = "snapshots.html" + section = "snapshots" + title = _("Snapshots") + breadcrumb = "Snapshots" + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + snapshots = Snapshot.objects.filter(owner=self.request.user) + context.update({ + 'snapshots': snapshots, + }) + return context