diff --git a/apps/assets/migrations/0114_node_domain.py b/apps/assets/migrations/0114_node_domain.py new file mode 100644 index 000000000..896a611d5 --- /dev/null +++ b/apps/assets/migrations/0114_node_domain.py @@ -0,0 +1,21 @@ +# Generated by Django 3.2.14 on 2022-11-29 05:14 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + dependencies = [ + ('assets', '0113_alter_accounttemplate_options'), + ] + + operations = [ + migrations.AddField( + model_name='node', + name='domain', + field=models.ForeignKey( + blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, + related_name='nodes', to='assets.domain', verbose_name='Domain' + ), + ), + ] diff --git a/apps/assets/models/asset/common.py b/apps/assets/models/asset/common.py index 81693252d..7f01c222d 100644 --- a/apps/assets/models/asset/common.py +++ b/apps/assets/models/asset/common.py @@ -105,6 +105,14 @@ class Asset(NodesRelationMixin, AbsConnectivity, JMSOrgBaseModel): def __str__(self): return '{0.name}({0.address})'.format(self) + def get_domains(self): + from ..domain import Domain + node_ids = self.get_all_nodes(flat=True) + domains = Domain.objects.filter( + Q(nodes__id__in=node_ids) | Q(id=self.domain_id) + ).distinct() + return domains + @property def specific(self): if not hasattr(self, self.category): diff --git a/apps/assets/models/node.py b/apps/assets/models/node.py index 0e98bce14..bf394e982 100644 --- a/apps/assets/models/node.py +++ b/apps/assets/models/node.py @@ -554,9 +554,14 @@ class Node(OrgModelMixin, SomeNodesMixin, FamilyMixin, NodeAssetsMixin): full_value = models.CharField(max_length=4096, verbose_name=_('Full value'), default='') child_mark = models.IntegerField(default=0) date_create = models.DateTimeField(auto_now_add=True) - parent_key = models.CharField(max_length=64, verbose_name=_("Parent key"), - db_index=True, default='') + parent_key = models.CharField( + max_length=64, verbose_name=_("Parent key"), db_index=True, default='' + ) assets_amount = models.IntegerField(default=0) + domain = models.ForeignKey( + "assets.Domain", null=True, blank=True, related_name='nodes', + verbose_name=_("Domain"), on_delete=models.SET_NULL + ) objects = OrgManager.from_queryset(NodeQuerySet)() is_node = True diff --git a/apps/assets/serializers/domain.py b/apps/assets/serializers/domain.py index 9e495d104..617aa34bc 100644 --- a/apps/assets/serializers/domain.py +++ b/apps/assets/serializers/domain.py @@ -4,19 +4,22 @@ from rest_framework import serializers from rest_framework.generics import get_object_or_404 from django.utils.translation import ugettext_lazy as _ -from orgs.mixins.serializers import BulkOrgResourceModelSerializer, OrgResourceSerializerMixin +from orgs.mixins.serializers import BulkOrgResourceModelSerializer from common.drf.serializers import SecretReadableMixin, WritableNestedModelSerializer from common.drf.fields import ObjectRelatedField, EncryptedField -from assets.models import Platform, Node from assets.const import SecretType, GATEWAY_NAME from ..serializers import AssetProtocolsSerializer -from ..models import Domain, Asset, Account, Host +from ..models import Platform, Domain, Node, Asset, Account, Host from .utils import validate_password_for_ansible, validate_ssh_key class DomainSerializer(BulkOrgResourceModelSerializer): + node_count = serializers.SerializerMethodField(label=_('Nodes amount')) asset_count = serializers.SerializerMethodField(label=_('Assets amount')) gateway_count = serializers.SerializerMethodField(label=_('Gateways count')) + nodes = ObjectRelatedField( + many=True, required=False, queryset=Node.objects, label=_('Node') + ) assets = ObjectRelatedField( many=True, required=False, queryset=Asset.objects, label=_('Asset') ) @@ -25,14 +28,18 @@ class DomainSerializer(BulkOrgResourceModelSerializer): model = Domain fields_mini = ['id', 'name'] fields_small = fields_mini + ['comment'] - fields_m2m = ['assets'] - read_only_fields = ['asset_count', 'gateway_count', 'date_created'] + fields_m2m = ['nodes', 'assets'] + read_only_fields = ['node_count', 'asset_count', 'gateway_count', 'date_created'] fields = fields_small + fields_m2m + read_only_fields extra_kwargs = { 'assets': {'required': False, 'label': _('Assets')}, } + @staticmethod + def get_node_count(obj): + return obj.nodes.count() + @staticmethod def get_asset_count(obj): return obj.assets.count() diff --git a/apps/ops/ansible/inventory.py b/apps/ops/ansible/inventory.py index 1e006ae77..aa7f8186d 100644 --- a/apps/ops/ansible/inventory.py +++ b/apps/ops/ansible/inventory.py @@ -1,6 +1,7 @@ # ~*~ coding: utf-8 ~*~ import json import os +import random from collections import defaultdict from django.utils.translation import gettext as _ @@ -117,8 +118,10 @@ class JMSInventory: host.update(ansible_config) gateway = None - if asset.domain: - gateway = asset.domain.select_gateway() + domains = asset.get_domains() + if domains: + gateways = [i.select_gateway() for i in domains if i.select_gateway()] + gateway = random.choice(gateways) if gateways else None if ansible_connection == 'local': if gateway: