blob: 273edc18e06e286c0e24592a566f8f583954bdcd [file] [log] [blame]
tiernoc0e42e22018-05-11 11:36:10 +02001#!/usr/bin/python3
2# -*- coding: utf-8 -*-
3
tierno2e215512018-11-28 09:37:52 +00004##
5# Copyright 2018 Telefonica S.A.
6#
7# Licensed under the Apache License, Version 2.0 (the "License"); you may
8# not use this file except in compliance with the License. You may obtain
9# a copy of the License at
10#
11# http://www.apache.org/licenses/LICENSE-2.0
12#
13# Unless required by applicable law or agreed to in writing, software
14# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
16# License for the specific language governing permissions and limitations
17# under the License.
18##
19
quilesj7e13aeb2019-10-08 13:34:55 +020020
21# DEBUG WITH PDB
22import os
23import pdb
24
tiernoc0e42e22018-05-11 11:36:10 +020025import asyncio
26import yaml
tierno275411e2018-05-16 14:33:32 +020027import logging
28import logging.handlers
29import getopt
tierno275411e2018-05-16 14:33:32 +020030import sys
tierno59d22d22018-09-25 18:10:19 +020031
bravof73bac502021-05-11 07:38:47 -040032from osm_lcm import ns, vim_sdn, netslice
tierno69f0d382020-05-07 13:08:09 +000033from osm_lcm.ng_ro import NgRoException, NgRoClient
34from osm_lcm.ROclient import ROClient, ROClientException
quilesj7e13aeb2019-10-08 13:34:55 +020035
tierno94f06112020-02-11 12:38:19 +000036from time import time
tierno8069ce52019-08-28 15:34:33 +000037from osm_lcm.lcm_utils import versiontuple, LcmException, TaskRegistry, LcmExceptionExit
tiernoa4dea5a2020-01-05 16:29:30 +000038from osm_lcm import version as lcm_version, version_date as lcm_version_date
tierno8069ce52019-08-28 15:34:33 +000039
bravof922c4172020-11-24 21:21:43 -030040from osm_common import msglocal, msgkafka
tierno98768132018-09-11 12:07:21 +020041from osm_common import version as common_version
tierno59d22d22018-09-25 18:10:19 +020042from osm_common.dbbase import DbException
tiernoc0e42e22018-05-11 11:36:10 +020043from osm_common.fsbase import FsException
44from osm_common.msgbase import MsgException
bravof922c4172020-11-24 21:21:43 -030045from osm_lcm.data_utils.database.database import Database
46from osm_lcm.data_utils.filesystem.filesystem import Filesystem
aticig56b86c22022-06-29 10:43:05 +030047from osm_lcm.lcm_hc import get_health_check_file
tierno275411e2018-05-16 14:33:32 +020048from os import environ, path
tierno16427352019-04-22 11:37:36 +000049from random import choice as random_choice
tierno59d22d22018-09-25 18:10:19 +020050from n2vc import version as n2vc_version
bravof922c4172020-11-24 21:21:43 -030051import traceback
tiernoc0e42e22018-05-11 11:36:10 +020052
garciadeblas5697b8b2021-03-24 09:17:02 +010053if os.getenv("OSMLCM_PDB_DEBUG", None) is not None:
quilesj7e13aeb2019-10-08 13:34:55 +020054 pdb.set_trace()
55
tiernoc0e42e22018-05-11 11:36:10 +020056
tierno275411e2018-05-16 14:33:32 +020057__author__ = "Alfonso Tierno"
tiernoe64f7fb2019-09-11 08:55:52 +000058min_RO_version = "6.0.2"
tierno6e9d2eb2018-09-12 17:47:18 +020059min_n2vc_version = "0.0.2"
quilesj7e13aeb2019-10-08 13:34:55 +020060
tierno16427352019-04-22 11:37:36 +000061min_common_version = "0.1.19"
tierno275411e2018-05-16 14:33:32 +020062
63
tiernoc0e42e22018-05-11 11:36:10 +020064class Lcm:
65
garciadeblas5697b8b2021-03-24 09:17:02 +010066 ping_interval_pace = (
67 120 # how many time ping is send once is confirmed all is running
68 )
69 ping_interval_boot = 5 # how many time ping is sent when booting
70 cfg_logger_name = {
71 "message": "lcm.msg",
72 "database": "lcm.db",
73 "storage": "lcm.fs",
74 "tsdb": "lcm.prometheus",
75 }
tierno991e95d2020-07-21 12:41:25 +000076 # ^ contains for each section at lcm.cfg the used logger name
tiernoa9843d82018-10-24 10:44:20 +020077
tierno59d22d22018-09-25 18:10:19 +020078 def __init__(self, config_file, loop=None):
tiernoc0e42e22018-05-11 11:36:10 +020079 """
80 Init, Connect to database, filesystem storage, and messaging
81 :param config: two level dictionary with configuration. Top level should contain 'database', 'storage',
82 :return: None
83 """
tiernoc0e42e22018-05-11 11:36:10 +020084 self.db = None
85 self.msg = None
tierno16427352019-04-22 11:37:36 +000086 self.msg_admin = None
tiernoc0e42e22018-05-11 11:36:10 +020087 self.fs = None
88 self.pings_not_received = 1
tiernoc2564fe2019-01-28 16:18:56 +000089 self.consecutive_errors = 0
90 self.first_start = False
tiernoc0e42e22018-05-11 11:36:10 +020091
tiernoc0e42e22018-05-11 11:36:10 +020092 # logging
garciadeblas5697b8b2021-03-24 09:17:02 +010093 self.logger = logging.getLogger("lcm")
tierno16427352019-04-22 11:37:36 +000094 # get id
95 self.worker_id = self.get_process_id()
tiernoc0e42e22018-05-11 11:36:10 +020096 # load configuration
97 config = self.read_config_file(config_file)
98 self.config = config
aticig56b86c22022-06-29 10:43:05 +030099 self.health_check_file = get_health_check_file(self.config)
tierno744303e2020-01-13 16:46:31 +0000100 self.config["ro_config"] = {
tierno69f0d382020-05-07 13:08:09 +0000101 "ng": config["RO"].get("ng", False),
102 "uri": config["RO"].get("uri"),
tierno750b2452018-05-17 16:39:29 +0200103 "tenant": config.get("tenant", "osm"),
tierno69f0d382020-05-07 13:08:09 +0000104 "logger_name": "lcm.roclient",
105 "loglevel": config["RO"].get("loglevel", "ERROR"),
tiernoc0e42e22018-05-11 11:36:10 +0200106 }
tierno69f0d382020-05-07 13:08:09 +0000107 if not self.config["ro_config"]["uri"]:
garciadeblas5697b8b2021-03-24 09:17:02 +0100108 self.config["ro_config"]["uri"] = "http://{}:{}/".format(
109 config["RO"]["host"], config["RO"]["port"]
110 )
111 elif (
112 "/ro" in self.config["ro_config"]["uri"][-4:]
113 or "/openmano" in self.config["ro_config"]["uri"][-10:]
114 ):
tierno2357f4e2020-10-19 16:38:59 +0000115 # uri ends with '/ro', '/ro/', '/openmano', '/openmano/'
116 index = self.config["ro_config"]["uri"][-1].rfind("/")
garciadeblas5697b8b2021-03-24 09:17:02 +0100117 self.config["ro_config"]["uri"] = self.config["ro_config"]["uri"][index + 1]
tiernoc0e42e22018-05-11 11:36:10 +0200118
tierno59d22d22018-09-25 18:10:19 +0200119 self.loop = loop or asyncio.get_event_loop()
garciadeblas5697b8b2021-03-24 09:17:02 +0100120 self.ns = (
121 self.netslice
122 ) = (
123 self.vim
124 ) = self.wim = self.sdn = self.k8scluster = self.vca = self.k8srepo = None
tiernoc0e42e22018-05-11 11:36:10 +0200125
126 # logging
garciadeblas5697b8b2021-03-24 09:17:02 +0100127 log_format_simple = (
128 "%(asctime)s %(levelname)s %(name)s %(filename)s:%(lineno)s %(message)s"
129 )
130 log_formatter_simple = logging.Formatter(
131 log_format_simple, datefmt="%Y-%m-%dT%H:%M:%S"
132 )
tiernoc0e42e22018-05-11 11:36:10 +0200133 config["database"]["logger_name"] = "lcm.db"
134 config["storage"]["logger_name"] = "lcm.fs"
135 config["message"]["logger_name"] = "lcm.msg"
tierno86aa62f2018-08-20 11:57:04 +0000136 if config["global"].get("logfile"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100137 file_handler = logging.handlers.RotatingFileHandler(
138 config["global"]["logfile"], maxBytes=100e6, backupCount=9, delay=0
139 )
tiernoc0e42e22018-05-11 11:36:10 +0200140 file_handler.setFormatter(log_formatter_simple)
141 self.logger.addHandler(file_handler)
tierno86aa62f2018-08-20 11:57:04 +0000142 if not config["global"].get("nologging"):
tiernoc0e42e22018-05-11 11:36:10 +0200143 str_handler = logging.StreamHandler()
144 str_handler.setFormatter(log_formatter_simple)
145 self.logger.addHandler(str_handler)
146
147 if config["global"].get("loglevel"):
148 self.logger.setLevel(config["global"]["loglevel"])
149
150 # logging other modules
tierno991e95d2020-07-21 12:41:25 +0000151 for k1, logname in self.cfg_logger_name.items():
tiernoc0e42e22018-05-11 11:36:10 +0200152 config[k1]["logger_name"] = logname
153 logger_module = logging.getLogger(logname)
tierno86aa62f2018-08-20 11:57:04 +0000154 if config[k1].get("logfile"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100155 file_handler = logging.handlers.RotatingFileHandler(
156 config[k1]["logfile"], maxBytes=100e6, backupCount=9, delay=0
157 )
tiernoc0e42e22018-05-11 11:36:10 +0200158 file_handler.setFormatter(log_formatter_simple)
159 logger_module.addHandler(file_handler)
tierno86aa62f2018-08-20 11:57:04 +0000160 if config[k1].get("loglevel"):
tiernoc0e42e22018-05-11 11:36:10 +0200161 logger_module.setLevel(config[k1]["loglevel"])
garciadeblas5697b8b2021-03-24 09:17:02 +0100162 self.logger.critical(
163 "starting osm/lcm version {} {}".format(lcm_version, lcm_version_date)
164 )
tierno59d22d22018-09-25 18:10:19 +0200165
tiernoc0e42e22018-05-11 11:36:10 +0200166 # check version of N2VC
167 # TODO enhance with int conversion or from distutils.version import LooseVersion
168 # or with list(map(int, version.split(".")))
tierno59d22d22018-09-25 18:10:19 +0200169 if versiontuple(n2vc_version) < versiontuple(min_n2vc_version):
garciadeblas5697b8b2021-03-24 09:17:02 +0100170 raise LcmException(
171 "Not compatible osm/N2VC version '{}'. Needed '{}' or higher".format(
172 n2vc_version, min_n2vc_version
173 )
174 )
tierno59d22d22018-09-25 18:10:19 +0200175 # check version of common
tierno27246d82018-09-27 15:59:09 +0200176 if versiontuple(common_version) < versiontuple(min_common_version):
garciadeblas5697b8b2021-03-24 09:17:02 +0100177 raise LcmException(
178 "Not compatible osm/common version '{}'. Needed '{}' or higher".format(
179 common_version, min_common_version
180 )
181 )
tierno22f4f9c2018-06-11 18:53:39 +0200182
tiernoc0e42e22018-05-11 11:36:10 +0200183 try:
bravof922c4172020-11-24 21:21:43 -0300184 self.db = Database(config).instance.db
tiernoc0e42e22018-05-11 11:36:10 +0200185
bravof922c4172020-11-24 21:21:43 -0300186 self.fs = Filesystem(config).instance.fs
sousaedu40365e82021-07-26 15:24:21 +0200187 self.fs.sync()
tiernoc0e42e22018-05-11 11:36:10 +0200188
quilesj7e13aeb2019-10-08 13:34:55 +0200189 # copy message configuration in order to remove 'group_id' for msg_admin
tiernoc2564fe2019-01-28 16:18:56 +0000190 config_message = config["message"].copy()
191 config_message["loop"] = self.loop
192 if config_message["driver"] == "local":
tiernoc0e42e22018-05-11 11:36:10 +0200193 self.msg = msglocal.MsgLocal()
tiernoc2564fe2019-01-28 16:18:56 +0000194 self.msg.connect(config_message)
tierno16427352019-04-22 11:37:36 +0000195 self.msg_admin = msglocal.MsgLocal()
196 config_message.pop("group_id", None)
197 self.msg_admin.connect(config_message)
tiernoc2564fe2019-01-28 16:18:56 +0000198 elif config_message["driver"] == "kafka":
tiernoc0e42e22018-05-11 11:36:10 +0200199 self.msg = msgkafka.MsgKafka()
tiernoc2564fe2019-01-28 16:18:56 +0000200 self.msg.connect(config_message)
tierno16427352019-04-22 11:37:36 +0000201 self.msg_admin = msgkafka.MsgKafka()
202 config_message.pop("group_id", None)
203 self.msg_admin.connect(config_message)
tiernoc0e42e22018-05-11 11:36:10 +0200204 else:
garciadeblas5697b8b2021-03-24 09:17:02 +0100205 raise LcmException(
206 "Invalid configuration param '{}' at '[message]':'driver'".format(
207 config["message"]["driver"]
208 )
209 )
tiernoc0e42e22018-05-11 11:36:10 +0200210 except (DbException, FsException, MsgException) as e:
211 self.logger.critical(str(e), exc_info=True)
212 raise LcmException(str(e))
213
kuused124bfe2019-06-18 12:09:24 +0200214 # contains created tasks/futures to be able to cancel
bravof922c4172020-11-24 21:21:43 -0300215 self.lcm_tasks = TaskRegistry(self.worker_id, self.logger)
kuused124bfe2019-06-18 12:09:24 +0200216
tierno22f4f9c2018-06-11 18:53:39 +0200217 async def check_RO_version(self):
tiernoe64f7fb2019-09-11 08:55:52 +0000218 tries = 14
219 last_error = None
220 while True:
tierno2357f4e2020-10-19 16:38:59 +0000221 ro_uri = self.config["ro_config"]["uri"]
tiernoe64f7fb2019-09-11 08:55:52 +0000222 try:
tierno2357f4e2020-10-19 16:38:59 +0000223 # try new RO, if fail old RO
224 try:
225 self.config["ro_config"]["uri"] = ro_uri + "ro"
tierno69f0d382020-05-07 13:08:09 +0000226 ro_server = NgRoClient(self.loop, **self.config["ro_config"])
tierno2357f4e2020-10-19 16:38:59 +0000227 ro_version = await ro_server.get_version()
228 self.config["ro_config"]["ng"] = True
229 except Exception:
230 self.config["ro_config"]["uri"] = ro_uri + "openmano"
tierno69f0d382020-05-07 13:08:09 +0000231 ro_server = ROClient(self.loop, **self.config["ro_config"])
tierno2357f4e2020-10-19 16:38:59 +0000232 ro_version = await ro_server.get_version()
233 self.config["ro_config"]["ng"] = False
tiernoe64f7fb2019-09-11 08:55:52 +0000234 if versiontuple(ro_version) < versiontuple(min_RO_version):
garciadeblas5697b8b2021-03-24 09:17:02 +0100235 raise LcmException(
236 "Not compatible osm/RO version '{}'. Needed '{}' or higher".format(
237 ro_version, min_RO_version
238 )
239 )
240 self.logger.info(
241 "Connected to RO version {} new-generation version {}".format(
242 ro_version, self.config["ro_config"]["ng"]
243 )
244 )
tiernoe64f7fb2019-09-11 08:55:52 +0000245 return
tierno69f0d382020-05-07 13:08:09 +0000246 except (ROClientException, NgRoException) as e:
tierno2357f4e2020-10-19 16:38:59 +0000247 self.config["ro_config"]["uri"] = ro_uri
tiernoe64f7fb2019-09-11 08:55:52 +0000248 tries -= 1
bravof922c4172020-11-24 21:21:43 -0300249 traceback.print_tb(e.__traceback__)
garciadeblas5697b8b2021-03-24 09:17:02 +0100250 error_text = "Error while connecting to RO on {}: {}".format(
251 self.config["ro_config"]["uri"], e
252 )
tiernoe64f7fb2019-09-11 08:55:52 +0000253 if tries <= 0:
254 self.logger.critical(error_text)
255 raise LcmException(error_text)
256 if last_error != error_text:
257 last_error = error_text
garciadeblas5697b8b2021-03-24 09:17:02 +0100258 self.logger.error(
259 error_text + ". Waiting until {} seconds".format(5 * tries)
260 )
tiernoe64f7fb2019-09-11 08:55:52 +0000261 await asyncio.sleep(5)
tierno22f4f9c2018-06-11 18:53:39 +0200262
tiernoc0e42e22018-05-11 11:36:10 +0200263 async def test(self, param=None):
264 self.logger.debug("Starting/Ending test task: {}".format(param))
265
tiernoc0e42e22018-05-11 11:36:10 +0200266 async def kafka_ping(self):
267 self.logger.debug("Task kafka_ping Enter")
268 consecutive_errors = 0
269 first_start = True
270 kafka_has_received = False
271 self.pings_not_received = 1
272 while True:
273 try:
tierno16427352019-04-22 11:37:36 +0000274 await self.msg_admin.aiowrite(
garciadeblas5697b8b2021-03-24 09:17:02 +0100275 "admin",
276 "ping",
277 {
278 "from": "lcm",
279 "to": "lcm",
280 "worker_id": self.worker_id,
281 "version": lcm_version,
282 },
283 self.loop,
284 )
tiernoc0e42e22018-05-11 11:36:10 +0200285 # time between pings are low when it is not received and at starting
garciadeblas5697b8b2021-03-24 09:17:02 +0100286 wait_time = (
287 self.ping_interval_boot
288 if not kafka_has_received
289 else self.ping_interval_pace
290 )
tiernoc0e42e22018-05-11 11:36:10 +0200291 if not self.pings_not_received:
292 kafka_has_received = True
293 self.pings_not_received += 1
294 await asyncio.sleep(wait_time, loop=self.loop)
295 if self.pings_not_received > 10:
296 raise LcmException("It is not receiving pings from Kafka bus")
297 consecutive_errors = 0
298 first_start = False
299 except LcmException:
300 raise
301 except Exception as e:
302 # if not first_start is the first time after starting. So leave more time and wait
303 # to allow kafka starts
304 if consecutive_errors == 8 if not first_start else 30:
garciadeblas5697b8b2021-03-24 09:17:02 +0100305 self.logger.error(
306 "Task kafka_read task exit error too many errors. Exception: {}".format(
307 e
308 )
309 )
tiernoc0e42e22018-05-11 11:36:10 +0200310 raise
311 consecutive_errors += 1
garciadeblas5697b8b2021-03-24 09:17:02 +0100312 self.logger.error(
313 "Task kafka_read retrying after Exception {}".format(e)
314 )
tierno16427352019-04-22 11:37:36 +0000315 wait_time = 2 if not first_start else 5
tiernoc0e42e22018-05-11 11:36:10 +0200316 await asyncio.sleep(wait_time, loop=self.loop)
317
gcalvinoed7f6d42018-12-14 14:44:56 +0100318 def kafka_read_callback(self, topic, command, params):
319 order_id = 1
320
321 if topic != "admin" and command != "ping":
garciadeblas5697b8b2021-03-24 09:17:02 +0100322 self.logger.debug(
323 "Task kafka_read receives {} {}: {}".format(topic, command, params)
324 )
gcalvinoed7f6d42018-12-14 14:44:56 +0100325 self.consecutive_errors = 0
326 self.first_start = False
327 order_id += 1
328 if command == "exit":
329 raise LcmExceptionExit
330 elif command.startswith("#"):
331 return
332 elif command == "echo":
333 # just for test
334 print(params)
335 sys.stdout.flush()
336 return
337 elif command == "test":
338 asyncio.Task(self.test(params), loop=self.loop)
339 return
340
341 if topic == "admin":
342 if command == "ping" and params["to"] == "lcm" and params["from"] == "lcm":
tierno16427352019-04-22 11:37:36 +0000343 if params.get("worker_id") != self.worker_id:
344 return
gcalvinoed7f6d42018-12-14 14:44:56 +0100345 self.pings_not_received = 0
tierno3e359b12019-02-03 02:29:13 +0100346 try:
aticig56b86c22022-06-29 10:43:05 +0300347 with open(self.health_check_file, "w") as f:
tierno3e359b12019-02-03 02:29:13 +0100348 f.write(str(time()))
349 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +0100350 self.logger.error(
351 "Cannot write into '{}' for healthcheck: {}".format(
aticig56b86c22022-06-29 10:43:05 +0300352 self.health_check_file, e
garciadeblas5697b8b2021-03-24 09:17:02 +0100353 )
354 )
gcalvinoed7f6d42018-12-14 14:44:56 +0100355 return
magnussonle9198bb2020-01-21 13:00:51 +0100356 elif topic == "pla":
357 if command == "placement":
358 self.ns.update_nsrs_with_pla_result(params)
359 return
calvinosanch9f9c6f22019-11-04 13:37:39 +0100360 elif topic == "k8scluster":
361 if command == "create" or command == "created":
362 k8scluster_id = params.get("_id")
363 task = asyncio.ensure_future(self.k8scluster.create(params, order_id))
garciadeblas5697b8b2021-03-24 09:17:02 +0100364 self.lcm_tasks.register(
365 "k8scluster", k8scluster_id, order_id, "k8scluster_create", task
366 )
calvinosanch9f9c6f22019-11-04 13:37:39 +0100367 return
368 elif command == "delete" or command == "deleted":
369 k8scluster_id = params.get("_id")
370 task = asyncio.ensure_future(self.k8scluster.delete(params, order_id))
garciadeblas5697b8b2021-03-24 09:17:02 +0100371 self.lcm_tasks.register(
372 "k8scluster", k8scluster_id, order_id, "k8scluster_delete", task
373 )
calvinosanch9f9c6f22019-11-04 13:37:39 +0100374 return
David Garciac1fe90a2021-03-31 19:12:02 +0200375 elif topic == "vca":
376 if command == "create" or command == "created":
377 vca_id = params.get("_id")
378 task = asyncio.ensure_future(self.vca.create(params, order_id))
379 self.lcm_tasks.register("vca", vca_id, order_id, "vca_create", task)
380 return
381 elif command == "delete" or command == "deleted":
382 vca_id = params.get("_id")
383 task = asyncio.ensure_future(self.vca.delete(params, order_id))
384 self.lcm_tasks.register("vca", vca_id, order_id, "vca_delete", task)
385 return
calvinosanch9f9c6f22019-11-04 13:37:39 +0100386 elif topic == "k8srepo":
387 if command == "create" or command == "created":
388 k8srepo_id = params.get("_id")
389 self.logger.debug("k8srepo_id = {}".format(k8srepo_id))
390 task = asyncio.ensure_future(self.k8srepo.create(params, order_id))
garciadeblas5697b8b2021-03-24 09:17:02 +0100391 self.lcm_tasks.register(
392 "k8srepo", k8srepo_id, order_id, "k8srepo_create", task
393 )
calvinosanch9f9c6f22019-11-04 13:37:39 +0100394 return
395 elif command == "delete" or command == "deleted":
396 k8srepo_id = params.get("_id")
397 task = asyncio.ensure_future(self.k8srepo.delete(params, order_id))
garciadeblas5697b8b2021-03-24 09:17:02 +0100398 self.lcm_tasks.register(
399 "k8srepo", k8srepo_id, order_id, "k8srepo_delete", task
400 )
calvinosanch9f9c6f22019-11-04 13:37:39 +0100401 return
gcalvinoed7f6d42018-12-14 14:44:56 +0100402 elif topic == "ns":
tierno307425f2020-01-26 23:35:59 +0000403 if command == "instantiate":
gcalvinoed7f6d42018-12-14 14:44:56 +0100404 # self.logger.debug("Deploying NS {}".format(nsr_id))
405 nslcmop = params
406 nslcmop_id = nslcmop["_id"]
407 nsr_id = nslcmop["nsInstanceId"]
408 task = asyncio.ensure_future(self.ns.instantiate(nsr_id, nslcmop_id))
garciadeblas5697b8b2021-03-24 09:17:02 +0100409 self.lcm_tasks.register(
410 "ns", nsr_id, nslcmop_id, "ns_instantiate", task
411 )
gcalvinoed7f6d42018-12-14 14:44:56 +0100412 return
tierno307425f2020-01-26 23:35:59 +0000413 elif command == "terminate":
gcalvinoed7f6d42018-12-14 14:44:56 +0100414 # self.logger.debug("Deleting NS {}".format(nsr_id))
415 nslcmop = params
416 nslcmop_id = nslcmop["_id"]
417 nsr_id = nslcmop["nsInstanceId"]
418 self.lcm_tasks.cancel(topic, nsr_id)
419 task = asyncio.ensure_future(self.ns.terminate(nsr_id, nslcmop_id))
420 self.lcm_tasks.register("ns", nsr_id, nslcmop_id, "ns_terminate", task)
421 return
ksaikiranr3fde2c72021-03-15 10:39:06 +0530422 elif command == "vca_status_refresh":
423 nslcmop = params
424 nslcmop_id = nslcmop["_id"]
425 nsr_id = nslcmop["nsInstanceId"]
garciadeblas5697b8b2021-03-24 09:17:02 +0100426 task = asyncio.ensure_future(
427 self.ns.vca_status_refresh(nsr_id, nslcmop_id)
428 )
429 self.lcm_tasks.register(
430 "ns", nsr_id, nslcmop_id, "ns_vca_status_refresh", task
431 )
ksaikiranr3fde2c72021-03-15 10:39:06 +0530432 return
gcalvinoed7f6d42018-12-14 14:44:56 +0100433 elif command == "action":
434 # self.logger.debug("Update NS {}".format(nsr_id))
435 nslcmop = params
436 nslcmop_id = nslcmop["_id"]
437 nsr_id = nslcmop["nsInstanceId"]
438 task = asyncio.ensure_future(self.ns.action(nsr_id, nslcmop_id))
439 self.lcm_tasks.register("ns", nsr_id, nslcmop_id, "ns_action", task)
440 return
aticigdffa6212022-04-12 15:27:53 +0300441 elif command == "update":
442 # self.logger.debug("Update NS {}".format(nsr_id))
443 nslcmop = params
444 nslcmop_id = nslcmop["_id"]
445 nsr_id = nslcmop["nsInstanceId"]
446 task = asyncio.ensure_future(self.ns.update(nsr_id, nslcmop_id))
447 self.lcm_tasks.register("ns", nsr_id, nslcmop_id, "ns_update", task)
448 return
gcalvinoed7f6d42018-12-14 14:44:56 +0100449 elif command == "scale":
450 # self.logger.debug("Update NS {}".format(nsr_id))
451 nslcmop = params
452 nslcmop_id = nslcmop["_id"]
453 nsr_id = nslcmop["nsInstanceId"]
454 task = asyncio.ensure_future(self.ns.scale(nsr_id, nslcmop_id))
455 self.lcm_tasks.register("ns", nsr_id, nslcmop_id, "ns_scale", task)
456 return
garciadeblas07f4e4c2022-06-09 09:42:58 +0200457 elif command == "heal":
458 # self.logger.debug("Healing NS {}".format(nsr_id))
459 nslcmop = params
460 nslcmop_id = nslcmop["_id"]
461 nsr_id = nslcmop["nsInstanceId"]
462 task = asyncio.ensure_future(self.ns.heal(nsr_id, nslcmop_id))
preethika.p28b0bf82022-09-23 07:36:28 +0000463 self.lcm_tasks.register("ns", nsr_id, nslcmop_id, "ns_heal", task)
garciadeblas07f4e4c2022-06-09 09:42:58 +0200464 return
elumalai80bcf1c2022-04-28 18:05:01 +0530465 elif command == "migrate":
466 nslcmop = params
467 nslcmop_id = nslcmop["_id"]
468 nsr_id = nslcmop["nsInstanceId"]
469 task = asyncio.ensure_future(self.ns.migrate(nsr_id, nslcmop_id))
470 self.lcm_tasks.register("ns", nsr_id, nslcmop_id, "ns_migrate", task)
471 return
govindarajul4ff4b512022-05-02 20:02:41 +0530472 elif command == "verticalscale":
473 nslcmop = params
474 nslcmop_id = nslcmop["_id"]
475 nsr_id = nslcmop["nsInstanceId"]
476 task = asyncio.ensure_future(self.ns.vertical_scale(nsr_id, nslcmop_id))
preethika.p28b0bf82022-09-23 07:36:28 +0000477 self.logger.debug(
478 "nsr_id,nslcmop_id,task {},{},{}".format(nsr_id, nslcmop_id, task)
479 )
480 self.lcm_tasks.register(
481 "ns", nsr_id, nslcmop_id, "ns_verticalscale", task
482 )
483 self.logger.debug(
484 "LCM task registered {},{},{} ".format(nsr_id, nslcmop_id, task)
485 )
govindarajul4ff4b512022-05-02 20:02:41 +0530486 return
gcalvinoed7f6d42018-12-14 14:44:56 +0100487 elif command == "show":
tiernoc2564fe2019-01-28 16:18:56 +0000488 nsr_id = params
gcalvinoed7f6d42018-12-14 14:44:56 +0100489 try:
490 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
garciadeblas5697b8b2021-03-24 09:17:02 +0100491 print(
492 "nsr:\n _id={}\n operational-status: {}\n config-status: {}"
493 "\n detailed-status: {}\n deploy: {}\n tasks: {}"
494 "".format(
495 nsr_id,
496 db_nsr["operational-status"],
497 db_nsr["config-status"],
498 db_nsr["detailed-status"],
499 db_nsr["_admin"]["deployed"],
500 self.lcm_ns_tasks.get(nsr_id),
501 )
502 )
gcalvinoed7f6d42018-12-14 14:44:56 +0100503 except Exception as e:
504 print("nsr {} not found: {}".format(nsr_id, e))
505 sys.stdout.flush()
506 return
507 elif command == "deleted":
508 return # TODO cleaning of task just in case should be done
garciadeblas5697b8b2021-03-24 09:17:02 +0100509 elif command in (
elumalaica7ece02022-04-12 12:47:32 +0530510 "vnf_terminated",
elumalaib9e357c2022-04-27 09:58:38 +0530511 "policy_updated",
garciadeblas5697b8b2021-03-24 09:17:02 +0100512 "terminated",
513 "instantiated",
514 "scaled",
garciadeblas07f4e4c2022-06-09 09:42:58 +0200515 "healed",
garciadeblas5697b8b2021-03-24 09:17:02 +0100516 "actioned",
aticigdffa6212022-04-12 15:27:53 +0300517 "updated",
elumalai80bcf1c2022-04-28 18:05:01 +0530518 "migrated",
govindarajul4ff4b512022-05-02 20:02:41 +0530519 "verticalscaled",
garciadeblas5697b8b2021-03-24 09:17:02 +0100520 ): # "scaled-cooldown-time"
gcalvinoed7f6d42018-12-14 14:44:56 +0100521 return
elumalaica7ece02022-04-12 12:47:32 +0530522
gcalvinoed7f6d42018-12-14 14:44:56 +0100523 elif topic == "nsi": # netslice LCM processes (instantiate, terminate, etc)
tierno307425f2020-01-26 23:35:59 +0000524 if command == "instantiate":
gcalvinoed7f6d42018-12-14 14:44:56 +0100525 # self.logger.debug("Instantiating Network Slice {}".format(nsilcmop["netsliceInstanceId"]))
526 nsilcmop = params
527 nsilcmop_id = nsilcmop["_id"] # slice operation id
528 nsir_id = nsilcmop["netsliceInstanceId"] # slice record id
garciadeblas5697b8b2021-03-24 09:17:02 +0100529 task = asyncio.ensure_future(
530 self.netslice.instantiate(nsir_id, nsilcmop_id)
531 )
532 self.lcm_tasks.register(
533 "nsi", nsir_id, nsilcmop_id, "nsi_instantiate", task
534 )
gcalvinoed7f6d42018-12-14 14:44:56 +0100535 return
tierno307425f2020-01-26 23:35:59 +0000536 elif command == "terminate":
gcalvinoed7f6d42018-12-14 14:44:56 +0100537 # self.logger.debug("Terminating Network Slice NS {}".format(nsilcmop["netsliceInstanceId"]))
538 nsilcmop = params
539 nsilcmop_id = nsilcmop["_id"] # slice operation id
540 nsir_id = nsilcmop["netsliceInstanceId"] # slice record id
541 self.lcm_tasks.cancel(topic, nsir_id)
garciadeblas5697b8b2021-03-24 09:17:02 +0100542 task = asyncio.ensure_future(
543 self.netslice.terminate(nsir_id, nsilcmop_id)
544 )
545 self.lcm_tasks.register(
546 "nsi", nsir_id, nsilcmop_id, "nsi_terminate", task
547 )
gcalvinoed7f6d42018-12-14 14:44:56 +0100548 return
549 elif command == "show":
tiernoc2564fe2019-01-28 16:18:56 +0000550 nsir_id = params
gcalvinoed7f6d42018-12-14 14:44:56 +0100551 try:
552 db_nsir = self.db.get_one("nsirs", {"_id": nsir_id})
garciadeblas5697b8b2021-03-24 09:17:02 +0100553 print(
554 "nsir:\n _id={}\n operational-status: {}\n config-status: {}"
555 "\n detailed-status: {}\n deploy: {}\n tasks: {}"
556 "".format(
557 nsir_id,
558 db_nsir["operational-status"],
559 db_nsir["config-status"],
560 db_nsir["detailed-status"],
561 db_nsir["_admin"]["deployed"],
562 self.lcm_netslice_tasks.get(nsir_id),
563 )
564 )
gcalvinoed7f6d42018-12-14 14:44:56 +0100565 except Exception as e:
566 print("nsir {} not found: {}".format(nsir_id, e))
567 sys.stdout.flush()
568 return
569 elif command == "deleted":
570 return # TODO cleaning of task just in case should be done
garciadeblas5697b8b2021-03-24 09:17:02 +0100571 elif command in (
572 "terminated",
573 "instantiated",
574 "scaled",
garciadeblas07f4e4c2022-06-09 09:42:58 +0200575 "healed",
garciadeblas5697b8b2021-03-24 09:17:02 +0100576 "actioned",
577 ): # "scaled-cooldown-time"
gcalvinoed7f6d42018-12-14 14:44:56 +0100578 return
579 elif topic == "vim_account":
580 vim_id = params["_id"]
tiernof210c1c2019-10-16 09:09:58 +0000581 if command in ("create", "created"):
tierno2357f4e2020-10-19 16:38:59 +0000582 if not self.config["ro_config"].get("ng"):
583 task = asyncio.ensure_future(self.vim.create(params, order_id))
garciadeblas5697b8b2021-03-24 09:17:02 +0100584 self.lcm_tasks.register(
585 "vim_account", vim_id, order_id, "vim_create", task
586 )
gcalvinoed7f6d42018-12-14 14:44:56 +0100587 return
calvinosanch9f9c6f22019-11-04 13:37:39 +0100588 elif command == "delete" or command == "deleted":
gcalvinoed7f6d42018-12-14 14:44:56 +0100589 self.lcm_tasks.cancel(topic, vim_id)
kuuse6a470c62019-07-10 13:52:45 +0200590 task = asyncio.ensure_future(self.vim.delete(params, order_id))
garciadeblas5697b8b2021-03-24 09:17:02 +0100591 self.lcm_tasks.register(
592 "vim_account", vim_id, order_id, "vim_delete", task
593 )
gcalvinoed7f6d42018-12-14 14:44:56 +0100594 return
595 elif command == "show":
596 print("not implemented show with vim_account")
597 sys.stdout.flush()
598 return
tiernof210c1c2019-10-16 09:09:58 +0000599 elif command in ("edit", "edited"):
tierno2357f4e2020-10-19 16:38:59 +0000600 if not self.config["ro_config"].get("ng"):
601 task = asyncio.ensure_future(self.vim.edit(params, order_id))
garciadeblas5697b8b2021-03-24 09:17:02 +0100602 self.lcm_tasks.register(
603 "vim_account", vim_id, order_id, "vim_edit", task
604 )
gcalvinoed7f6d42018-12-14 14:44:56 +0100605 return
tiernof210c1c2019-10-16 09:09:58 +0000606 elif command == "deleted":
607 return # TODO cleaning of task just in case should be done
gcalvinoed7f6d42018-12-14 14:44:56 +0100608 elif topic == "wim_account":
609 wim_id = params["_id"]
tiernof210c1c2019-10-16 09:09:58 +0000610 if command in ("create", "created"):
tierno2357f4e2020-10-19 16:38:59 +0000611 if not self.config["ro_config"].get("ng"):
612 task = asyncio.ensure_future(self.wim.create(params, order_id))
garciadeblas5697b8b2021-03-24 09:17:02 +0100613 self.lcm_tasks.register(
614 "wim_account", wim_id, order_id, "wim_create", task
615 )
gcalvinoed7f6d42018-12-14 14:44:56 +0100616 return
calvinosanch9f9c6f22019-11-04 13:37:39 +0100617 elif command == "delete" or command == "deleted":
gcalvinoed7f6d42018-12-14 14:44:56 +0100618 self.lcm_tasks.cancel(topic, wim_id)
kuuse6a470c62019-07-10 13:52:45 +0200619 task = asyncio.ensure_future(self.wim.delete(params, order_id))
garciadeblas5697b8b2021-03-24 09:17:02 +0100620 self.lcm_tasks.register(
621 "wim_account", wim_id, order_id, "wim_delete", task
622 )
gcalvinoed7f6d42018-12-14 14:44:56 +0100623 return
624 elif command == "show":
625 print("not implemented show with wim_account")
626 sys.stdout.flush()
627 return
tiernof210c1c2019-10-16 09:09:58 +0000628 elif command in ("edit", "edited"):
gcalvinoed7f6d42018-12-14 14:44:56 +0100629 task = asyncio.ensure_future(self.wim.edit(params, order_id))
garciadeblas5697b8b2021-03-24 09:17:02 +0100630 self.lcm_tasks.register(
631 "wim_account", wim_id, order_id, "wim_edit", task
632 )
gcalvinoed7f6d42018-12-14 14:44:56 +0100633 return
tiernof210c1c2019-10-16 09:09:58 +0000634 elif command == "deleted":
635 return # TODO cleaning of task just in case should be done
gcalvinoed7f6d42018-12-14 14:44:56 +0100636 elif topic == "sdn":
637 _sdn_id = params["_id"]
tiernof210c1c2019-10-16 09:09:58 +0000638 if command in ("create", "created"):
tierno2357f4e2020-10-19 16:38:59 +0000639 if not self.config["ro_config"].get("ng"):
640 task = asyncio.ensure_future(self.sdn.create(params, order_id))
garciadeblas5697b8b2021-03-24 09:17:02 +0100641 self.lcm_tasks.register(
642 "sdn", _sdn_id, order_id, "sdn_create", task
643 )
gcalvinoed7f6d42018-12-14 14:44:56 +0100644 return
calvinosanch9f9c6f22019-11-04 13:37:39 +0100645 elif command == "delete" or command == "deleted":
gcalvinoed7f6d42018-12-14 14:44:56 +0100646 self.lcm_tasks.cancel(topic, _sdn_id)
kuuse6a470c62019-07-10 13:52:45 +0200647 task = asyncio.ensure_future(self.sdn.delete(params, order_id))
gcalvinoed7f6d42018-12-14 14:44:56 +0100648 self.lcm_tasks.register("sdn", _sdn_id, order_id, "sdn_delete", task)
649 return
tiernof210c1c2019-10-16 09:09:58 +0000650 elif command in ("edit", "edited"):
gcalvinoed7f6d42018-12-14 14:44:56 +0100651 task = asyncio.ensure_future(self.sdn.edit(params, order_id))
652 self.lcm_tasks.register("sdn", _sdn_id, order_id, "sdn_edit", task)
653 return
tiernof210c1c2019-10-16 09:09:58 +0000654 elif command == "deleted":
655 return # TODO cleaning of task just in case should be done
gcalvinoed7f6d42018-12-14 14:44:56 +0100656 self.logger.critical("unknown topic {} and command '{}'".format(topic, command))
657
tiernoc0e42e22018-05-11 11:36:10 +0200658 async def kafka_read(self):
garciadeblas5697b8b2021-03-24 09:17:02 +0100659 self.logger.debug(
660 "Task kafka_read Enter with worker_id={}".format(self.worker_id)
661 )
tiernoc0e42e22018-05-11 11:36:10 +0200662 # future = asyncio.Future()
gcalvinoed7f6d42018-12-14 14:44:56 +0100663 self.consecutive_errors = 0
664 self.first_start = True
665 while self.consecutive_errors < 10:
tiernoc0e42e22018-05-11 11:36:10 +0200666 try:
garciadeblas5697b8b2021-03-24 09:17:02 +0100667 topics = (
668 "ns",
669 "vim_account",
670 "wim_account",
671 "sdn",
672 "nsi",
673 "k8scluster",
674 "vca",
675 "k8srepo",
676 "pla",
677 )
678 topics_admin = ("admin",)
tierno16427352019-04-22 11:37:36 +0000679 await asyncio.gather(
garciadeblas5697b8b2021-03-24 09:17:02 +0100680 self.msg.aioread(
681 topics, self.loop, self.kafka_read_callback, from_beginning=True
682 ),
683 self.msg_admin.aioread(
684 topics_admin,
685 self.loop,
686 self.kafka_read_callback,
687 group_id=False,
688 ),
tierno16427352019-04-22 11:37:36 +0000689 )
tiernoc0e42e22018-05-11 11:36:10 +0200690
gcalvinoed7f6d42018-12-14 14:44:56 +0100691 except LcmExceptionExit:
692 self.logger.debug("Bye!")
693 break
tiernoc0e42e22018-05-11 11:36:10 +0200694 except Exception as e:
695 # if not first_start is the first time after starting. So leave more time and wait
696 # to allow kafka starts
gcalvinoed7f6d42018-12-14 14:44:56 +0100697 if self.consecutive_errors == 8 if not self.first_start else 30:
garciadeblas5697b8b2021-03-24 09:17:02 +0100698 self.logger.error(
699 "Task kafka_read task exit error too many errors. Exception: {}".format(
700 e
701 )
702 )
tiernoc0e42e22018-05-11 11:36:10 +0200703 raise
gcalvinoed7f6d42018-12-14 14:44:56 +0100704 self.consecutive_errors += 1
garciadeblas5697b8b2021-03-24 09:17:02 +0100705 self.logger.error(
706 "Task kafka_read retrying after Exception {}".format(e)
707 )
gcalvinoed7f6d42018-12-14 14:44:56 +0100708 wait_time = 2 if not self.first_start else 5
tiernoc0e42e22018-05-11 11:36:10 +0200709 await asyncio.sleep(wait_time, loop=self.loop)
710
711 # self.logger.debug("Task kafka_read terminating")
712 self.logger.debug("Task kafka_read exit")
713
714 def start(self):
tierno22f4f9c2018-06-11 18:53:39 +0200715
716 # check RO version
717 self.loop.run_until_complete(self.check_RO_version())
718
aticig15db6142022-01-24 12:51:26 +0300719 self.ns = ns.NsLcm(self.msg, self.lcm_tasks, self.config, self.loop)
garciadeblas5697b8b2021-03-24 09:17:02 +0100720 self.netslice = netslice.NetsliceLcm(
721 self.msg, self.lcm_tasks, self.config, self.loop, self.ns
722 )
bravof922c4172020-11-24 21:21:43 -0300723 self.vim = vim_sdn.VimLcm(self.msg, self.lcm_tasks, self.config, self.loop)
724 self.wim = vim_sdn.WimLcm(self.msg, self.lcm_tasks, self.config, self.loop)
725 self.sdn = vim_sdn.SdnLcm(self.msg, self.lcm_tasks, self.config, self.loop)
garciadeblas5697b8b2021-03-24 09:17:02 +0100726 self.k8scluster = vim_sdn.K8sClusterLcm(
727 self.msg, self.lcm_tasks, self.config, self.loop
728 )
David Garciac1fe90a2021-03-31 19:12:02 +0200729 self.vca = vim_sdn.VcaLcm(self.msg, self.lcm_tasks, self.config, self.loop)
garciadeblas5697b8b2021-03-24 09:17:02 +0100730 self.k8srepo = vim_sdn.K8sRepoLcm(
731 self.msg, self.lcm_tasks, self.config, self.loop
732 )
tierno2357f4e2020-10-19 16:38:59 +0000733
garciadeblas5697b8b2021-03-24 09:17:02 +0100734 self.loop.run_until_complete(
735 asyncio.gather(self.kafka_read(), self.kafka_ping())
736 )
bravof73bac502021-05-11 07:38:47 -0400737
tiernoc0e42e22018-05-11 11:36:10 +0200738 # TODO
739 # self.logger.debug("Terminating cancelling creation tasks")
tiernoca2e16a2018-06-29 15:25:24 +0200740 # self.lcm_tasks.cancel("ALL", "create")
tiernoc0e42e22018-05-11 11:36:10 +0200741 # timeout = 200
742 # while self.is_pending_tasks():
743 # self.logger.debug("Task kafka_read terminating. Waiting for tasks termination")
744 # await asyncio.sleep(2, loop=self.loop)
745 # timeout -= 2
746 # if not timeout:
tiernoca2e16a2018-06-29 15:25:24 +0200747 # self.lcm_tasks.cancel("ALL", "ALL")
tiernoc0e42e22018-05-11 11:36:10 +0200748 self.loop.close()
749 self.loop = None
750 if self.db:
751 self.db.db_disconnect()
752 if self.msg:
753 self.msg.disconnect()
tierno16427352019-04-22 11:37:36 +0000754 if self.msg_admin:
755 self.msg_admin.disconnect()
tiernoc0e42e22018-05-11 11:36:10 +0200756 if self.fs:
757 self.fs.fs_disconnect()
758
tiernoc0e42e22018-05-11 11:36:10 +0200759 def read_config_file(self, config_file):
760 # TODO make a [ini] + yaml inside parser
761 # the configparser library is not suitable, because it does not admit comments at the end of line,
762 # and not parse integer or boolean
763 try:
tierno744303e2020-01-13 16:46:31 +0000764 # read file as yaml format
tiernoc0e42e22018-05-11 11:36:10 +0200765 with open(config_file) as f:
Luisccdc2162022-07-01 14:35:49 +0000766 conf = yaml.safe_load(f)
tierno744303e2020-01-13 16:46:31 +0000767 # Ensure all sections are not empty
garciadeblas5697b8b2021-03-24 09:17:02 +0100768 for k in (
769 "global",
770 "timeout",
771 "RO",
772 "VCA",
773 "database",
774 "storage",
775 "message",
776 ):
tierno744303e2020-01-13 16:46:31 +0000777 if not conf.get(k):
778 conf[k] = {}
779
780 # read all environ that starts with OSMLCM_
tiernoc0e42e22018-05-11 11:36:10 +0200781 for k, v in environ.items():
782 if not k.startswith("OSMLCM_"):
783 continue
tierno744303e2020-01-13 16:46:31 +0000784 subject, _, item = k[7:].lower().partition("_")
785 if not item:
tierno17a612f2018-10-23 11:30:42 +0200786 continue
tierno744303e2020-01-13 16:46:31 +0000787 if subject in ("ro", "vca"):
tierno17a612f2018-10-23 11:30:42 +0200788 # put in capital letter
tierno744303e2020-01-13 16:46:31 +0000789 subject = subject.upper()
tiernoc0e42e22018-05-11 11:36:10 +0200790 try:
tierno744303e2020-01-13 16:46:31 +0000791 if item == "port" or subject == "timeout":
792 conf[subject][item] = int(v)
tiernoc0e42e22018-05-11 11:36:10 +0200793 else:
tierno744303e2020-01-13 16:46:31 +0000794 conf[subject][item] = v
tiernoc0e42e22018-05-11 11:36:10 +0200795 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +0100796 self.logger.warning(
797 "skipping environ '{}' on exception '{}'".format(k, e)
798 )
tierno744303e2020-01-13 16:46:31 +0000799
800 # backward compatibility of VCA parameters
801
garciadeblas5697b8b2021-03-24 09:17:02 +0100802 if "pubkey" in conf["VCA"]:
803 conf["VCA"]["public_key"] = conf["VCA"].pop("pubkey")
804 if "cacert" in conf["VCA"]:
805 conf["VCA"]["ca_cert"] = conf["VCA"].pop("cacert")
806 if "apiproxy" in conf["VCA"]:
807 conf["VCA"]["api_proxy"] = conf["VCA"].pop("apiproxy")
tierno744303e2020-01-13 16:46:31 +0000808
garciadeblas5697b8b2021-03-24 09:17:02 +0100809 if "enableosupgrade" in conf["VCA"]:
810 conf["VCA"]["enable_os_upgrade"] = conf["VCA"].pop("enableosupgrade")
811 if isinstance(conf["VCA"].get("enable_os_upgrade"), str):
812 if conf["VCA"]["enable_os_upgrade"].lower() == "false":
813 conf["VCA"]["enable_os_upgrade"] = False
814 elif conf["VCA"]["enable_os_upgrade"].lower() == "true":
815 conf["VCA"]["enable_os_upgrade"] = True
tierno744303e2020-01-13 16:46:31 +0000816
garciadeblas5697b8b2021-03-24 09:17:02 +0100817 if "aptmirror" in conf["VCA"]:
818 conf["VCA"]["apt_mirror"] = conf["VCA"].pop("aptmirror")
tiernoc0e42e22018-05-11 11:36:10 +0200819
820 return conf
821 except Exception as e:
822 self.logger.critical("At config file '{}': {}".format(config_file, e))
823 exit(1)
824
tierno16427352019-04-22 11:37:36 +0000825 @staticmethod
826 def get_process_id():
827 """
828 Obtain a unique ID for this process. If running from inside docker, it will get docker ID. If not it
829 will provide a random one
830 :return: Obtained ID
831 """
832 # Try getting docker id. If fails, get pid
833 try:
834 with open("/proc/self/cgroup", "r") as f:
835 text_id_ = f.readline()
836 _, _, text_id = text_id_.rpartition("/")
garciadeblas5697b8b2021-03-24 09:17:02 +0100837 text_id = text_id.replace("\n", "")[:12]
tierno16427352019-04-22 11:37:36 +0000838 if text_id:
839 return text_id
840 except Exception:
841 pass
842 # Return a random id
garciadeblas5697b8b2021-03-24 09:17:02 +0100843 return "".join(random_choice("0123456789abcdef") for _ in range(12))
tierno16427352019-04-22 11:37:36 +0000844
tiernoc0e42e22018-05-11 11:36:10 +0200845
tierno275411e2018-05-16 14:33:32 +0200846def usage():
garciadeblas5697b8b2021-03-24 09:17:02 +0100847 print(
848 """Usage: {} [options]
quilesj7e13aeb2019-10-08 13:34:55 +0200849 -c|--config [configuration_file]: loads the configuration file (default: ./lcm.cfg)
tiernoa9843d82018-10-24 10:44:20 +0200850 --health-check: do not run lcm, but inspect kafka bus to determine if lcm is healthy
tierno275411e2018-05-16 14:33:32 +0200851 -h|--help: shows this help
garciadeblas5697b8b2021-03-24 09:17:02 +0100852 """.format(
853 sys.argv[0]
854 )
855 )
tierno750b2452018-05-17 16:39:29 +0200856 # --log-socket-host HOST: send logs to this host")
857 # --log-socket-port PORT: send logs using this port (default: 9022)")
tierno275411e2018-05-16 14:33:32 +0200858
859
garciadeblas5697b8b2021-03-24 09:17:02 +0100860if __name__ == "__main__":
quilesj7e13aeb2019-10-08 13:34:55 +0200861
tierno275411e2018-05-16 14:33:32 +0200862 try:
tierno8c16b052020-02-05 15:08:32 +0000863 # print("SYS.PATH='{}'".format(sys.path))
tierno275411e2018-05-16 14:33:32 +0200864 # load parameters and configuration
quilesj7e13aeb2019-10-08 13:34:55 +0200865 # -h
866 # -c value
867 # --config value
868 # --help
869 # --health-check
garciadeblas5697b8b2021-03-24 09:17:02 +0100870 opts, args = getopt.getopt(
871 sys.argv[1:], "hc:", ["config=", "help", "health-check"]
872 )
tierno275411e2018-05-16 14:33:32 +0200873 # TODO add "log-socket-host=", "log-socket-port=", "log-file="
874 config_file = None
875 for o, a in opts:
876 if o in ("-h", "--help"):
877 usage()
878 sys.exit()
879 elif o in ("-c", "--config"):
880 config_file = a
tiernoa9843d82018-10-24 10:44:20 +0200881 elif o == "--health-check":
tierno94f06112020-02-11 12:38:19 +0000882 from osm_lcm.lcm_hc import health_check
garciadeblas5697b8b2021-03-24 09:17:02 +0100883
aticig56b86c22022-06-29 10:43:05 +0300884 health_check(config_file, Lcm.ping_interval_pace)
tierno275411e2018-05-16 14:33:32 +0200885 # elif o == "--log-socket-port":
886 # log_socket_port = a
887 # elif o == "--log-socket-host":
888 # log_socket_host = a
889 # elif o == "--log-file":
890 # log_file = a
891 else:
892 assert False, "Unhandled option"
quilesj7e13aeb2019-10-08 13:34:55 +0200893
tierno275411e2018-05-16 14:33:32 +0200894 if config_file:
895 if not path.isfile(config_file):
garciadeblas5697b8b2021-03-24 09:17:02 +0100896 print(
897 "configuration file '{}' does not exist".format(config_file),
898 file=sys.stderr,
899 )
tierno275411e2018-05-16 14:33:32 +0200900 exit(1)
901 else:
garciadeblas5697b8b2021-03-24 09:17:02 +0100902 for config_file in (
903 __file__[: __file__.rfind(".")] + ".cfg",
904 "./lcm.cfg",
905 "/etc/osm/lcm.cfg",
906 ):
tierno275411e2018-05-16 14:33:32 +0200907 if path.isfile(config_file):
908 break
909 else:
garciadeblas5697b8b2021-03-24 09:17:02 +0100910 print(
911 "No configuration file 'lcm.cfg' found neither at local folder nor at /etc/osm/",
912 file=sys.stderr,
913 )
tierno275411e2018-05-16 14:33:32 +0200914 exit(1)
915 lcm = Lcm(config_file)
tierno3e359b12019-02-03 02:29:13 +0100916 lcm.start()
tierno22f4f9c2018-06-11 18:53:39 +0200917 except (LcmException, getopt.GetoptError) as e:
tierno275411e2018-05-16 14:33:32 +0200918 print(str(e), file=sys.stderr)
919 # usage()
920 exit(1)