perf: 修改合并引起的 migrations 依赖问题

pull/9158/head
ibuler 2022-12-05 16:07:14 +08:00
parent e91cbb9c97
commit 2168610ffe
24 changed files with 347 additions and 461 deletions

View File

@ -1,8 +1,8 @@
from rest_framework import serializers from rest_framework import serializers
from common.utils import get_object_or_none
from orgs.utils import tmp_to_root_org from orgs.utils import tmp_to_root_org
from common.utils import get_object_or_none, lazyproperty
from users.models import User from users.models import User
from assets.models import Asset, Account
__all__ = ['LoginAssetCheckSerializer'] __all__ = ['LoginAssetCheckSerializer']
@ -22,6 +22,7 @@ class LoginAssetCheckSerializer(serializers.Serializer):
return user_id return user_id
def validate_asset_id(self, asset_id): def validate_asset_id(self, asset_id):
from assets.models import Asset
self.asset = self.get_object(Asset, asset_id) self.asset = self.get_object(Asset, asset_id)
return asset_id return asset_id

View File

@ -0,0 +1,22 @@
# Generated by Django 3.2.12 on 2022-07-14 02:46
from django.db import migrations
def migrate_db_oracle_version_to_attrs(apps, schema_editor):
db_alias = schema_editor.connection.alias
model = apps.get_model("applications", "Application")
oracles = list(model.objects.using(db_alias).filter(type='oracle'))
for o in oracles:
o.attrs['version'] = '12c'
model.objects.using(db_alias).bulk_update(oracles, ['attrs'])
class Migration(migrations.Migration):
dependencies = [
('applications', '0021_auto_20220629_1826'),
]
operations = [
migrations.RunPython(migrate_db_oracle_version_to_attrs)
]

View File

@ -0,0 +1,47 @@
# Generated by Django 3.1.14 on 2022-07-15 07:56
import time
from django.db import migrations
def migrate_account_dirty_data(apps, schema_editor):
db_alias = schema_editor.connection.alias
account_model = apps.get_model('applications', 'Account')
count = 0
bulk_size = 1000
while True:
accounts = account_model.objects.using(db_alias) \
.filter(org_id='')[count:count + bulk_size]
if not accounts:
break
accounts = list(accounts)
start = time.time()
for i in accounts:
if i.app:
org_id = i.app.org_id
elif i.systemuser:
org_id = i.systemuser.org_id
else:
org_id = ''
if org_id:
i.org_id = org_id
account_model.objects.bulk_update(accounts, ['org_id', ])
print("Update account org is empty: {}-{} using: {:.2f}s".format(
count, count + len(accounts), time.time() - start
))
count += len(accounts)
class Migration(migrations.Migration):
dependencies = [
('applications', '0022_auto_20220714_1046'),
]
operations = [
migrations.RunPython(migrate_account_dirty_data),
]

View File

@ -1,23 +0,0 @@
# Generated by Django 3.2.14 on 2022-08-18 02:57
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('applications', '0023_auto_20220817_1716'),
]
operations = [
migrations.AlterField(
model_name='application',
name='category',
field=models.CharField(max_length=16, verbose_name='Category'),
),
migrations.AlterField(
model_name='application',
name='type',
field=models.CharField(max_length=16, verbose_name='Type'),
),
]

View File

@ -1,6 +1,6 @@
# Generated by Django 3.2.14 on 2022-08-17 05:46 # Generated by Django 3.2.14 on 2022-08-17 05:46
from django.db import migrations from django.db import migrations, models
def migrate_db_oracle_version_to_attrs(apps, schema_editor): def migrate_db_oracle_version_to_attrs(apps, schema_editor):
@ -14,7 +14,7 @@ def migrate_db_oracle_version_to_attrs(apps, schema_editor):
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [ dependencies = [
('applications', '0021_auto_20220629_1826'), ('applications', '0024_alter_application_type'),
] ]
operations = [ operations = [
@ -47,4 +47,14 @@ class Migration(migrations.Migration):
model_name='historicalaccount', model_name='historicalaccount',
name='systemuser', name='systemuser',
), ),
migrations.AlterField(
model_name='application',
name='category',
field=models.CharField(max_length=16, verbose_name='Category'),
),
migrations.AlterField(
model_name='application',
name='type',
field=models.CharField(max_length=16, verbose_name='Type'),
),
] ]

View File

@ -39,7 +39,7 @@ def migrate_account_dirty_data(apps, schema_editor):
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [ dependencies = [
('applications', '0022_auto_20220817_1346'), ('applications', '0025_auto_20220817_1346'),
('perms', '0031_auto_20220816_1600'), ('perms', '0031_auto_20220816_1600'),
('ops', '0022_auto_20220817_1346'), ('ops', '0022_auto_20220817_1346'),
('assets', '0105_auto_20220817_1544'), ('assets', '0105_auto_20220817_1544'),

View File

@ -1,106 +0,0 @@
# Generated by Django 3.1.14 on 2022-03-30 10:35
import uuid
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('assets', '0091_auto_20220629_1826'),
]
operations = [
migrations.AddField(
model_name='asset',
name='info',
field=models.JSONField(blank=True, default=dict, verbose_name='Info'),
),
migrations.RenameField(
model_name='asset',
old_name='hostname',
new_name='name',
),
migrations.AlterField(
model_name='asset',
name='name',
field=models.CharField(max_length=128, verbose_name='Name'),
),
migrations.AlterModelOptions(
name='asset',
options={'ordering': ['name'], 'permissions': [('refresh_assethardwareinfo', 'Can refresh asset hardware info'), ('test_assetconnectivity', 'Can test asset connectivity'), ('push_assetsystemuser', 'Can push system user to asset'), ('match_asset', 'Can match asset'), ('add_assettonode', 'Add asset to node'), ('move_assettonode', 'Move asset to node')], 'verbose_name': 'Asset'},
),
migrations.RenameField(
model_name='asset',
old_name='ip',
new_name='address',
),
migrations.AddField(
model_name='asset',
name='date_updated',
field=models.DateTimeField(auto_now=True, verbose_name='Date updated'),
),
migrations.AddField(
model_name='asset',
name='updated_by',
field=models.CharField(blank=True, max_length=32, null=True, verbose_name='Updated by'),
),
migrations.AlterField(
model_name='asset',
name='created_by',
field=models.CharField(blank=True, max_length=32, null=True, verbose_name='Created by'),
),
migrations.CreateModel(
name='Host',
fields=[
('asset_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='assets.asset')),
],
),
migrations.CreateModel(
name='Database',
fields=[
('asset_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='assets.asset')),
('db_name', models.CharField(blank=True, max_length=1024, verbose_name='Database')),
],
options={
'verbose_name': 'Database',
},
bases=('assets.asset',),
),
migrations.CreateModel(
name='Device',
fields=[
('asset_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='assets.asset')),
],
options={
'abstract': False,
},
bases=('assets.asset',),
),
migrations.CreateModel(
name='Cloud',
fields=[
('asset_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='assets.asset')),
],
options={
'abstract': False,
},
bases=('assets.asset',),
),
migrations.CreateModel(
name='Web',
fields=[
('asset_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='assets.asset')),
('autofill', models.CharField(choices=[('no', 'Disabled'), ('basic', 'Basic'), ('script', 'Script')], default='basic', max_length=16, verbose_name='Autofill')),
('password_selector', models.CharField(blank=True, default='', max_length=128, verbose_name='Password selector')),
('submit_selector', models.CharField(blank=True, default='', max_length=128, verbose_name='Submit selector')),
('username_selector', models.CharField(blank=True, default='', max_length=128, verbose_name='Username selector')),
('script', models.JSONField(blank=True, default=list, verbose_name='Script')),
],
options={
'abstract': False,
},
bases=('assets.asset',),
),
]

View File

@ -1,18 +0,0 @@
# Generated by Django 3.2.14 on 2022-11-04 07:06
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('assets', '0092_commandfilter_nodes'),
]
operations = [
migrations.AlterField(
model_name='systemuser',
name='protocol',
field=models.CharField(choices=[('ssh', 'SSH'), ('rdp', 'RDP'), ('telnet', 'Telnet'), ('vnc', 'VNC'), ('mysql', 'MySQL'), ('oracle', 'Oracle'), ('mariadb', 'MariaDB'), ('postgresql', 'PostgreSQL'), ('sqlserver', 'SQLServer'), ('redis', 'Redis'), ('mongodb', 'MongoDB'), ('clickhouse', 'ClickHouse'), ('k8s', 'K8S')], default='ssh', max_length=16, verbose_name='Protocol'),
),
]

View File

@ -1,6 +1,6 @@
# Generated by Django 3.1.14 on 2022-04-02 08:27 # Generated by Django 3.1.14 on 2022-04-02 08:27
from django.utils import timezone import django.db
from django.db import migrations, models from django.db import migrations, models
@ -13,7 +13,7 @@ def migrate_to_host(apps, schema_editor):
batch_size = 1000 batch_size = 1000
while True: while True:
assets = asset_model.objects.using(db_alias).all()[count:count+batch_size] assets = asset_model.objects.using(db_alias).all()[count:count + batch_size]
if not assets: if not assets:
break break
count += len(assets) count += len(assets)
@ -33,7 +33,7 @@ def migrate_hardware_info(apps, *args):
] ]
while True: while True:
assets = asset_model.objects.all()[count:count+batch_size] assets = asset_model.objects.all()[count:count + batch_size]
if not assets: if not assets:
break break
count += len(assets) count += len(assets)
@ -49,12 +49,121 @@ def migrate_hardware_info(apps, *args):
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [ dependencies = [
('assets', '0092_add_host'), ('assets', '0092_commandfilter_nodes'),
] ]
operations = [ operations = [
migrations.AddField(
model_name='asset',
name='info',
field=models.JSONField(blank=True, default=dict, verbose_name='Info'),
),
migrations.RenameField(
model_name='asset',
old_name='hostname',
new_name='name',
),
migrations.AlterField(
model_name='asset',
name='name',
field=models.CharField(max_length=128, verbose_name='Name'),
),
migrations.AlterModelOptions(
name='asset',
options={'ordering': ['name'],
'permissions': [('refresh_assethardwareinfo', 'Can refresh asset hardware info'),
('test_assetconnectivity', 'Can test asset connectivity'),
('push_assetsystemuser', 'Can push system user to asset'),
('match_asset', 'Can match asset'), ('add_assettonode', 'Add asset to node'),
('move_assettonode', 'Move asset to node')], 'verbose_name': 'Asset'},
),
migrations.RenameField(
model_name='asset',
old_name='ip',
new_name='address',
),
migrations.AddField(
model_name='asset',
name='date_updated',
field=models.DateTimeField(auto_now=True, verbose_name='Date updated'),
),
migrations.AddField(
model_name='asset',
name='updated_by',
field=models.CharField(blank=True, max_length=32, null=True, verbose_name='Updated by'),
),
migrations.AlterField(
model_name='asset',
name='created_by',
field=models.CharField(blank=True, max_length=32, null=True, verbose_name='Created by'),
),
migrations.CreateModel(
name='Host',
fields=[
('asset_ptr',
models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True,
primary_key=True, serialize=False, to='assets.asset')),
],
),
migrations.CreateModel(
name='Database',
fields=[
('asset_ptr',
models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True,
primary_key=True, serialize=False, to='assets.asset')),
('db_name', models.CharField(blank=True, max_length=1024, verbose_name='Database')),
],
options={
'verbose_name': 'Database',
},
bases=('assets.asset',),
),
migrations.CreateModel(
name='Device',
fields=[
('asset_ptr',
models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True,
primary_key=True, serialize=False, to='assets.asset')),
],
options={
'abstract': False,
},
bases=('assets.asset',),
),
migrations.CreateModel(
name='Cloud',
fields=[
('asset_ptr',
models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True,
primary_key=True, serialize=False, to='assets.asset')),
],
options={
'abstract': False,
},
bases=('assets.asset',),
),
migrations.CreateModel(
name='Web',
fields=[
('asset_ptr',
models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True,
primary_key=True, serialize=False, to='assets.asset')),
('autofill', models.CharField(choices=[('no', 'Disabled'), ('basic', 'Basic'), ('script', 'Script')],
default='basic', max_length=16, verbose_name='Autofill')),
('password_selector',
models.CharField(blank=True, default='', max_length=128, verbose_name='Password selector')),
('submit_selector',
models.CharField(blank=True, default='', max_length=128, verbose_name='Submit selector')),
('username_selector',
models.CharField(blank=True, default='', max_length=128, verbose_name='Username selector')),
('script', models.JSONField(blank=True, default=list, verbose_name='Script')),
],
options={
'abstract': False,
},
bases=('assets.asset',),
),
migrations.RunPython(migrate_hardware_info), migrations.RunPython(migrate_hardware_info),
migrations.RunPython(migrate_to_host), migrations.RunPython(migrate_to_host),
] ]

View File

@ -1,14 +1,15 @@
# Generated by Django 3.2.14 on 2022-10-19 03:15 # Generated by Django 3.2.14 on 2022-10-19 03:15
import common.db.fields import uuid
import django.db.models.deletion
from django.conf import settings from django.conf import settings
from django.db import migrations, models from django.db import migrations, models
import django.db.models.deletion
import uuid import common.db.fields
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [ dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL), migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('assets', '0106_auto_20220916_1556'), ('assets', '0106_auto_20220916_1556'),
@ -18,14 +19,17 @@ class Migration(migrations.Migration):
migrations.CreateModel( migrations.CreateModel(
name='AutomationExecution', name='AutomationExecution',
fields=[ fields=[
('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), ('org_id',
models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')),
('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)),
('status', models.CharField(default='pending', max_length=16)), ('status', models.CharField(default='pending', max_length=16)),
('date_created', models.DateTimeField(auto_now_add=True, verbose_name='Date created')), ('date_created', models.DateTimeField(auto_now_add=True, verbose_name='Date created')),
('date_start', models.DateTimeField(db_index=True, null=True, verbose_name='Date start')), ('date_start', models.DateTimeField(db_index=True, null=True, verbose_name='Date start')),
('date_finished', models.DateTimeField(null=True, verbose_name='Date finished')), ('date_finished', models.DateTimeField(null=True, verbose_name='Date finished')),
('snapshot', common.db.fields.EncryptJsonDictTextField(blank=True, default=dict, null=True, verbose_name='Automation snapshot')), ('snapshot', common.db.fields.EncryptJsonDictTextField(blank=True, default=dict, null=True,
('trigger', models.CharField(choices=[('manual', 'Manual trigger'), ('timing', 'Timing trigger')], default='manual', max_length=128, verbose_name='Trigger mode')), verbose_name='Automation snapshot')),
('trigger', models.CharField(choices=[('manual', 'Manual trigger'), ('timing', 'Timing trigger')],
default='manual', max_length=128, verbose_name='Trigger mode')),
], ],
options={ options={
'verbose_name': 'Automation task execution', 'verbose_name': 'Automation task execution',
@ -38,9 +42,10 @@ class Migration(migrations.Migration):
('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')), ('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')),
('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')), ('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')),
('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)),
('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), ('org_id',
models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')),
('name', models.CharField(max_length=128, verbose_name='Name')), ('name', models.CharField(max_length=128, verbose_name='Name')),
('is_periodic', models.BooleanField(default=False)), ('is_periodic', models.BooleanField(default=False, verbose_name='Periodic perform')),
('interval', models.IntegerField(blank=True, default=24, null=True, verbose_name='Cycle perform')), ('interval', models.IntegerField(blank=True, default=24, null=True, verbose_name='Cycle perform')),
('crontab', models.CharField(blank=True, max_length=128, null=True, verbose_name='Regularly perform')), ('crontab', models.CharField(blank=True, max_length=128, null=True, verbose_name='Regularly perform')),
('accounts', models.JSONField(default=list, verbose_name='Accounts')), ('accounts', models.JSONField(default=list, verbose_name='Accounts')),
@ -88,7 +93,9 @@ class Migration(migrations.Migration):
migrations.CreateModel( migrations.CreateModel(
name='DiscoveryAccountAutomation', name='DiscoveryAccountAutomation',
fields=[ fields=[
('baseautomation_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='assets.baseautomation')), ('baseautomation_ptr',
models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True,
primary_key=True, serialize=False, to='assets.baseautomation')),
], ],
options={ options={
'verbose_name': 'Discovery account automation', 'verbose_name': 'Discovery account automation',
@ -98,7 +105,9 @@ class Migration(migrations.Migration):
migrations.CreateModel( migrations.CreateModel(
name='GatherFactsAutomation', name='GatherFactsAutomation',
fields=[ fields=[
('baseautomation_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='assets.baseautomation')), ('baseautomation_ptr',
models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True,
primary_key=True, serialize=False, to='assets.baseautomation')),
], ],
options={ options={
'verbose_name': 'Gather asset facts', 'verbose_name': 'Gather asset facts',
@ -108,7 +117,9 @@ class Migration(migrations.Migration):
migrations.CreateModel( migrations.CreateModel(
name='PushAccountAutomation', name='PushAccountAutomation',
fields=[ fields=[
('baseautomation_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='assets.baseautomation')), ('baseautomation_ptr',
models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True,
primary_key=True, serialize=False, to='assets.baseautomation')),
], ],
options={ options={
'verbose_name': 'Push asset account', 'verbose_name': 'Push asset account',
@ -118,7 +129,9 @@ class Migration(migrations.Migration):
migrations.CreateModel( migrations.CreateModel(
name='VerifyAccountAutomation', name='VerifyAccountAutomation',
fields=[ fields=[
('baseautomation_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='assets.baseautomation')), ('baseautomation_ptr',
models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True,
primary_key=True, serialize=False, to='assets.baseautomation')),
], ],
options={ options={
'verbose_name': 'Verify asset account', 'verbose_name': 'Verify asset account',
@ -139,8 +152,10 @@ class Migration(migrations.Migration):
('date_finished', models.DateTimeField(blank=True, null=True, verbose_name='Date finished')), ('date_finished', models.DateTimeField(blank=True, null=True, verbose_name='Date finished')),
('status', models.CharField(default='pending', max_length=16)), ('status', models.CharField(default='pending', max_length=16)),
('error', models.TextField(blank=True, null=True, verbose_name='Error')), ('error', models.TextField(blank=True, null=True, verbose_name='Error')),
('account', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='assets.account')), ('account',
('execution', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='assets.automationexecution')), models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='assets.account')),
('execution',
models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='assets.automationexecution')),
], ],
options={ options={
'verbose_name': 'Change secret record', 'verbose_name': 'Change secret record',
@ -149,18 +164,30 @@ class Migration(migrations.Migration):
migrations.AddField( migrations.AddField(
model_name='automationexecution', model_name='automationexecution',
name='automation', name='automation',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='executions', to='assets.baseautomation', verbose_name='Automation task'), field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='executions',
to='assets.baseautomation', verbose_name='Automation task'),
), ),
migrations.CreateModel( migrations.CreateModel(
name='ChangeSecretAutomation', name='ChangeSecretAutomation',
fields=[ fields=[
('baseautomation_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='assets.baseautomation')), ('baseautomation_ptr',
('secret_type', models.CharField(choices=[('password', 'Password'), ('ssh_key', 'SSH key'), ('access_key', 'Access key'), ('token', 'Token')], default='password', max_length=16, verbose_name='Secret type')), models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True,
('secret_strategy', models.CharField(choices=[('specific', 'Specific'), ('random_one', 'All assets use the same random password'), ('random_all', 'All assets use different random password')], default='specific', max_length=16, verbose_name='Secret strategy')), primary_key=True, serialize=False, to='assets.baseautomation')),
('secret_type', models.CharField(
choices=[('password', 'Password'), ('ssh_key', 'SSH key'), ('access_key', 'Access key'),
('token', 'Token')], default='password', max_length=16, verbose_name='Secret type')),
('secret_strategy', models.CharField(
choices=[('specific', 'Specific'), ('random_one', 'All assets use the same random password'),
('random_all', 'All assets use different random password')], default='specific',
max_length=16, verbose_name='Secret strategy')),
('secret', common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='Secret')), ('secret', common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='Secret')),
('password_rules', models.JSONField(default=dict, verbose_name='Password rules')), ('password_rules', models.JSONField(default=dict, verbose_name='Password rules')),
('ssh_key_change_strategy', models.CharField(choices=[('add', 'Append SSH KEY'), ('set', 'Empty and append SSH KEY'), ('set_jms', 'Replace (The key generated by JumpServer) ')], default='add', max_length=16, verbose_name='SSH key change strategy')), ('ssh_key_change_strategy', models.CharField(
('recipients', models.ManyToManyField(blank=True, to=settings.AUTH_USER_MODEL, verbose_name='Recipient')), choices=[('add', 'Append SSH KEY'), ('set', 'Empty and append SSH KEY'),
('set_jms', 'Replace (The key generated by JumpServer) ')], default='add', max_length=16,
verbose_name='SSH key change strategy')),
('recipients',
models.ManyToManyField(blank=True, to=settings.AUTH_USER_MODEL, verbose_name='Recipient')),
], ],
options={ options={
'verbose_name': 'Change secret automation', 'verbose_name': 'Change secret automation',

View File

@ -4,21 +4,25 @@ from django.db import migrations, models
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [ dependencies = [
('audits', '0014_auto_20220505_1902'), ('audits', '0015_auto_20221011_1745'),
] ]
operations = [ operations = [
migrations.AlterField( migrations.AlterField(
model_name='ftplog', model_name='ftplog',
name='operate', name='operate',
field=models.CharField(choices=[('mkdir', 'Mkdir'), ('rmdir', 'Rmdir'), ('delete', 'Delete'), ('upload', 'Upload'), ('rename', 'Rename'), ('symlink', 'Symlink'), ('download', 'Download')], max_length=16, verbose_name='Operate'), field=models.CharField(
choices=[('mkdir', 'Mkdir'), ('rmdir', 'Rmdir'), ('delete', 'Delete'), ('upload', 'Upload'),
('rename', 'Rename'), ('symlink', 'Symlink'), ('download', 'Download')], max_length=16,
verbose_name='Operate'),
), ),
migrations.AlterField( migrations.AlterField(
model_name='operatelog', model_name='operatelog',
name='action', name='action',
field=models.CharField(choices=[('view', 'View'), ('update', 'Update'), ('delete', 'Delete'), ('create', 'Create')], max_length=16, verbose_name='Action'), field=models.CharField(
choices=[('view', 'View'), ('update', 'Update'), ('delete', 'Delete'), ('create', 'Create')],
max_length=16, verbose_name='Action'),
), ),
migrations.AlterField( migrations.AlterField(
model_name='userloginlog', model_name='userloginlog',

View File

@ -2,41 +2,37 @@
# #
import uuid import uuid
from django.dispatch import receiver
from django.conf import settings from django.conf import settings
from django.contrib.auth import BACKEND_SESSION_KEY
from django.db import transaction from django.db import transaction
from django.db.models.signals import post_save, pre_save, m2m_changed, pre_delete
from django.dispatch import receiver
from django.utils import timezone, translation from django.utils import timezone, translation
from django.utils.functional import LazyObject from django.utils.functional import LazyObject
from django.contrib.auth import BACKEND_SESSION_KEY
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from django.db.models.signals import post_save, pre_save, m2m_changed, pre_delete
from rest_framework.request import Request
from rest_framework.renderers import JSONRenderer from rest_framework.renderers import JSONRenderer
from rest_framework.request import Request
from users.models import User
from audits.utils import model_to_dict_for_operate_log as model_to_dict
from audits.handler import ( from audits.handler import (
get_instance_current_with_cache_diff, cache_instance_before_data, get_instance_current_with_cache_diff, cache_instance_before_data,
create_or_update_operate_log, get_instance_dict_from_cache create_or_update_operate_log, get_instance_dict_from_cache
) )
from audits.utils import model_to_dict_for_operate_log as model_to_dict
from authentication.signals import post_auth_failed, post_auth_success from authentication.signals import post_auth_failed, post_auth_success
from authentication.utils import check_different_city_login_if_need from authentication.utils import check_different_city_login_if_need
from terminal.models import Session, Command
from jumpserver.utils import current_request
from users.signals import post_user_change_password
from .models import OperateLog
from .const import MODELS_NEED_RECORD
from terminal.serializers import SessionSerializer
from terminal.backends.command.serializers import SessionCommandSerializer
from common.const.signals import POST_ADD, POST_REMOVE, POST_CLEAR, SKIP_SIGNAL from common.const.signals import POST_ADD, POST_REMOVE, POST_CLEAR, SKIP_SIGNAL
from common.utils import get_request_ip, get_logger, get_syslogger from common.utils import get_request_ip, get_logger, get_syslogger
from common.utils.encode import data_to_json from common.utils.encode import data_to_json
from jumpserver.utils import current_request
from terminal.backends.command.serializers import SessionCommandSerializer
from terminal.models import Session, Command
from terminal.serializers import SessionSerializer
from users.models import User
from users.signals import post_user_change_password
from . import models, serializers from . import models, serializers
from .const import MODELS_NEED_RECORD, ActionChoices
from .utils import write_login_log from .utils import write_login_log
logger = get_logger(__name__) logger = get_logger(__name__)
sys_logger = get_syslogger(__name__) sys_logger = get_syslogger(__name__)
json_render = JSONRenderer() json_render = JSONRenderer()
@ -66,9 +62,9 @@ class AuthBackendLabelMapping(LazyObject):
AUTH_BACKEND_LABEL_MAPPING = AuthBackendLabelMapping() AUTH_BACKEND_LABEL_MAPPING = AuthBackendLabelMapping()
M2M_ACTION = { M2M_ACTION = {
POST_ADD: OperateLog.ACTION_CREATE, POST_ADD: ActionChoices.create,
POST_REMOVE: OperateLog.ACTION_DELETE, POST_REMOVE: ActionChoices.delete,
POST_CLEAR: OperateLog.ACTION_DELETE, POST_CLEAR: ActionChoices.delete,
} }
@ -92,9 +88,9 @@ def on_m2m_changed(sender, action, instance, reverse, model, pk_set, **kwargs):
changed_field = current_instance.get(field_name, []) changed_field = current_instance.get(field_name, [])
after, before, before_value = None, None, None after, before, before_value = None, None, None
if action == OperateLog.ACTION_CREATE: if action == ActionChoices.create:
before_value = list(set(changed_field) - set(objs_display)) before_value = list(set(changed_field) - set(objs_display))
elif action == OperateLog.ACTION_DELETE: elif action == ActionChoices.delete:
before_value = list( before_value = list(
set(changed_field).symmetric_difference(set(objs_display)) set(changed_field).symmetric_difference(set(objs_display))
) )
@ -108,7 +104,7 @@ def on_m2m_changed(sender, action, instance, reverse, model, pk_set, **kwargs):
return return
create_or_update_operate_log( create_or_update_operate_log(
OperateLog.ACTION_UPDATE, resource_type, ActionChoices.update, resource_type,
resource=instance, log_id=log_id, before=before, after=after resource=instance, log_id=log_id, before=before, after=after
) )
@ -159,11 +155,11 @@ def on_object_created_or_update(sender, instance=None, created=False, update_fie
log_id, before, after = None, None, None log_id, before, after = None, None, None
if created: if created:
action = models.OperateLog.ACTION_CREATE action = models.ActionChoices.create
after = model_to_dict(instance) after = model_to_dict(instance)
log_id = getattr(instance, 'operate_log_id', None) log_id = getattr(instance, 'operate_log_id', None)
else: else:
action = models.OperateLog.ACTION_UPDATE action = ActionChoices.update
current_instance = model_to_dict(instance) current_instance = model_to_dict(instance)
log_id, before, after = get_instance_current_with_cache_diff(current_instance) log_id, before, after = get_instance_current_with_cache_diff(current_instance)
@ -182,7 +178,7 @@ def on_object_delete(sender, instance=None, **kwargs):
resource_type = sender._meta.verbose_name resource_type = sender._meta.verbose_name
create_or_update_operate_log( create_or_update_operate_log(
models.OperateLog.ACTION_DELETE, resource_type, ActionChoices.delete, resource_type,
resource=instance, before=model_to_dict(instance) resource=instance, before=model_to_dict(instance)
) )

View File

@ -9,15 +9,14 @@
- 此文件中添加代码的时候注意不要跟 `django.db.models` 中的命名冲突 - 此文件中添加代码的时候注意不要跟 `django.db.models` 中的命名冲突
""" """
import inspect
import uuid import uuid
from functools import reduce, partial from functools import reduce, partial
import inspect
from django.db import models from django.db import models
from django.db.models import F, Value, ExpressionWrapper
from django.db import transaction from django.db import transaction
from django.db.models import F, ExpressionWrapper, CASCADE
from django.db.models import QuerySet from django.db.models import QuerySet
from django.db.models.functions import Concat
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from ..const.signals import SKIP_SIGNAL from ..const.signals import SKIP_SIGNAL

View File

@ -1,18 +0,0 @@
# Generated by Django 3.2.14 on 2022-11-04 07:06
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('perms', '0028_auto_20220316_2028'),
]
operations = [
migrations.AlterField(
model_name='applicationpermission',
name='type',
field=models.CharField(choices=[('mysql', 'MySQL'), ('mariadb', 'MariaDB'), ('oracle', 'Oracle'), ('postgresql', 'PostgreSQL'), ('sqlserver', 'SQLServer'), ('redis', 'Redis'), ('mongodb', 'MongoDB'), ('clickhouse', 'ClickHouse'), ('chrome', 'Chrome'), ('mysql_workbench', 'MySQL Workbench'), ('vmware_client', 'vSphere Client'), ('custom', 'Custom'), ('k8s', 'Kubernetes')], max_length=16, verbose_name='Type'),
),
]

View File

@ -1,32 +0,0 @@
# Generated by Django 3.2.13 on 2022-08-30 04:44
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('terminal', '0052_auto_20220713_1417'),
]
operations = [
migrations.AlterField(
model_name='session',
name='protocol',
field=models.CharField(db_index=True, default='ssh', max_length=16),
),
migrations.RenameField(
model_name='session',
old_name='system_user',
new_name='account',
),
migrations.RemoveField(
model_name='session',
name='system_user_id',
),
migrations.AlterField(
model_name='session',
name='account',
field=models.CharField(db_index=True, max_length=128, verbose_name='Account'),
),
]

View File

@ -1,18 +0,0 @@
# Generated by Django 3.2.14 on 2022-11-04 07:06
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('terminal', '0053_auto_20221009_1755'),
]
operations = [
migrations.AlterField(
model_name='session',
name='protocol',
field=models.CharField(choices=[('ssh', 'ssh'), ('rdp', 'rdp'), ('vnc', 'vnc'), ('telnet', 'telnet'), ('mysql', 'mysql'), ('oracle', 'oracle'), ('mariadb', 'mariadb'), ('sqlserver', 'sqlserver'), ('postgresql', 'postgresql'), ('redis', 'redis'), ('mongodb', 'MongoDB'), ('clickhouse', 'ClickHouse'), ('k8s', 'kubernetes')], db_index=True, default='ssh', max_length=16),
),
]

View File

@ -1,18 +1,37 @@
# Generated by Django 3.2.14 on 2022-10-27 03:25 # Generated by Django 3.2.14 on 2022-10-27 03:25
from django.db import migrations, models
import django.db.models.deletion
import uuid import uuid
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [ dependencies = [
('assets', '0107_auto_20221019_1115'), ('assets', '0107_auto_20221019_1115'),
('terminal', '0053_auto_20220830_1244'), ('terminal', '0053_auto_20221009_1755'),
] ]
operations = [ operations = [
migrations.AlterField(
model_name='session',
name='protocol',
field=models.CharField(db_index=True, default='ssh', max_length=16),
),
migrations.RenameField(
model_name='session',
old_name='system_user',
new_name='account',
),
migrations.RemoveField(
model_name='session',
name='system_user_id',
),
migrations.AlterField(
model_name='session',
name='account',
field=models.CharField(db_index=True, max_length=128, verbose_name='Account'),
),
migrations.CreateModel( migrations.CreateModel(
name='Applet', name='Applet',
fields=[ fields=[
@ -25,7 +44,9 @@ class Migration(migrations.Migration):
('display_name', models.CharField(max_length=128, verbose_name='Display name')), ('display_name', models.CharField(max_length=128, verbose_name='Display name')),
('version', models.CharField(max_length=16, verbose_name='Version')), ('version', models.CharField(max_length=16, verbose_name='Version')),
('author', models.CharField(max_length=128, verbose_name='Author')), ('author', models.CharField(max_length=128, verbose_name='Author')),
('type', models.CharField(choices=[('general', 'General'), ('web', 'Web')], default='general', max_length=16, verbose_name='Type')), ('type',
models.CharField(choices=[('general', 'General'), ('web', 'Web')], default='general', max_length=16,
verbose_name='Type')),
('is_active', models.BooleanField(default=True, verbose_name='Is active')), ('is_active', models.BooleanField(default=True, verbose_name='Is active')),
('protocols', models.JSONField(default=list, verbose_name='Protocol')), ('protocols', models.JSONField(default=list, verbose_name='Protocol')),
('tags', models.JSONField(default=list, verbose_name='Tags')), ('tags', models.JSONField(default=list, verbose_name='Tags')),
@ -38,7 +59,9 @@ class Migration(migrations.Migration):
migrations.CreateModel( migrations.CreateModel(
name='AppletHost', name='AppletHost',
fields=[ fields=[
('host_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='assets.host')), ('host_ptr',
models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True,
primary_key=True, serialize=False, to='assets.host')),
('date_synced', models.DateTimeField(blank=True, null=True, verbose_name='Date synced')), ('date_synced', models.DateTimeField(blank=True, null=True, verbose_name='Date synced')),
('status', models.CharField(max_length=16, verbose_name='Status')), ('status', models.CharField(max_length=16, verbose_name='Status')),
], ],
@ -57,8 +80,10 @@ class Migration(migrations.Migration):
('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)),
('status', models.CharField(default='', max_length=16, verbose_name='Status')), ('status', models.CharField(default='', max_length=16, verbose_name='Status')),
('comment', models.TextField(blank=True, default='', verbose_name='Comment')), ('comment', models.TextField(blank=True, default='', verbose_name='Comment')),
('applet', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='terminal.applet', verbose_name='Applet')), ('applet', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='terminal.applet',
('host', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='terminal.applethost', verbose_name='Host')), verbose_name='Applet')),
('host', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='terminal.applethost',
verbose_name='Host')),
], ],
options={ options={
'unique_together': {('applet', 'host')}, 'unique_together': {('applet', 'host')},
@ -74,7 +99,8 @@ class Migration(migrations.Migration):
('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)),
('status', models.CharField(max_length=16, default='', verbose_name='Status')), ('status', models.CharField(max_length=16, default='', verbose_name='Status')),
('comment', models.TextField(blank=True, default='', verbose_name='Comment')), ('comment', models.TextField(blank=True, default='', verbose_name='Comment')),
('host', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='terminal.applethost', verbose_name='Hosting')), ('host', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='terminal.applethost',
verbose_name='Hosting')),
], ],
options={ options={
'abstract': False, 'abstract': False,
@ -83,6 +109,7 @@ class Migration(migrations.Migration):
migrations.AddField( migrations.AddField(
model_name='applethost', model_name='applethost',
name='applets', name='applets',
field=models.ManyToManyField(through='terminal.AppletPublication', to='terminal.Applet', verbose_name='Applet'), field=models.ManyToManyField(through='terminal.AppletPublication', to='terminal.Applet',
verbose_name='Applet'),
), ),
] ]

View File

@ -1,13 +1,11 @@
from django.core.validators import MinValueValidator, MaxValueValidator
from django.db import models from django.db import models
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from django.core.validators import MinValueValidator, MaxValueValidator
from common.db.models import JMSBaseModel from assets.models import Asset
from common.db.fields import PortField from common.db.fields import PortField
from common.db.models import JMSBaseModel
from common.utils.ip import contains_ip from common.utils.ip import contains_ip
from ..utils import db_port_manager, DBPortManager
db_port_manager: DBPortManager
class Endpoint(JMSBaseModel): class Endpoint(JMSBaseModel):
@ -31,9 +29,10 @@ class Endpoint(JMSBaseModel):
return self.name return self.name
def get_port(self, target_instance, protocol): def get_port(self, target_instance, protocol):
from terminal.utils import db_port_manager
if protocol in ['https', 'http', 'ssh', 'rdp']: if protocol in ['https', 'http', 'ssh', 'rdp']:
port = getattr(self, f'{protocol}_port', 0) port = getattr(self, f'{protocol}_port', 0)
elif isinstance(target_instance, Application) and target_instance.category_db: elif isinstance(target_instance, Asset) and target_instance.category == 'dabase':
port = db_port_manager.get_port_by_db(target_instance) port = db_port_manager.get_port_by_db(target_instance)
else: else:
port = 0 port = 0

View File

@ -5,8 +5,8 @@ from django.conf import settings
from django.db import models from django.db import models
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from common.utils import get_logger, lazyproperty
from common.const.signals import SKIP_SIGNAL from common.const.signals import SKIP_SIGNAL
from common.utils import get_logger, lazyproperty
from orgs.utils import tmp_to_root_org from orgs.utils import tmp_to_root_org
from terminal.const import TerminalType as TypeChoices from terminal.const import TerminalType as TypeChoices
from users.models import User from users.models import User
@ -85,8 +85,9 @@ class Terminal(StorageMixin, TerminalStatusMixin, models.Model):
remote_addr = models.CharField(max_length=128, blank=True, verbose_name=_('Remote Address')) remote_addr = models.CharField(max_length=128, blank=True, verbose_name=_('Remote Address'))
command_storage = models.CharField(max_length=128, verbose_name=_("Command storage"), default='default') command_storage = models.CharField(max_length=128, verbose_name=_("Command storage"), default='default')
replay_storage = models.CharField(max_length=128, verbose_name=_("Replay storage"), default='default') replay_storage = models.CharField(max_length=128, verbose_name=_("Replay storage"), default='default')
user = models.OneToOneField(User, related_name='terminal', verbose_name=_('Application User'), null=True, on_delete=models.CASCADE) user = models.OneToOneField(User, related_name='terminal', verbose_name=_('Application User'), null=True,
is_accepted = models.BooleanField(default=False, verbose_name=_('Is Accepted')) on_delete=models.CASCADE)
is_deleted = models.BooleanField(default=False, verbose_name=_('Is deleted'))
date_created = models.DateTimeField(auto_now_add=True) date_created = models.DateTimeField(auto_now_add=True)
comment = models.TextField(blank=True, verbose_name=_('Comment')) comment = models.TextField(blank=True, verbose_name=_('Comment'))

View File

@ -2,55 +2,11 @@
# #
from common.utils import get_logger from common.utils import get_logger
from .. import const
from tickets.models import TicketSession from tickets.models import TicketSession
logger = get_logger(__name__) logger = get_logger(__name__)
class ComputeStatUtil:
# system status
@staticmethod
def _common_compute_system_status(value, thresholds):
if thresholds[0] <= value <= thresholds[1]:
return const.ComponentStatusChoices.normal.value
elif thresholds[1] < value <= thresholds[2]:
return const.ComponentStatusChoices.high.value
else:
return const.ComponentStatusChoices.critical.value
@classmethod
def _compute_system_stat_status(cls, stat):
system_stat_thresholds_mapper = {
'cpu_load': [0, 5, 20],
'memory_used': [0, 85, 95],
'disk_used': [0, 80, 99]
}
system_status = {}
for stat_key, thresholds in system_stat_thresholds_mapper.items():
stat_value = getattr(stat, stat_key)
if stat_value is None:
msg = 'stat: {}, stat_key: {}, stat_value: {}'
logger.debug(msg.format(stat, stat_key, stat_value))
stat_value = 0
status = cls._common_compute_system_status(stat_value, thresholds)
system_status[stat_key] = status
return system_status
@classmethod
def compute_component_status(cls, stat):
if not stat:
return const.ComponentStatusChoices.offline
system_status_values = cls._compute_system_stat_status(stat).values()
if const.ComponentStatusChoices.critical in system_status_values:
return const.ComponentStatusChoices.critical
elif const.ComponentStatusChoices.high in system_status_values:
return const.ComponentStatusChoices.high
else:
return const.ComponentStatusChoices.normal
def is_session_approver(session_id, user_id): def is_session_approver(session_id, user_id):
ticket = TicketSession.get_ticket_by_session_id(session_id) ticket = TicketSession.get_ticket_by_session_id(session_id)
if not ticket: if not ticket:

View File

@ -1,94 +1,24 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
import os
import time import time
from itertools import groupby, chain
from collections import defaultdict
from django.utils import timezone
from django.conf import settings
from django.core.files.storage import default_storage
import jms_storage
from itertools import groupby from itertools import groupby
from common.utils import get_logger from common.utils import get_logger
from tickets.models import TicketSession from terminal.const import ComponentLoad
from . import const
from ..models import ReplayStorage
logger = get_logger(__name__) logger = get_logger(__name__)
def find_session_replay_local(session):
# 存在外部存储上,所有可能的路径名
session_paths = session.get_all_possible_relative_path()
# 存在本地存储上,所有可能的路径名
local_paths = session.get_all_possible_local_path()
for _local_path in chain(session_paths, local_paths):
if default_storage.exists(_local_path):
url = default_storage.url(_local_path)
return _local_path, url
return None, None
def download_session_replay(session):
replay_storages = ReplayStorage.objects.all()
configs = {
storage.name: storage.config
for storage in replay_storages
if not storage.type_null_or_server
}
if settings.SERVER_REPLAY_STORAGE:
configs['SERVER_REPLAY_STORAGE'] = settings.SERVER_REPLAY_STORAGE
if not configs:
msg = "Not found replay file, and not remote storage set"
return None, msg
storage = jms_storage.get_multi_object_storage(configs)
# 获取外部存储路径名
session_path = session.find_ok_relative_path_in_storage(storage)
if not session_path:
msg = "Not found session replay file"
return None, msg
# 通过外部存储路径名后缀,构造真实的本地存储路径
local_path = session.get_local_path_by_relative_path(session_path)
# 保存到storage的路径
target_path = os.path.join(default_storage.base_location, local_path)
target_dir = os.path.dirname(target_path)
if not os.path.isdir(target_dir):
os.makedirs(target_dir, exist_ok=True)
ok, err = storage.download(session_path, target_path)
if not ok:
msg = "Failed download replay file: {}".format(err)
logger.error(msg)
return None, msg
url = default_storage.url(local_path)
return local_path, url
def get_session_replay_url(session):
local_path, url = find_session_replay_local(session)
if local_path is None:
local_path, url = download_session_replay(session)
return local_path, url
class ComputeLoadUtil: class ComputeLoadUtil:
# system status # system status
@staticmethod @staticmethod
def _common_compute_system_status(value, thresholds): def _common_compute_system_status(value, thresholds):
if thresholds[0] <= value <= thresholds[1]: if thresholds[0] <= value <= thresholds[1]:
return const.ComponentLoad.normal.value return ComponentLoad.normal.value
elif thresholds[1] < value <= thresholds[2]: elif thresholds[1] < value <= thresholds[2]:
return const.ComponentLoad.high.value return ComponentLoad.high.value
else: else:
return const.ComponentLoad.critical.value return ComponentLoad.critical.value
@classmethod @classmethod
def _compute_system_stat_status(cls, stat): def _compute_system_stat_status(cls, stat):
@ -111,14 +41,14 @@ class ComputeLoadUtil:
@classmethod @classmethod
def compute_load(cls, stat): def compute_load(cls, stat):
if not stat or time.time() - stat.date_created.timestamp() > 150: if not stat or time.time() - stat.date_created.timestamp() > 150:
return const.ComponentLoad.offline return ComponentLoad.offline
system_status_values = cls._compute_system_stat_status(stat).values() system_status_values = cls._compute_system_stat_status(stat).values()
if const.ComponentLoad.critical in system_status_values: if ComponentLoad.critical in system_status_values:
return const.ComponentLoad.critical return ComponentLoad.critical
elif const.ComponentLoad.high in system_status_values: elif ComponentLoad.high in system_status_values:
return const.ComponentLoad.high return ComponentLoad.high
else: else:
return const.ComponentLoad.normal return ComponentLoad.normal
class TypedComponentsStatusMetricsUtil(object): class TypedComponentsStatusMetricsUtil(object):
@ -236,4 +166,3 @@ class ComponentsPrometheusMetricsUtil(TypedComponentsStatusMetricsUtil):
prometheus_metrics.append('\n') prometheus_metrics.append('\n')
prometheus_metrics_text = '\n'.join(prometheus_metrics) prometheus_metrics_text = '\n'.join(prometheus_metrics)
return prometheus_metrics_text return prometheus_metrics_text

View File

@ -1,15 +1,14 @@
from django.utils.translation import ugettext_lazy as _
from django.core.cache import cache
from django.conf import settings from django.conf import settings
from django.core.cache import cache
from django.utils.translation import ugettext_lazy as _
from assets.const import Category
from assets.models import Asset
from common.decorator import Singleton from common.decorator import Singleton
from common.utils import get_logger, get_object_or_none
from common.exceptions import JMSException from common.exceptions import JMSException
from applications.const import AppCategory from common.utils import get_logger, get_object_or_none
from applications.models import Application
from orgs.utils import tmp_to_root_org from orgs.utils import tmp_to_root_org
logger = get_logger(__file__) logger = get_logger(__file__)
@ -37,19 +36,19 @@ class DBPortManager(object):
def init(self): def init(self):
with tmp_to_root_org(): with tmp_to_root_org():
db_ids = Application.objects.filter(category=AppCategory.db).values_list('id', flat=True) db_ids = Asset.objects.filter(platform__category=Category.DATABASE).values_list('id', flat=True)
db_ids = [str(i) for i in db_ids] db_ids = [str(i) for i in db_ids]
mapper = dict(zip(self.all_available_ports, list(db_ids))) mapper = dict(zip(self.all_available_ports, list(db_ids)))
self.set_mapper(mapper) self.set_mapper(mapper)
def add(self, db: Application): def add(self, db: Asset):
mapper = self.get_mapper() mapper = self.get_mapper()
available_port = self.get_next_available_port() available_port = self.get_next_available_port()
mapper.update({available_port: str(db.id)}) mapper.update({available_port: str(db.id)})
self.set_mapper(mapper) self.set_mapper(mapper)
return True return True
def pop(self, db: Application): def pop(self, db: Asset):
mapper = self.get_mapper() mapper = self.get_mapper()
to_delete_port = self.get_port_by_db(db, raise_exception=False) to_delete_port = self.get_port_by_db(db, raise_exception=False)
mapper.pop(to_delete_port, None) mapper.pop(to_delete_port, None)
@ -79,7 +78,7 @@ class DBPortManager(object):
if not db_id: if not db_id:
raise JMSException('Database not in port-db mapper, port: {}'.format(port)) raise JMSException('Database not in port-db mapper, port: {}'.format(port))
with tmp_to_root_org(): with tmp_to_root_org():
db = get_object_or_none(Application, id=db_id) db = get_object_or_none(Asset, id=db_id)
if not db: if not db:
raise JMSException('Database not exists, db id: {}'.format(db_id)) raise JMSException('Database not exists, db id: {}'.format(db_id))
return db return db

View File

@ -1,18 +0,0 @@
# Generated by Django 3.2.14 on 2022-11-04 07:06
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('tickets', '0018_applyapplicationticket_apply_actions'),
]
operations = [
migrations.AlterField(
model_name='applyapplicationticket',
name='apply_type',
field=models.CharField(choices=[('mysql', 'MySQL'), ('mariadb', 'MariaDB'), ('oracle', 'Oracle'), ('postgresql', 'PostgreSQL'), ('sqlserver', 'SQLServer'), ('redis', 'Redis'), ('mongodb', 'MongoDB'), ('clickhouse', 'ClickHouse'), ('chrome', 'Chrome'), ('mysql_workbench', 'MySQL Workbench'), ('vmware_client', 'vSphere Client'), ('custom', 'Custom'), ('k8s', 'Kubernetes')], max_length=16, verbose_name='Type'),
),
]

View File

@ -1,14 +1,14 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
from rest_framework import serializers
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from rest_framework import serializers
from common.drf.fields import LabeledChoiceField from common.drf.fields import LabeledChoiceField
from users.models import User
from orgs.models import Organization
from orgs.mixins.serializers import OrgResourceModelSerializerMixin from orgs.mixins.serializers import OrgResourceModelSerializerMixin
from tickets.models import Ticket, TicketFlow from orgs.models import Organization
from tickets.const import TicketType, TicketStatus, TicketState from tickets.const import TicketType, TicketStatus, TicketState
from tickets.models import Ticket, TicketFlow
from users.models import User
__all__ = [ __all__ = [
'TicketApplySerializer', 'TicketApproveSerializer', 'TicketSerializer', 'TicketApplySerializer', 'TicketApproveSerializer', 'TicketSerializer',
@ -63,13 +63,6 @@ class TicketApplySerializer(TicketSerializer):
) )
applicant = serializers.CharField(required=False, allow_blank=True) applicant = serializers.CharField(required=False, allow_blank=True)
class Meta:
model = Ticket
fields = TicketSerializer.Meta.fields
extra_kwargs = {
'type': {'required': True}
}
def get_applicant(self, applicant_id): def get_applicant(self, applicant_id):
current_user = self.context['request'].user current_user = self.context['request'].user
want_applicant = User.objects.filter(id=applicant_id).first() want_applicant = User.objects.filter(id=applicant_id).first()