node.py 8.3 KB
Newer Older
baltery's avatar
baltery 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
# ~*~ coding: utf-8 ~*~
# Copyright (C) 2014-2018 Beijing DuiZhan Technology Co.,Ltd. All Rights Reserved.
#
# Licensed under the GNU General Public License v2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.gnu.org/licenses/gpl-2.0.html
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from rest_framework import generics, mixins
17
from rest_framework.serializers import ValidationError
18
from rest_framework.views import APIView
baltery's avatar
baltery 已提交
19 20 21
from rest_framework.response import Response
from rest_framework_bulk import BulkModelViewSet
from django.utils.translation import ugettext_lazy as _
22
from django.shortcuts import get_object_or_404
baltery's avatar
baltery 已提交
23

baltery's avatar
baltery 已提交
24
from common.utils import get_logger, get_object_or_none
baltery's avatar
baltery 已提交
25 26
from ..hands import IsSuperUser
from ..models import Node
27
from ..tasks import update_assets_hardware_info_util, test_asset_connectability_util
baltery's avatar
baltery 已提交
28 29 30 31
from .. import serializers


logger = get_logger(__file__)
32
__all__ = [
baltery's avatar
baltery 已提交
33 34
    'NodeViewSet', 'NodeChildrenApi', 'NodeAssetsApi',
    'NodeAddAssetsApi', 'NodeRemoveAssetsApi', 'NodeReplaceAssetsApi',
35 36
    'NodeAddChildrenApi', 'RefreshNodeHardwareInfoApi',
    'TestNodeConnectiveApi'
37
]
baltery's avatar
baltery 已提交
38 39 40


class NodeViewSet(BulkModelViewSet):
baltery's avatar
baltery 已提交
41
    queryset = Node.objects.all()
baltery's avatar
baltery 已提交
42
    permission_classes = (IsSuperUser,)
43
    serializer_class = serializers.NodeSerializer
baltery's avatar
baltery 已提交
44

45 46 47 48
    def perform_create(self, serializer):
        child_key = Node.root().get_next_child_key()
        serializer.validated_data["key"] = child_key
        serializer.save()
baltery's avatar
baltery 已提交
49 50


51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
# class NodeWithAssetsApi(generics.ListAPIView):
#     permission_classes = (IsSuperUser,)
#     serializers = serializers.NodeSerializer
#
#     def get_node(self):
#         pk = self.kwargs.get('pk') or self.request.query_params.get('node')
#         if not pk:
#             node = Node.root()
#         else:
#             node = get_object_or_404(Node, pk)
#         return node
#
#     def get_queryset(self):
#         queryset = []
#         node = self.get_node()
#         children = node.get_children()
#         assets = node.get_assets()
#         queryset.extend(list(children))
#
#         for asset in assets:
#             node = Node()
#             node.id = asset.id
#             node.parent = node.id
#             node.value = asset.hostname
#             queryset.append(node)
#         return queryset
baltery's avatar
baltery 已提交
77 78


baltery's avatar
baltery 已提交
79
class NodeChildrenApi(mixins.ListModelMixin, generics.CreateAPIView):
baltery's avatar
baltery 已提交
80
    queryset = Node.objects.all()
baltery's avatar
baltery 已提交
81 82 83 84
    permission_classes = (IsSuperUser,)
    serializer_class = serializers.NodeSerializer
    instance = None

85 86 87 88 89 90 91 92 93 94
    def counter(self):
        values = [
            child.value[child.value.rfind(' '):]
            for child in self.get_object().get_children()
            if child.value.startswith("新节点 ")
        ]
        values = [int(value) for value in values if value.strip().isdigit()]
        count = max(values)+1 if values else 1
        return count

baltery's avatar
baltery 已提交
95 96
    def post(self, request, *args, **kwargs):
        if not request.data.get("value"):
97
            request.data["value"] = _("New node {}").format(self.counter())
baltery's avatar
baltery 已提交
98 99 100 101 102
        return super().post(request, *args, **kwargs)

    def create(self, request, *args, **kwargs):
        instance = self.get_object()
        value = request.data.get("value")
103 104
        values = [child.value for child in instance.get_children()]
        if value in values:
105 106 107
            raise ValidationError(
                'The same level node name cannot be the same'
            )
baltery's avatar
baltery 已提交
108 109 110 111 112 113
        node = instance.create_child(value=value)
        return Response(
            {"id": node.id, "key": node.key, "value": node.value},
            status=201,
        )

baltery's avatar
baltery 已提交
114 115 116
    def get_object(self):
        pk = self.kwargs.get('pk') or self.request.query_params.get('id')
        if not pk:
117
            node = None
baltery's avatar
baltery 已提交
118 119 120 121 122
        else:
            node = get_object_or_404(Node, pk=pk)
        return node

    def get_queryset(self):
baltery's avatar
baltery 已提交
123
        queryset = []
baltery's avatar
baltery 已提交
124 125 126
        query_all = self.request.query_params.get("all")
        query_assets = self.request.query_params.get('assets')
        node = self.get_object()
127 128
        if node is None:
            node = Node.root()
baltery's avatar
baltery 已提交
129
            queryset.append(node)
baltery's avatar
baltery 已提交
130 131 132 133 134
        if query_all:
            children = node.get_all_children()
        else:
            children = node.get_children()

baltery's avatar
baltery 已提交
135
        queryset.extend(list(children))
baltery's avatar
baltery 已提交
136 137 138 139 140
        if query_assets:
            assets = node.get_assets()
            for asset in assets:
                node_fake = Node()
                node_fake.id = asset.id
141
                node_fake.is_node = False
baltery's avatar
baltery 已提交
142
                node_fake.parent_id = node.id
baltery's avatar
baltery 已提交
143
                node_fake.value = asset.hostname
baltery's avatar
baltery 已提交
144
                queryset.append(node_fake)
145
        queryset = sorted(queryset, key=lambda x: x.is_node, reverse=True)
baltery's avatar
baltery 已提交
146 147
        return queryset

baltery's avatar
baltery 已提交
148
    def get(self, request, *args, **kwargs):
baltery's avatar
baltery 已提交
149 150 151 152 153 154 155 156 157 158 159 160 161
        return super().list(request, *args, **kwargs)


class NodeAssetsApi(generics.ListAPIView):
    permission_classes = (IsSuperUser,)
    serializer_class = serializers.AssetSerializer

    def get_queryset(self):
        node_id = self.kwargs.get('pk')
        query_all = self.request.query_params.get('all')
        instance = get_object_or_404(Node, pk=node_id)
        if query_all:
            return instance.get_all_assets()
baltery's avatar
baltery 已提交
162
        else:
baltery's avatar
baltery 已提交
163
            return instance.get_assets()
baltery's avatar
baltery 已提交
164

165

baltery's avatar
baltery 已提交
166
class NodeAddChildrenApi(generics.UpdateAPIView):
baltery's avatar
baltery 已提交
167
    queryset = Node.objects.all()
baltery's avatar
baltery 已提交
168 169 170 171 172 173 174 175 176 177 178
    permission_classes = (IsSuperUser,)
    serializer_class = serializers.NodeAddChildrenSerializer
    instance = None

    def put(self, request, *args, **kwargs):
        instance = self.get_object()
        nodes_id = request.data.get("nodes")
        children = [get_object_or_none(Node, id=pk) for pk in nodes_id]
        for node in children:
            if not node:
                continue
179
            node.parent = instance
baltery's avatar
baltery 已提交
180 181 182
        return Response("OK")


183 184
class NodeAddAssetsApi(generics.UpdateAPIView):
    serializer_class = serializers.NodeAssetsSerializer
baltery's avatar
baltery 已提交
185
    queryset = Node.objects.all()
186 187 188 189 190 191 192 193 194 195 196
    permission_classes = (IsSuperUser,)
    instance = None

    def perform_update(self, serializer):
        assets = serializer.validated_data.get('assets')
        instance = self.get_object()
        instance.assets.add(*tuple(assets))


class NodeRemoveAssetsApi(generics.UpdateAPIView):
    serializer_class = serializers.NodeAssetsSerializer
baltery's avatar
baltery 已提交
197
    queryset = Node.objects.all()
198 199 200 201 202 203
    permission_classes = (IsSuperUser,)
    instance = None

    def perform_update(self, serializer):
        assets = serializer.validated_data.get('assets')
        instance = self.get_object()
baltery's avatar
baltery 已提交
204 205
        if instance != Node.root():
            instance.assets.remove(*tuple(assets))
206 207 208
        else:
            assets = [asset for asset in assets if asset.nodes.count() > 1]
            instance.assets.remove(*tuple(assets))
209 210


baltery's avatar
baltery 已提交
211 212
class NodeReplaceAssetsApi(generics.UpdateAPIView):
    serializer_class = serializers.NodeAssetsSerializer
baltery's avatar
baltery 已提交
213
    queryset = Node.objects.all()
baltery's avatar
baltery 已提交
214 215 216 217 218 219 220 221 222 223
    permission_classes = (IsSuperUser,)
    instance = None

    def perform_update(self, serializer):
        assets = serializer.validated_data.get('assets')
        instance = self.get_object()
        for asset in assets:
            asset.nodes.set([instance])


224 225 226 227 228 229 230 231
class RefreshNodeHardwareInfoApi(APIView):
    permission_classes = (IsSuperUser,)
    model = Node

    def get(self, request, *args, **kwargs):
        node_id = kwargs.get('pk')
        node = get_object_or_404(self.model, id=node_id)
        assets = node.assets.all()
baltery's avatar
baltery 已提交
232
        task_name = _("更新节点资产硬件信息: {}".format(node.name))
233 234
        task = update_assets_hardware_info_util.delay(assets, task_name=task_name)
        return Response({"task": task.id})
235 236 237 238 239 240 241 242 243 244


class TestNodeConnectiveApi(APIView):
    permission_classes = (IsSuperUser,)
    model = Node

    def get(self, request, *args, **kwargs):
        node_id = kwargs.get('pk')
        node = get_object_or_404(self.model, id=node_id)
        assets = node.assets.all()
baltery's avatar
baltery 已提交
245
        task_name = _("测试节点下资产是否可连接: {}".format(node.name))
246 247
        task = test_asset_connectability_util.delay(assets, task_name=task_name)
        return Response({"task": task.id})