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 import events
24 from o2common.service.unit_of_work import AbstractUnitOfWork
25 from helm_sdk import Helm
26 from ruamel import yaml
28 from o2common.config import config
29 from retry import retry
31 # from . import unit_of_work
33 from o2common.helper import o2logging
34 logger = o2logging.get_logger(__name__)
35 LOCAL_HELM_BIN = config.get_helm_cli()
36 K8S_KUBECONFIG, K8S_APISERVER, K8S_TOKEN = \
37 config.get_k8s_api_endpoint()
40 def publish_nfdeployment_state_change(
41 event: events.NfDeploymentStateChanged,
44 publish("NfDeploymentStateChanged", event)
46 "published NfDeploymentStateChanged: {}, state from {} to {}".format(
47 event.NfDeploymentId, event.FromState, event.ToState))
50 def handle_nfdeployment_statechanged(
51 cmd: commands.HandleNfDeploymentStateChanged,
52 uow: AbstractUnitOfWork
54 if cmd.FromState == NfDeploymentState.Initial:
55 if cmd.ToState == NfDeploymentState.Installing:
56 cmd2 = commands.InstallNfDeployment(cmd.NfDeploymentId)
57 install_nfdeployment(cmd2, uow)
59 logger.debug("Not insterested state change: {}".format(cmd))
60 elif cmd.FromState == NfDeploymentState.Installed \
61 or cmd.FromState == NfDeploymentState.Installing \
62 or cmd.FromState == NfDeploymentState.Updating \
63 or cmd.FromState == NfDeploymentState.Abnormal:
65 if cmd.ToState == NfDeploymentState.Uninstalling:
66 cmd2 = commands.UninstallNfDeployment(cmd.NfDeploymentId)
67 uninstall_nfdeployment(cmd2, uow)
69 logger.debug("Not insterested state change: {}".format(cmd))
70 elif cmd.FromState == NfDeploymentState.Initial \
71 or cmd.FromState == NfDeploymentState.Abnormal:
73 if cmd.ToState == NfDeploymentState.Deleting:
74 cmd2 = commands.UninstallNfDeployment(cmd.NfDeploymentId)
75 uninstall_nfdeployment(cmd2, uow)
76 cmd2 = commands.DeleteNfDeployment(cmd.NfDeploymentId)
77 delete_nfdeployment(cmd2, uow)
79 logger.debug("Not insterested state change: {}".format(cmd))
81 logger.debug("Not insterested state change: {}".format(cmd))
85 @retry(tries=20, max_delay=10000)
86 def _retry_get_nfdeployment(
87 cmd: commands.InstallNfDeployment,
88 uow: AbstractUnitOfWork):
89 nfdeployment: NfDeployment = uow.nfdeployments.get(
91 if nfdeployment is None:
92 raise Exception("Cannot find NfDeployment: {}".format(
97 def install_nfdeployment(
98 cmd: commands.InstallNfDeployment,
99 uow: AbstractUnitOfWork
101 logger.info("install with NfDeploymentId: {}".format(
103 nfdeployment: NfDeployment = _retry_get_nfdeployment(cmd, uow)
104 if nfdeployment is None:
105 raise Exception("Cannot find NfDeployment: {}".format(
107 # get nfdeploymentdescriptor by descriptorId
108 desc: NfDeploymentDesc = uow.nfdeployment_descs.get(
109 nfdeployment.descriptorId)
112 "Cannot find NfDeploymentDescriptor:{} for NfDeployment:{}".format(
113 nfdeployment.descriptorId, nfdeployment.id
116 nfdeployment.set_state(NfDeploymentState.Installing)
119 repourl = desc.artifactRepoUrl
120 helm = Helm(logger, LOCAL_HELM_BIN, environment_variables={})
123 repolist = helm.repo_list()
124 for repo in repolist:
125 if repo['url'] == repourl:
126 repoName = repo['name']
133 repoName = "repo4{}".format(nfdeployment.name)
134 logger.debug("Trying to add repo:{}".format(repourl))
135 helm.repo_add(repoName, repourl)
136 helm.repo_update(None)
138 repolist = helm.repo_list()
139 logger.debug('repo list:{}'.format(repolist))
141 # helm install name chart
142 values_file_path = '/tmp/override_{}.yaml'.format(nfdeployment.name)
143 if len(desc.inputParams) > 0:
144 logger.info("dump override yaml:{}".format(values_file_path))
145 values = json.loads(desc.inputParams)
146 _create_values_file(values_file_path, values)
148 values_file_path = None
150 logger.debug('Try to helm install {}/{} {} -f {}'.format(
151 repoName, nfdeployment.name, desc.artifactName, values_file_path))
152 tokens = desc.artifactName.split(':')
153 chartname = tokens[0]
155 # if (len(tokens) > 1):
156 # myflags = {"name": "version", "value": tokens[1]}
157 result = helm.install(
158 nfdeployment.name, "{}/{}".format(repoName, chartname), flags=myflags,
159 values_file=values_file_path, kubeconfig=K8S_KUBECONFIG,
160 token=K8S_TOKEN, apiserver=K8S_APISERVER)
161 logger.debug('result: {}'.format(result))
165 entity: NfDeployment = uow.nfdeployments.get(cmd.NfDeploymentId)
167 entity.set_state(NfDeploymentState.Installed)
168 entity.transit_state(NfDeploymentState.Installed)
172 def _create_values_file(filePath: str, content: dict):
173 with open(filePath, "w", encoding="utf-8") as f:
174 yaml.dump(content, f, Dumper=yaml.RoundTripDumper)
177 def uninstall_nfdeployment(
178 cmd: commands.UninstallNfDeployment,
179 uow: AbstractUnitOfWork
181 logger.info("uninstall with NfDeploymentId: {}".format(
183 nfdeployment: NfDeployment = _retry_get_nfdeployment(cmd, uow)
184 if nfdeployment is None:
185 raise Exception("Cannot find NfDeployment: {}".format(
187 # get nfdeploymentdescriptor by descriptorId
188 desc: NfDeploymentDesc = uow.nfdeployment_descs.get(
189 nfdeployment.descriptorId)
192 "Cannot find NfDeploymentDescriptor:{} for NfDeployment:{}".format(
193 nfdeployment.descriptorId, nfdeployment.id
196 nfdeployment.set_state(NfDeploymentState.Uninstalling)
197 helm = Helm(logger, LOCAL_HELM_BIN, environment_variables={})
199 logger.debug('Try to helm del {}'.format(
202 # if (len(tokens) > 1):
203 # myflags = {"name": "version", "value": tokens[1]}
204 result = helm.uninstall(
205 nfdeployment.name, flags=myflags,
206 kubeconfig=K8S_KUBECONFIG,
207 token=K8S_TOKEN, apiserver=K8S_APISERVER)
208 logger.debug('result: {}'.format(result))
213 entity: NfDeployment = uow.nfdeployments.get(cmd.NfDeploymentId)
215 entity.transit_state(NfDeploymentState.Initial)
216 # uow.nfdeployments.update(
217 # cmd.NfDeploymentId, status=NfDeploymentState.Initial)
221 def delete_nfdeployment(
222 cmd: commands.UninstallNfDeployment,
223 uow: AbstractUnitOfWork
225 logger.info("delete with NfDeploymentId: {}".format(
228 # nfdeployment: NfDeployment = _retry_get_nfdeployment(cmd, uow)
230 uow.nfdeployments.delete(cmd.NfDeploymentId)