blob: 048ccff865750ef1e011b5f2f13affd09b3f93cc [file] [log] [blame]
tierno59d22d22018-09-25 18:10:19 +02001# -*- coding: utf-8 -*-
2
tierno2e215512018-11-28 09:37:52 +00003##
4# Copyright 2018 Telefonica S.A.
5#
6# Licensed under the Apache License, Version 2.0 (the "License"); you may
7# not use this file except in compliance with the License. You may obtain
8# a copy of the License at
9#
10# http://www.apache.org/licenses/LICENSE-2.0
11#
12# Unless required by applicable law or agreed to in writing, software
13# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
15# License for the specific language governing permissions and limitations
16# under the License.
17##
tierno59d22d22018-09-25 18:10:19 +020018
19from collections import OrderedDict
20from osm_common.dbbase import DbException
21
22__author__ = "Alfonso Tierno"
23
24
25class LcmException(Exception):
26 pass
27
28
tiernof578e552018-11-08 19:07:20 +010029class LcmExceptionNoMgmtIP(LcmException):
30 pass
31
32
tierno59d22d22018-09-25 18:10:19 +020033def versiontuple(v):
tierno27246d82018-09-27 15:59:09 +020034 """utility for compare dot separate versions. Fills with zeros to proper number comparison
35 package version will be something like 4.0.1.post11+gb3f024d.dirty-1. Where 4.0.1 is the git tag, postXX is the
36 number of commits from this tag, and +XXXXXXX is the git commit short id. Total length is 16 with until 999 commits
37 """
tierno59d22d22018-09-25 18:10:19 +020038 filled = []
39 for point in v.split("."):
tierno27246d82018-09-27 15:59:09 +020040 filled.append(point.zfill(16))
tierno59d22d22018-09-25 18:10:19 +020041 return tuple(filled)
42
43
44class TaskRegistry:
45 """
46 Implements a registry of task needed for later cancelation, look for related tasks that must be completed before
47 etc. It stores a four level dict
48 First level is the topic, ns, vim_account, sdn
49 Second level is the _id
50 Third level is the operation id
51 Fourth level is a descriptive name, the value is the task class
52 """
53
54 def __init__(self):
55 self.task_registry = {
56 "ns": {},
Felipe Vicensc2033f22018-11-15 15:09:58 +010057 "nsi": {},
tierno59d22d22018-09-25 18:10:19 +020058 "vim_account": {},
59 "sdn": {},
60 }
61
62 def register(self, topic, _id, op_id, task_name, task):
63 """
64 Register a new task
Felipe Vicensc2033f22018-11-15 15:09:58 +010065 :param topic: Can be "ns", "nsi", "vim_account", "sdn"
tierno59d22d22018-09-25 18:10:19 +020066 :param _id: _id of the related item
67 :param op_id: id of the operation of the related item
68 :param task_name: Task descriptive name, as create, instantiate, terminate. Must be unique in this op_id
69 :param task: Task class
70 :return: none
71 """
72 if _id not in self.task_registry[topic]:
73 self.task_registry[topic][_id] = OrderedDict()
74 if op_id not in self.task_registry[topic][_id]:
75 self.task_registry[topic][_id][op_id] = {task_name: task}
76 else:
77 self.task_registry[topic][_id][op_id][task_name] = task
78 # print("registering task", topic, _id, op_id, task_name, task)
79
80 def remove(self, topic, _id, op_id, task_name=None):
81 """
82 When task is ended, it should removed. It ignores missing tasks
Felipe Vicensc2033f22018-11-15 15:09:58 +010083 :param topic: Can be "ns", "nsi", "vim_account", "sdn"
tierno59d22d22018-09-25 18:10:19 +020084 :param _id: _id of the related item
85 :param op_id: id of the operation of the related item
86 :param task_name: Task descriptive name. If note it deletes all
87 :return:
88 """
89 if not self.task_registry[topic].get(_id) or not self.task_registry[topic][_id].get(op_id):
90 return
91 if not task_name:
92 # print("deleting tasks", topic, _id, op_id, self.task_registry[topic][_id][op_id])
93 del self.task_registry[topic][_id][op_id]
94 elif task_name in self.task_registry[topic][_id][op_id]:
95 # print("deleting tasks", topic, _id, op_id, task_name, self.task_registry[topic][_id][op_id][task_name])
96 del self.task_registry[topic][_id][op_id][task_name]
97 if not self.task_registry[topic][_id][op_id]:
98 del self.task_registry[topic][_id][op_id]
99 if not self.task_registry[topic][_id]:
100 del self.task_registry[topic][_id]
101
102 def lookfor_related(self, topic, _id, my_op_id=None):
103 task_list = []
104 task_name_list = []
105 if _id not in self.task_registry[topic]:
106 return "", task_name_list
107 for op_id in reversed(self.task_registry[topic][_id]):
108 if my_op_id:
109 if my_op_id == op_id:
110 my_op_id = None # so that the next task is taken
111 continue
112
113 for task_name, task in self.task_registry[topic][_id][op_id].items():
114 task_list.append(task)
115 task_name_list.append(task_name)
116 break
117 return ", ".join(task_name_list), task_list
118
119 def cancel(self, topic, _id, target_op_id=None, target_task_name=None):
120 """
Felipe Vicensc2033f22018-11-15 15:09:58 +0100121 Cancel all active tasks of a concrete ns, nsi, vim_account, sdn identified for _id. If op_id is supplied only
122 this is cancelled, and the same with task_name
tierno59d22d22018-09-25 18:10:19 +0200123 """
124 if not self.task_registry[topic].get(_id):
125 return
126 for op_id in reversed(self.task_registry[topic][_id]):
127 if target_op_id and target_op_id != op_id:
128 continue
129 for task_name, task in self.task_registry[topic][_id][op_id].items():
130 if target_task_name and target_task_name != task_name:
131 continue
132 # result =
133 task.cancel()
134 # if result:
135 # self.logger.debug("{} _id={} order_id={} task={} cancelled".format(topic, _id, op_id, task_name))
136
137
138class LcmBase:
139
140 def __init__(self, db, msg, fs, logger):
141 """
142
143 :param db: database connection
144 """
145 self.db = db
146 self.msg = msg
147 self.fs = fs
148 self.logger = logger
149
150 def update_db_2(self, item, _id, _desc):
151 """
152 Updates database with _desc information. Upon success _desc is cleared
153 :param item:
154 :param _id:
155 :param _desc:
156 :return:
157 """
158 if not _desc:
159 return
160 try:
161 self.db.set_one(item, {"_id": _id}, _desc)
162 _desc.clear()
163 except DbException as e:
164 self.logger.error("Updating {} _id={} with '{}'. Error: {}".format(item, _id, _desc, e))