Test Failed
Pull Request — master (#64)
by
unknown
02:28
created

MaintenanceController.start_window()   A

Complexity

Conditions 1

Size

Total Lines 12
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 9
nop 2
dl 0
loc 12
rs 9.95
c 0
b 0
f 0
1
"""MaintenanceController."""
2
3
# pylint: disable=invalid-name
4
from datetime import datetime
5
import os
6
import pytz
7
from typing import Optional
8
9
from bson.codec_options import CodecOptions
10
import pymongo
11
from pymongo.errors import AutoReconnect
12
from tenacity import retry_if_exception_type, stop_after_attempt, wait_random
13
from werkzeug.exceptions import BadRequest
14
15
from kytos.core import log
16
from kytos.core.db import Mongo
17
from kytos.core.retry import before_sleep, for_all_methods, retries
18
from napps.kytos.maintenance.models import (
19
    MaintenanceWindow,
20
    MaintenanceWindows,
21
    MaintenanceID,
22
    Status,
23
)
24
25
26
@for_all_methods(
27
    retries,
28
    stop=stop_after_attempt(
29
        int(os.environ.get("MONGO_AUTO_RETRY_STOP_AFTER_ATTEMPT", 3))
30
    ),
31
    wait=wait_random(
32
        min=int(os.environ.get("MONGO_AUTO_RETRY_WAIT_RANDOM_MIN", 0.1)),
33
        max=int(os.environ.get("MONGO_AUTO_RETRY_WAIT_RANDOM_MAX", 1)),
34
    ),
35
    before_sleep=before_sleep,
36
    retry=retry_if_exception_type((AutoReconnect,)),
37
)
38
class MaintenanceController:
39
    """MaintenanceController."""
40
41
    def __init__(self, get_mongo=lambda: Mongo()) -> None:
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable Mongo does not seem to be defined.
Loading history...
42
        """Constructor of MaintenanceController."""
43
        self.mongo = get_mongo()
44
        self.db_client = self.mongo.client
45
        self.db = self.db_client[self.mongo.db_name]
46
        self.windows = self.db['maintenance.windows'].with_options(
47
            codec_options=CodecOptions(
48
                tz_aware=True,
49
            )
50
        )
51
52
    def bootstrap_indexes(self) -> None:
53
        """Bootstrap all maintenance related indexes."""
54
        unique_index_tuples = [
55
            ("maintenance.windows", [("id", pymongo.ASCENDING)]),
56
        ]
57
        for collection, keys in unique_index_tuples:
58
            if self.mongo.bootstrap_index(collection, keys, unique=True):
59
                log.info(
60
                    f"Created DB unique index {keys}, collection: {collection})"
61
                )
62
63
    def insert_window(self, window: MaintenanceWindow):
64
        now = datetime.now(pytz.utc)
65
        self.windows.insert_one({
66
                    **window.dict(exclude={'inserted_at', 'updated_at'}),
67
                    'inserted_at': now,
68
                    'updated_at': now,
69
        })
70
71
72
    def update_window(self, window: MaintenanceWindow):
73
        self.windows.update_one(
74
            {'id': window.id},
75
            [{
76
                '$set': {
77
                    **window.dict(exclude={'inserted_at', 'updated_at'}),
78
                    'updated_at': '$$NOW',
79
                },
80
            }],
81
        )
82
83
    def get_window(self, mw_id: MaintenanceID) -> Optional[MaintenanceWindow]:
84
        window = self.windows.find_one(
85
            {'id': mw_id},
86
            {'_id': False},
87
        )
88
        if window is None:
89
            return None
90
        else:
91
            return MaintenanceWindow.construct(**window)
92
93
    def start_window(self, mw_id: MaintenanceID) -> MaintenanceWindow:
94
        window = self.windows.find_one_and_update(
95
            {'id': mw_id},
96
            [{
97
                '$set': {
98
                    'status': Status.RUNNING,
99
                    'last_modified': '$$NOW',
100
                },
101
            }],
102
            {'_id': False},
103
        )
104
        return MaintenanceWindow.construct(**window)
105
106
    def end_window(self, mw_id: MaintenanceID) -> MaintenanceWindow:
107
        window = self.windows.find_one_and_update(
108
            {'id': mw_id},
109
            [{
110
                '$set': {
111
                    'status': Status.FINISHED,
112
                    'last_modified': '$$NOW',
113
                },
114
            }],
115
            {'_id': False},
116
        )
117
        return MaintenanceWindow.construct(**window)
118
119
    def get_windows(self) -> MaintenanceWindows:
120
        windows = self.windows.find(projection={'_id': False})
121
        return MaintenanceWindows.construct(
122
            __root__ = [MaintenanceWindow.construct(**window) for window in windows]
123
        )
124
125
    def remove_window(self, mw_id: MaintenanceID):
126
        self.windows.delete_one({'id': mw_id})