1 # Copyright (C) 2021 Wind River Systems, Inc.
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
7 # http://www.apache.org/licenses/LICENSE-2.0
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
15 # pylint: disable=unused-argument
16 from __future__ import annotations
17 from o2dms.domain.states import NfDeploymentState
18 # from o2common.service import messagebus
19 from o2dms.domain.dms import NfDeployment, NfDeploymentDesc
20 from o2dms.domain import commands
21 from typing import Callable
23 from o2dms.domain.exceptions import NfdeploymentNotFoundError
24 from o2dms.domain import events
25 from o2common.service.unit_of_work import AbstractUnitOfWork
26 from helm_sdk import Helm
27 from ruamel import yaml
29 from o2common.config import config
30 from retry import retry
32 # from . import unit_of_work
34 from o2common.helper import o2logging
35 logger = o2logging.get_logger(__name__)
36 LOCAL_HELM_BIN = config.get_helm_cli()
37 K8S_KUBECONFIG, K8S_APISERVER, K8S_TOKEN = \
38 config.get_k8s_api_endpoint()
41 def publish_nfdeployment_state_change(
42 event: events.NfDeploymentStateChanged,
45 publish("NfDeploymentStateChanged", event)
47 "published NfDeploymentStateChanged: {}, state from {} to {}".format(
48 event.NfDeploymentId, event.FromState, event.ToState))
51 def handle_nfdeployment_statechanged(
52 cmd: commands.HandleNfDeploymentStateChanged,
53 uow: AbstractUnitOfWork
55 if cmd.FromState == NfDeploymentState.Initial:
56 if cmd.ToState == NfDeploymentState.Installing:
57 cmd2 = commands.InstallNfDeployment(cmd.NfDeploymentId)
58 install_nfdeployment(cmd2, uow)
60 logger.debug("Not insterested state change: {}".format(cmd))
61 elif cmd.FromState == NfDeploymentState.Installed \
62 or cmd.FromState == NfDeploymentState.Installing \
63 or cmd.FromState == NfDeploymentState.Updating \
64 or cmd.FromState == NfDeploymentState.Abnormal:
66 if cmd.ToState == NfDeploymentState.Uninstalling:
67 cmd2 = commands.UninstallNfDeployment(cmd.NfDeploymentId)
68 uninstall_nfdeployment(cmd2, uow)
70 logger.debug("Not insterested state change: {}".format(cmd))
71 elif cmd.FromState == NfDeploymentState.Initial \
72 or cmd.FromState == NfDeploymentState.Abnormal:
74 if cmd.ToState == NfDeploymentState.Deleting:
75 # cmd2 = commands.UninstallNfDeployment(cmd.NfDeploymentId)
76 # uninstall_nfdeployment(cmd2, uow)
77 cmd2 = commands.DeleteNfDeployment(cmd.NfDeploymentId)
78 delete_nfdeployment(cmd2, uow)
80 logger.debug("Not insterested state change: {}".format(cmd))
82 logger.debug("Not insterested state change: {}".format(cmd))
87 (NfdeploymentNotFoundError),
89 delay=2, max_delay=10000, backoff=1)
90 def _retry_get_nfdeployment(
91 cmd: commands.InstallNfDeployment,
92 uow: AbstractUnitOfWork):
93 nfdeployment: NfDeployment = uow.nfdeployments.get(
95 if nfdeployment is None:
96 raise NfdeploymentNotFoundError(
97 "Cannot find NfDeployment: {}".format(
102 def install_nfdeployment(
103 cmd: commands.InstallNfDeployment,
104 uow: AbstractUnitOfWork
106 logger.info("install with NfDeploymentId: {}".format(
108 nfdeployment: NfDeployment = _retry_get_nfdeployment(cmd, uow)
109 if nfdeployment is None:
110 raise Exception("Cannot find NfDeployment: {}".format(
112 # get nfdeploymentdescriptor by descriptorId
113 desc: NfDeploymentDesc = uow.nfdeployment_descs.get(
114 nfdeployment.descriptorId)
117 "Cannot find NfDeploymentDescriptor:{} for NfDeployment:{}".format(
118 nfdeployment.descriptorId, nfdeployment.id
121 nfdeployment.set_state(NfDeploymentState.Installing)
124 repourl = desc.artifactRepoUrl
125 helm = Helm(logger, LOCAL_HELM_BIN, environment_variables={})
128 repolist = helm.repo_list()
129 for repo in repolist:
130 if repo['url'] == repourl:
131 repoName = repo['name']
138 repoName = "repo4{}".format(nfdeployment.name)
139 logger.debug("Trying to add repo:{}".format(repourl))
140 helm.repo_add(repoName, repourl)
141 helm.repo_update(None)
143 repolist = helm.repo_list()
144 logger.debug('repo list:{}'.format(repolist))
146 # helm install name chart
147 values_file_path = '/tmp/override_{}.yaml'.format(nfdeployment.name)
148 if len(desc.inputParams) > 0:
149 logger.info("dump override yaml:{}".format(values_file_path))
150 values = json.loads(desc.inputParams)
151 _create_values_file(values_file_path, values)
153 values_file_path = None
155 logger.debug('Try to helm install {}/{} {} -f {}'.format(
156 repoName, nfdeployment.name, desc.artifactName, values_file_path))
157 tokens = desc.artifactName.split(':')
158 chartname = tokens[0]
160 # if (len(tokens) > 1):
161 # myflags = {"name": "version", "value": tokens[1]}
162 result = helm.install(
163 nfdeployment.name, "{}/{}".format(repoName, chartname), flags=myflags,
164 values_file=values_file_path, kubeconfig=K8S_KUBECONFIG,
165 token=K8S_TOKEN, apiserver=K8S_APISERVER)
166 logger.debug('result: {}'.format(result))
170 entity: NfDeployment = uow.nfdeployments.get(cmd.NfDeploymentId)
172 entity.set_state(NfDeploymentState.Installed)
173 entity.transit_state(NfDeploymentState.Installed)
177 def _create_values_file(filePath: str, content: dict):
178 with open(filePath, "w", encoding="utf-8") as f:
179 yaml.dump(content, f, Dumper=yaml.RoundTripDumper)
182 def uninstall_nfdeployment(
183 cmd: commands.UninstallNfDeployment,
184 uow: AbstractUnitOfWork
186 logger.info("uninstall with NfDeploymentId: {}".format(
188 nfdeployment: NfDeployment = _retry_get_nfdeployment(cmd, uow)
189 if nfdeployment is None:
190 raise Exception("Cannot find NfDeployment: {}".format(
192 # get nfdeploymentdescriptor by descriptorId
193 desc: NfDeploymentDesc = uow.nfdeployment_descs.get(
194 nfdeployment.descriptorId)
197 "Cannot find NfDeploymentDescriptor:{} for NfDeployment:{}".format(
198 nfdeployment.descriptorId, nfdeployment.id
202 entity: NfDeployment = uow.nfdeployments.get(cmd.NfDeploymentId)
204 entity.set_state(NfDeploymentState.Uninstalling)
207 helm = Helm(logger, LOCAL_HELM_BIN, environment_variables={})
209 logger.debug('Try to helm del {}'.format(
212 # if (len(tokens) > 1):
213 # myflags = {"name": "version", "value": tokens[1]}
214 result = helm.uninstall(
215 nfdeployment.name, flags=myflags,
216 kubeconfig=K8S_KUBECONFIG,
217 token=K8S_TOKEN, apiserver=K8S_APISERVER)
218 logger.debug('result: {}'.format(result))
223 entity: NfDeployment = uow.nfdeployments.get(cmd.NfDeploymentId)
225 entity.set_state(NfDeploymentState.Initial)
226 entity.transit_state(NfDeploymentState.Deleting)
227 # uow.nfdeployments.update(
228 # cmd.NfDeploymentId, status=NfDeploymentState.Initial)
232 def delete_nfdeployment(
233 cmd: commands.UninstallNfDeployment,
234 uow: AbstractUnitOfWork
236 logger.info("delete with NfDeploymentId: {}".format(
239 # nfdeployment: NfDeployment = _retry_get_nfdeployment(cmd, uow)
241 uow.nfdeployments.delete(cmd.NfDeploymentId)