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)
59 elif cmd.ToState == NfDeploymentState.Deleting:
60 cmd2 = commands.DeleteNfDeployment(cmd.NfDeploymentId)
61 delete_nfdeployment(cmd2, uow)
63 logger.debug("Not insterested state change: {}".format(cmd))
64 elif cmd.FromState == NfDeploymentState.Installed \
65 or cmd.FromState == NfDeploymentState.Installing \
66 or cmd.FromState == NfDeploymentState.Updating \
67 or cmd.FromState == NfDeploymentState.Abnormal:
69 if cmd.ToState == NfDeploymentState.Uninstalling:
70 cmd2 = commands.UninstallNfDeployment(cmd.NfDeploymentId)
71 uninstall_nfdeployment(cmd2, uow)
73 logger.debug("Not insterested state change: {}".format(cmd))
74 elif cmd.FromState == NfDeploymentState.Abnormal:
75 if cmd.ToState == NfDeploymentState.Deleting:
76 # cmd2 = commands.UninstallNfDeployment(cmd.NfDeploymentId)
77 # uninstall_nfdeployment(cmd2, uow)
78 cmd2 = commands.DeleteNfDeployment(cmd.NfDeploymentId)
79 delete_nfdeployment(cmd2, uow)
81 logger.debug("Not insterested state change: {}".format(cmd))
83 logger.debug("Not insterested state change: {}".format(cmd))
88 (NfdeploymentNotFoundError),
90 delay=2, max_delay=10000, backoff=1)
91 def _retry_get_nfdeployment(
92 cmd: commands.InstallNfDeployment,
93 uow: AbstractUnitOfWork):
94 nfdeployment: NfDeployment = uow.nfdeployments.get(
96 if nfdeployment is None:
97 raise NfdeploymentNotFoundError(
98 "Cannot find NfDeployment: {}".format(
103 def install_nfdeployment(
104 cmd: commands.InstallNfDeployment,
105 uow: AbstractUnitOfWork
107 logger.info("install with NfDeploymentId: {}".format(
109 nfdeployment: NfDeployment = _retry_get_nfdeployment(cmd, uow)
110 if nfdeployment is None:
111 raise Exception("Cannot find NfDeployment: {}".format(
113 # get nfdeploymentdescriptor by descriptorId
114 desc: NfDeploymentDesc = uow.nfdeployment_descs.get(
115 nfdeployment.descriptorId)
118 "Cannot find NfDeploymentDescriptor:{} for NfDeployment:{}".format(
119 nfdeployment.descriptorId, nfdeployment.id
122 nfdeployment.set_state(NfDeploymentState.Installing)
125 repourl = desc.artifactRepoUrl
126 helm = Helm(logger, LOCAL_HELM_BIN, environment_variables={})
129 repolist = helm.repo_list()
130 for repo in repolist:
131 if repo['url'] == repourl:
132 repoName = repo['name']
139 repoName = "repo4{}".format(nfdeployment.name)
140 logger.debug("Trying to add repo:{}".format(repourl))
141 helm.repo_add(repoName, repourl)
142 helm.repo_update(None)
144 repolist = helm.repo_list()
145 logger.debug('repo list:{}'.format(repolist))
147 # helm install name chart
148 values_file_path = '/tmp/override_{}.yaml'.format(nfdeployment.name)
149 if len(desc.inputParams) > 0:
150 logger.info("dump override yaml:{}".format(values_file_path))
151 values = json.loads(desc.inputParams)
152 _create_values_file(values_file_path, values)
154 values_file_path = None
156 logger.debug('Try to helm install {}/{} {} -f {}'.format(
157 repoName, nfdeployment.name, desc.artifactName, values_file_path))
158 tokens = desc.artifactName.split(':')
159 chartname = tokens[0]
161 # if (len(tokens) > 1):
162 # myflags = {"name": "version", "value": tokens[1]}
163 result = helm.install(
164 nfdeployment.name, "{}/{}".format(repoName, chartname), flags=myflags,
165 values_file=values_file_path, kubeconfig=K8S_KUBECONFIG,
166 token=K8S_TOKEN, apiserver=K8S_APISERVER)
167 logger.debug('result: {}'.format(result))
171 entity: NfDeployment = uow.nfdeployments.get(cmd.NfDeploymentId)
173 entity.set_state(NfDeploymentState.Installed)
174 entity.transit_state(NfDeploymentState.Installed)
178 def _create_values_file(filePath: str, content: dict):
179 with open(filePath, "w", encoding="utf-8") as f:
180 yaml.dump(content, f, Dumper=yaml.RoundTripDumper)
183 def uninstall_nfdeployment(
184 cmd: commands.UninstallNfDeployment,
185 uow: AbstractUnitOfWork
187 logger.info("uninstall with NfDeploymentId: {}".format(
189 nfdeployment: NfDeployment = _retry_get_nfdeployment(cmd, uow)
190 if nfdeployment is None:
191 raise Exception("Cannot find NfDeployment: {}".format(
193 # get nfdeploymentdescriptor by descriptorId
194 desc: NfDeploymentDesc = uow.nfdeployment_descs.get(
195 nfdeployment.descriptorId)
198 "Cannot find NfDeploymentDescriptor:{} for NfDeployment:{}".format(
199 nfdeployment.descriptorId, nfdeployment.id
203 entity: NfDeployment = uow.nfdeployments.get(cmd.NfDeploymentId)
205 entity.set_state(NfDeploymentState.Uninstalling)
208 helm = Helm(logger, LOCAL_HELM_BIN, environment_variables={})
210 logger.debug('Try to helm del {}'.format(
213 # if (len(tokens) > 1):
214 # myflags = {"name": "version", "value": tokens[1]}
215 result = helm.uninstall(
216 nfdeployment.name, flags=myflags,
217 kubeconfig=K8S_KUBECONFIG,
218 token=K8S_TOKEN, apiserver=K8S_APISERVER)
219 logger.debug('result: {}'.format(result))
224 entity: NfDeployment = uow.nfdeployments.get(cmd.NfDeploymentId)
226 entity.set_state(NfDeploymentState.Initial)
227 entity.transit_state(NfDeploymentState.Deleting)
228 # uow.nfdeployments.update(
229 # cmd.NfDeploymentId, status=NfDeploymentState.Initial)
233 def delete_nfdeployment(
234 cmd: commands.UninstallNfDeployment,
235 uow: AbstractUnitOfWork
237 logger.info("delete with NfDeploymentId: {}".format(
240 # nfdeployment: NfDeployment = _retry_get_nfdeployment(cmd, uow)
242 uow.nfdeployments.delete(cmd.NfDeploymentId)