perf: add applets deployment

pull/9075/head
Eric 2022-11-14 18:48:21 +08:00
parent 8e1312e8ce
commit d554e92d02
8 changed files with 278 additions and 181 deletions

View File

@ -2,16 +2,15 @@ from rest_framework import viewsets
from rest_framework.decorators import action from rest_framework.decorators import action
from rest_framework.response import Response from rest_framework.response import Response
from common.permissions import IsServiceAccount
from common.drf.api import JMSModelViewSet from common.drf.api import JMSModelViewSet
from common.permissions import IsServiceAccount
from orgs.utils import tmp_to_builtin_org from orgs.utils import tmp_to_builtin_org
from terminal.models import AppletHost, AppletHostDeployment
from terminal.serializers import ( from terminal.serializers import (
AppletHostSerializer, AppletHostDeploymentSerializer, AppletHostSerializer, AppletHostDeploymentSerializer,
AppletHostStartupSerializer AppletHostStartupSerializer, AppletHostDeployAppletSerializer
) )
from terminal.models import AppletHost, AppletHostDeployment from terminal.tasks import run_applet_host_deployment, run_applet_host_deployment_install_applet
from terminal.tasks import run_applet_host_deployment
__all__ = ['AppletHostViewSet', 'AppletHostDeploymentViewSet'] __all__ = ['AppletHostViewSet', 'AppletHostDeploymentViewSet']
@ -41,6 +40,9 @@ class AppletHostViewSet(JMSModelViewSet):
class AppletHostDeploymentViewSet(viewsets.ModelViewSet): class AppletHostDeploymentViewSet(viewsets.ModelViewSet):
serializer_class = AppletHostDeploymentSerializer serializer_class = AppletHostDeploymentSerializer
queryset = AppletHostDeployment.objects.all() queryset = AppletHostDeployment.objects.all()
rbac_perms = (
('applets', 'terminal.view_AppletHostDeployment'),
)
def create(self, request, *args, **kwargs): def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data) serializer = self.get_serializer(data=request.data)
@ -49,3 +51,11 @@ class AppletHostDeploymentViewSet(viewsets.ModelViewSet):
task = run_applet_host_deployment.delay(instance.id) task = run_applet_host_deployment.delay(instance.id)
return Response({'task': str(task.id)}, status=201) return Response({'task': str(task.id)}, status=201)
@action(methods=['post'], detail=False, serializer_class=AppletHostDeployAppletSerializer)
def applets(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
applet_id = serializer.validated_data.get('applet_id')
instance = serializer.save()
task = run_applet_host_deployment_install_applet.delay(instance.id, applet_id)
return Response({'task': str(task.id)}, status=201)

View File

@ -1,22 +1,23 @@
import os
import datetime import datetime
import shutil import os
import yaml import yaml
from django.utils import timezone
from django.conf import settings from django.conf import settings
from django.utils import timezone
from common.utils import get_logger
from common.db.utils import safe_db_connection from common.db.utils import safe_db_connection
from common.utils import get_logger
from ops.ansible import PlaybookRunner, JMSInventory from ops.ansible import PlaybookRunner, JMSInventory
from terminal.models import Applet, AppletHostDeployment
logger = get_logger(__name__) logger = get_logger(__name__)
CURRENT_DIR = os.path.dirname(os.path.abspath(__file__)) CURRENT_DIR = os.path.dirname(os.path.abspath(__file__))
class DeployAppletHostManager: class DeployAppletHostManager:
def __init__(self, deployment): def __init__(self, deployment: AppletHostDeployment, applet: Applet = None):
self.deployment = deployment self.deployment = deployment
self.applet = applet
self.run_dir = self.get_run_dir() self.run_dir = self.get_run_dir()
@staticmethod @staticmethod
@ -25,29 +26,56 @@ class DeployAppletHostManager:
now = datetime.datetime.now().strftime("%Y%m%d%H%M%S") now = datetime.datetime.now().strftime("%Y%m%d%H%M%S")
return os.path.join(base, now) return os.path.join(base, now)
def generate_playbook(self): def run(self, **kwargs):
playbook_src = os.path.join(CURRENT_DIR, "playbook.yml") self._run(self._run_initial_deploy, **kwargs)
base_site_url = settings.BASE_SITE_URL
def install_applet(self, **kwargs):
self._run(self._run_install_applet, **kwargs)
def _run_initial_deploy(self, **kwargs):
playbook = self.generate_initial_playbook
return self._run_playbook(playbook, **kwargs)
def _run_install_applet(self, **kwargs):
if self.applet:
generate_playbook = self.generate_install_applet_playbook
else:
generate_playbook = self.generate_install_all_playbook
return self._run_playbook(generate_playbook, **kwargs)
def generate_initial_playbook(self):
site_url = settings.SITE_URL
bootstrap_token = settings.BOOTSTRAP_TOKEN bootstrap_token = settings.BOOTSTRAP_TOKEN
host_id = str(self.deployment.host.id) host_id = str(self.deployment.host.id)
if not base_site_url: if not site_url:
base_site_url = "http://localhost:8080" site_url = "http://localhost:8080"
with open(playbook_src) as f: options = self.deployment.host.deploy_options
plays = yaml.safe_load(f)
for play in plays:
play["vars"].update(self.deployment.host.deploy_options)
play["vars"]["DownloadHost"] = base_site_url + "/download"
play["vars"]["CORE_HOST"] = base_site_url
play["vars"]["BOOTSTRAP_TOKEN"] = bootstrap_token
play["vars"]["HOST_ID"] = host_id
play["vars"]["HOST_NAME"] = self.deployment.host.name
playbook_dir = os.path.join(self.run_dir, "playbook") def handler(plays):
playbook_dst = os.path.join(playbook_dir, "main.yml") for play in plays:
os.makedirs(playbook_dir, exist_ok=True) play["vars"].update(options)
with open(playbook_dst, "w") as f: play["vars"]["DownloadHost"] = site_url + "/download"
yaml.safe_dump(plays, f) play["vars"]["CORE_HOST"] = site_url
return playbook_dst play["vars"]["BOOTSTRAP_TOKEN"] = bootstrap_token
play["vars"]["HOST_ID"] = host_id
play["vars"]["HOST_NAME"] = self.deployment.host.name
return self._generate_playbook("playbook.yml", handler)
def generate_install_all_playbook(self):
return self._generate_playbook("install_all.yml")
def generate_install_applet_playbook(self):
applet_name = self.applet.name
options = self.deployment.host.deploy_options
def handler(plays):
for play in plays:
play["vars"].update(options)
play["vars"]["applet_name"] = applet_name
return plays
return self._generate_playbook("install_applet.yml", handler)
def generate_inventory(self): def generate_inventory(self):
inventory = JMSInventory( inventory = JMSInventory(
@ -58,18 +86,31 @@ class DeployAppletHostManager:
inventory.write_to_file(inventory_path) inventory.write_to_file(inventory_path)
return inventory_path return inventory_path
def _run(self, **kwargs): def _generate_playbook(self, playbook_template_name, plays_handler: callable = None):
playbook_src = os.path.join(CURRENT_DIR, playbook_template_name)
with open(playbook_src) as f:
plays = yaml.safe_load(f)
if plays_handler:
plays = plays_handler(plays)
playbook_dir = os.path.join(self.run_dir, "playbook")
playbook_dst = os.path.join(playbook_dir, "main.yml")
os.makedirs(playbook_dir, exist_ok=True)
with open(playbook_dst, "w") as f:
yaml.safe_dump(plays, f)
return playbook_dst
def _run_playbook(self, generate_playbook: callable, **kwargs):
inventory = self.generate_inventory() inventory = self.generate_inventory()
playbook = self.generate_playbook() playbook = generate_playbook()
runner = PlaybookRunner( runner = PlaybookRunner(
inventory=inventory, playbook=playbook, project_dir=self.run_dir inventory=inventory, playbook=playbook, project_dir=self.run_dir
) )
return runner.run(**kwargs) return runner.run(**kwargs)
def run(self, **kwargs): def _run(self, cb_func: callable, **kwargs):
try: try:
self.deployment.date_start = timezone.now() self.deployment.date_start = timezone.now()
cb = self._run(**kwargs) cb = cb_func(**kwargs)
self.deployment.status = cb.status self.deployment.status = cb.status
except Exception as e: except Exception as e:
logger.error("Error: {}".format(e)) logger.error("Error: {}".format(e))

View File

@ -0,0 +1,8 @@
---
- hosts: all
tasks:
- name: Install all applets
ansible.windows.win_shell:
"tinkerd install all"

View File

@ -0,0 +1,11 @@
---
- hosts: all
vars:
applet_name: chrome
tasks:
- name: Install applet
ansible.windows.win_shell:
"tinkerd install --name {{ applet_name }}"
when: applet_name != 'all'

View File

@ -3,7 +3,6 @@
- hosts: all - hosts: all
vars: vars:
DownloadHost: https://demo.jumpserver.org/download DownloadHost: https://demo.jumpserver.org/download
Initial: 0
HOST_NAME: test HOST_NAME: test
HOST_ID: 00000000-0000-0000-0000-000000000000 HOST_ID: 00000000-0000-0000-0000-000000000000
CORE_HOST: https://demo.jumpserver.org CORE_HOST: https://demo.jumpserver.org
@ -17,166 +16,166 @@
TinkerInstaller: Tinker_Installer_v0.0.1.exe TinkerInstaller: Tinker_Installer_v0.0.1.exe
tasks: tasks:
- name: Install RDS-Licensing (RDS) - name: Install RDS-Licensing (RDS)
ansible.windows.win_feature: ansible.windows.win_feature:
name: RDS-Licensing name: RDS-Licensing
state: present state: present
include_management_tools: yes include_management_tools: yes
when: RDS_Licensing when: RDS_Licensing
- name: Install RDS-RD-Server (RDS) - name: Install RDS-RD-Server (RDS)
ansible.windows.win_feature: ansible.windows.win_feature:
name: RDS-RD-Server name: RDS-RD-Server
state: present state: present
include_management_tools: yes include_management_tools: yes
register: rds_install register: rds_install
- name: Download JumpServer Tinker installer (jumpserver) - name: Download JumpServer Tinker installer (jumpserver)
ansible.windows.win_get_url: ansible.windows.win_get_url:
url: "{{ DownloadHost }}/{{ TinkerInstaller }}" url: "{{ DownloadHost }}/{{ TinkerInstaller }}"
dest: "{{ ansible_env.TEMP }}\\{{ TinkerInstaller }}" dest: "{{ ansible_env.TEMP }}\\{{ TinkerInstaller }}"
- name: Install JumpServer Tinker (jumpserver) - name: Install JumpServer Tinker (jumpserver)
ansible.windows.win_package: ansible.windows.win_package:
path: "{{ ansible_env.TEMP }}\\{{ TinkerInstaller }}" path: "{{ ansible_env.TEMP }}\\{{ TinkerInstaller }}"
arguments: arguments:
- /VERYSILENT - /VERYSILENT
- /SUPPRESSMSGBOXES - /SUPPRESSMSGBOXES
- /NORESTART - /NORESTART
state: present state: present
- name: Set remote-server on the global system path (remote-server) - name: Set remote-server on the global system path (remote-server)
ansible.windows.win_path: ansible.windows.win_path:
elements: elements:
- '%USERPROFILE%\AppData\Local\Programs\Tinker\' - '%USERPROFILE%\AppData\Local\Programs\Tinker\'
scope: user scope: user
- name: Download python-3.10.8 - name: Download python-3.10.8
ansible.windows.win_get_url: ansible.windows.win_get_url:
url: "{{ DownloadHost }}/python-3.10.8-amd64.exe" url: "{{ DownloadHost }}/python-3.10.8-amd64.exe"
dest: "{{ ansible_env.TEMP }}\\python-3.10.8-amd64.exe" dest: "{{ ansible_env.TEMP }}\\python-3.10.8-amd64.exe"
- name: Install the python-3.10.8 - name: Install the python-3.10.8
ansible.windows.win_package: ansible.windows.win_package:
path: "{{ ansible_env.TEMP }}\\python-3.10.8-amd64.exe" path: "{{ ansible_env.TEMP }}\\python-3.10.8-amd64.exe"
product_id: '{371d0d73-d418-4ffe-b280-58c3e7987525}' product_id: '{371d0d73-d418-4ffe-b280-58c3e7987525}'
arguments: arguments:
- /quiet - /quiet
- InstallAllUsers=1 - InstallAllUsers=1
- PrependPath=1 - PrependPath=1
- Include_test=0 - Include_test=0
- Include_launcher=0 - Include_launcher=0
state: present state: present
register: win_install_python register: win_install_python
- name: Reboot if installing requires it - name: Reboot if installing requires it
ansible.windows.win_reboot: ansible.windows.win_reboot:
post_reboot_delay: 10 post_reboot_delay: 10
test_command: whoami test_command: whoami
when: rds_install.reboot_required or win_install_python.reboot_required when: rds_install.reboot_required or win_install_python.reboot_required
- name: Set RDS LicenseServer (regedit) - name: Set RDS LicenseServer (regedit)
ansible.windows.win_regedit: ansible.windows.win_regedit:
path: HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services path: HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services
name: LicenseServers name: LicenseServers
data: "{{ RDS_LicenseServer }}" data: "{{ RDS_LicenseServer }}"
type: string type: string
- name: Set RDS LicensingMode (regedit) - name: Set RDS LicensingMode (regedit)
ansible.windows.win_regedit: ansible.windows.win_regedit:
path: HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services path: HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services
name: LicensingMode name: LicensingMode
data: "{{ RDS_LicensingMode }}" data: "{{ RDS_LicensingMode }}"
type: dword type: dword
- name: Set RDS fSingleSessionPerUser (regedit) - name: Set RDS fSingleSessionPerUser (regedit)
ansible.windows.win_regedit: ansible.windows.win_regedit:
path: HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services path: HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services
name: fSingleSessionPerUser name: fSingleSessionPerUser
data: "{{ RDS_fSingleSessionPerUser }}" data: "{{ RDS_fSingleSessionPerUser }}"
type: dword type: dword
- name: Set RDS MaxDisconnectionTime (regedit) - name: Set RDS MaxDisconnectionTime (regedit)
ansible.windows.win_regedit: ansible.windows.win_regedit:
path: HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services path: HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services
name: MaxDisconnectionTime name: MaxDisconnectionTime
data: "{{ RDS_MaxDisconnectionTime }}" data: "{{ RDS_MaxDisconnectionTime }}"
type: dword type: dword
when: RDS_MaxDisconnectionTime >= 60000 when: RDS_MaxDisconnectionTime >= 60000
- name: Set RDS RemoteAppLogoffTimeLimit (regedit) - name: Set RDS RemoteAppLogoffTimeLimit (regedit)
ansible.windows.win_regedit: ansible.windows.win_regedit:
path: HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services path: HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services
name: RemoteAppLogoffTimeLimit name: RemoteAppLogoffTimeLimit
data: "{{ RDS_RemoteAppLogoffTimeLimit }}" data: "{{ RDS_RemoteAppLogoffTimeLimit }}"
type: dword type: dword
- name: Download pip packages - name: Download pip packages
ansible.windows.win_get_url: ansible.windows.win_get_url:
url: "{{ DownloadHost }}/pip_packages_v0.0.1.zip" url: "{{ DownloadHost }}/pip_packages_v0.0.1.zip"
dest: "{{ ansible_env.TEMP }}\\pip_packages_v0.0.1.zip" dest: "{{ ansible_env.TEMP }}\\pip_packages_v0.0.1.zip"
- name: Unzip pip_packages - name: Unzip pip_packages
community.windows.win_unzip: community.windows.win_unzip:
src: "{{ ansible_env.TEMP }}\\pip_packages_v0.0.1.zip" src: "{{ ansible_env.TEMP }}\\pip_packages_v0.0.1.zip"
dest: "{{ ansible_env.TEMP }}" dest: "{{ ansible_env.TEMP }}"
- name: Install python requirements offline - name: Install python requirements offline
ansible.windows.win_shell: > ansible.windows.win_shell: >
pip install -r '{{ ansible_env.TEMP }}\pip_packages_v0.0.1\requirements.txt' pip install -r '{{ ansible_env.TEMP }}\pip_packages_v0.0.1\requirements.txt'
--no-index --find-links='{{ ansible_env.TEMP }}\pip_packages_v0.0.1' --no-index --find-links='{{ ansible_env.TEMP }}\pip_packages_v0.0.1'
- name: Download chromedriver (chrome) - name: Download chromedriver (chrome)
ansible.windows.win_get_url: ansible.windows.win_get_url:
url: "{{ DownloadHost }}/chromedriver_win32.107.zip" url: "{{ DownloadHost }}/chromedriver_win32.107.zip"
dest: "{{ ansible_env.TEMP }}\\chromedriver_win32.107.zip" dest: "{{ ansible_env.TEMP }}\\chromedriver_win32.107.zip"
- name: Unzip chromedriver (chrome) - name: Unzip chromedriver (chrome)
community.windows.win_unzip: community.windows.win_unzip:
src: "{{ ansible_env.TEMP }}\\chromedriver_win32.107.zip" src: "{{ ansible_env.TEMP }}\\chromedriver_win32.107.zip"
dest: C:\Program Files\JumpServer\drivers dest: C:\Program Files\JumpServer\drivers
- name: Set chromedriver on the global system path (chrome) - name: Set chromedriver on the global system path (chrome)
ansible.windows.win_path: ansible.windows.win_path:
elements: elements:
- 'C:\Program Files\JumpServer\drivers' - 'C:\Program Files\JumpServer\drivers'
- name: Download chrome msi package (chrome) - name: Download chrome msi package (chrome)
ansible.windows.win_get_url: ansible.windows.win_get_url:
url: "{{ DownloadHost }}/googlechromestandaloneenterprise64.msi" url: "{{ DownloadHost }}/googlechromestandaloneenterprise64.msi"
dest: "{{ ansible_env.TEMP }}\\googlechromestandaloneenterprise64.msi" dest: "{{ ansible_env.TEMP }}\\googlechromestandaloneenterprise64.msi"
- name: Install chrome (chrome) - name: Install chrome (chrome)
ansible.windows.win_package: ansible.windows.win_package:
path: "{{ ansible_env.TEMP }}\\googlechromestandaloneenterprise64.msi" path: "{{ ansible_env.TEMP }}\\googlechromestandaloneenterprise64.msi"
state: present state: present
arguments: arguments:
- /quiet - /quiet
- name: Generate tinkerd component config - name: Generate tinkerd component config
ansible.windows.win_shell: ansible.windows.win_shell:
"tinkerd config --hostname {{ HOST_NAME }} --core_host {{ CORE_HOST }} "tinkerd config --hostname {{ HOST_NAME }} --core_host {{ CORE_HOST }}
--token {{ BOOTSTRAP_TOKEN }} --host_id {{ HOST_ID }}" --token {{ BOOTSTRAP_TOKEN }} --host_id {{ HOST_ID }}"
- name: Install tinkerd service - name: Install tinkerd service
ansible.windows.win_shell: ansible.windows.win_shell:
"tinkerd service install" "tinkerd service install"
- name: Start tinkerd service - name: Start tinkerd service
ansible.windows.win_shell: ansible.windows.win_shell:
"tinkerd service start" "tinkerd service start"
- name: Wait Tinker api health - name: Wait Tinker api health
ansible.windows.win_uri: ansible.windows.win_uri:
url: http://localhost:6068/api/health/ url: http://localhost:6068/api/health/
status_code: 200 status_code: 200
method: GET method: GET
register: _result register: _result
until: _result.status_code == 200 until: _result.status_code == 200
retries: 30 retries: 30
delay: 5 delay: 5
- name: Sync all remote applets - name: Sync all remote applets
ansible.windows.win_shell: ansible.windows.win_shell:
"tinkerd install all" "tinkerd install all"

View File

@ -110,3 +110,13 @@ class AppletHostDeployment(JMSBaseModel):
from ...automations.deploy_applet_host import DeployAppletHostManager from ...automations.deploy_applet_host import DeployAppletHostManager
manager = DeployAppletHostManager(self) manager = DeployAppletHostManager(self)
manager.run(**kwargs) manager.run(**kwargs)
def install_applet(self, applet_id, **kwargs):
from ...automations.deploy_applet_host import DeployAppletHostManager
from .applet import Applet
if applet_id:
applet = Applet.objects.get(id=applet_id)
else:
applet = None
manager = DeployAppletHostManager(self, applet=applet)
manager.install_applet(**kwargs)

View File

@ -1,19 +1,18 @@
from rest_framework import serializers
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from rest_framework import serializers
from common.validators import ProjectUniqueValidator
from common.drf.fields import ObjectRelatedField, LabeledChoiceField
from assets.models import Platform, Account from assets.models import Platform, Account
from assets.serializers import HostSerializer from assets.serializers import HostSerializer
from ..models import AppletHost, AppletHostDeployment, Applet from common.drf.fields import LabeledChoiceField
from common.validators import ProjectUniqueValidator
from .applet import AppletSerializer from .applet import AppletSerializer
from .. import const from .. import const
from ..models import AppletHost, AppletHostDeployment
__all__ = [ __all__ = [
'AppletHostSerializer', 'AppletHostDeploymentSerializer', 'AppletHostSerializer', 'AppletHostDeploymentSerializer',
'AppletHostAccountSerializer', 'AppletHostAppletReportSerializer', 'AppletHostAccountSerializer', 'AppletHostAppletReportSerializer',
'AppletHostStartupSerializer', 'AppletHostStartupSerializer', 'AppletHostDeployAppletSerializer'
] ]
@ -29,7 +28,8 @@ class DeployOptionsSerializer(serializers.Serializer):
RDS_Licensing = serializers.BooleanField(default=False, label=_("RDS Licensing")) RDS_Licensing = serializers.BooleanField(default=False, label=_("RDS Licensing"))
RDS_LicenseServer = serializers.CharField(default='127.0.0.1', label=_('RDS License Server'), max_length=1024) RDS_LicenseServer = serializers.CharField(default='127.0.0.1', label=_('RDS License Server'), max_length=1024)
RDS_LicensingMode = serializers.ChoiceField(choices=LICENSE_MODE_CHOICES, default=4, label=_('RDS Licensing Mode')) RDS_LicensingMode = serializers.ChoiceField(choices=LICENSE_MODE_CHOICES, default=4, label=_('RDS Licensing Mode'))
RDS_fSingleSessionPerUser = serializers.ChoiceField(choices=SESSION_PER_USER, default=1, label=_("RDS fSingleSessionPerUser")) RDS_fSingleSessionPerUser = serializers.ChoiceField(choices=SESSION_PER_USER, default=1,
label=_("RDS fSingleSessionPerUser"))
RDS_MaxDisconnectionTime = serializers.IntegerField(default=60000, label=_("RDS Max Disconnection Time")) RDS_MaxDisconnectionTime = serializers.IntegerField(default=60000, label=_("RDS Max Disconnection Time"))
RDS_RemoteAppLogoffTimeLimit = serializers.IntegerField(default=0, label=_("RDS Remote App Logoff Time Limit")) RDS_RemoteAppLogoffTimeLimit = serializers.IntegerField(default=0, label=_("RDS Remote App Logoff Time Limit"))
@ -94,6 +94,18 @@ class AppletHostDeploymentSerializer(serializers.ModelSerializer):
fields = fields_mini + ['comment'] + read_only_fields fields = fields_mini + ['comment'] + read_only_fields
class AppletHostDeployAppletSerializer(AppletHostDeploymentSerializer):
applet_id = serializers.UUIDField(write_only=True, allow_null=True, required=False)
class Meta(AppletHostDeploymentSerializer.Meta):
fields = AppletHostDeploymentSerializer.Meta.fields + ['applet_id']
def create(self, validated_data):
applet_id = validated_data.pop('applet_id', None)
deployment = super().create(validated_data)
return deployment
class AppletHostAccountSerializer(serializers.ModelSerializer): class AppletHostAccountSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = Account model = Account

View File

@ -1,26 +1,25 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
import datetime
import os import os
import subprocess import subprocess
import datetime
from celery import shared_task from celery import shared_task
from celery.utils.log import get_task_logger from celery.utils.log import get_task_logger
from django.utils import timezone
from django.core.files.storage import default_storage from django.core.files.storage import default_storage
from django.utils import timezone
from common.utils import get_log_keep_day from common.utils import get_log_keep_day
from ops.celery.decorator import ( from ops.celery.decorator import (
register_as_period_task, after_app_ready_start, register_as_period_task, after_app_ready_start,
after_app_shutdown_clean_periodic after_app_shutdown_clean_periodic
) )
from .models import (
Status, Session, Command, Task, AppletHost,
AppletHostDeployment
)
from orgs.utils import tmp_to_builtin_org from orgs.utils import tmp_to_builtin_org
from .backends import server_replay_storage from .backends import server_replay_storage
from .models import (
Status, Session, Command, Task, AppletHostDeployment
)
from .utils import find_session_replay_local from .utils import find_session_replay_local
CACHE_REFRESH_INTERVAL = 10 CACHE_REFRESH_INTERVAL = 10
@ -57,7 +56,7 @@ def clean_orphan_session():
@shared_task @shared_task
@register_as_period_task(interval=3600*24) @register_as_period_task(interval=3600 * 24)
@after_app_ready_start @after_app_ready_start
@after_app_shutdown_clean_periodic @after_app_shutdown_clean_periodic
def clean_expired_session_period(): def clean_expired_session_period():
@ -114,3 +113,10 @@ def run_applet_host_deployment(did):
with tmp_to_builtin_org(system=1): with tmp_to_builtin_org(system=1):
deployment = AppletHostDeployment.objects.get(id=did) deployment = AppletHostDeployment.objects.get(id=did)
deployment.start() deployment.start()
@shared_task
def run_applet_host_deployment_install_applet(did, applet_id):
with tmp_to_builtin_org(system=1):
deployment = AppletHostDeployment.objects.get(id=did)
deployment.install_applet(applet_id)