blob: 49e346b668d0c0dca2c6171aa8d2a3c5ee1dd450 [file] [log] [blame]
Jian Li304dca42020-12-27 23:22:46 +09001/*
2 * Copyright 2020-present Open Networking Foundation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package org.onosproject.kubevirtnode.impl;
17
18import io.fabric8.kubernetes.api.model.Node;
Jian Li304dca42020-12-27 23:22:46 +090019import io.fabric8.kubernetes.client.KubernetesClient;
Jian Li304dca42020-12-27 23:22:46 +090020import org.onosproject.cluster.ClusterService;
21import org.onosproject.cluster.LeadershipService;
22import org.onosproject.cluster.NodeId;
23import org.onosproject.core.ApplicationId;
24import org.onosproject.core.CoreService;
Jian Li304dca42020-12-27 23:22:46 +090025import org.onosproject.kubevirtnode.api.KubevirtApiConfig;
26import org.onosproject.kubevirtnode.api.KubevirtApiConfigAdminService;
27import org.onosproject.kubevirtnode.api.KubevirtApiConfigEvent;
28import org.onosproject.kubevirtnode.api.KubevirtApiConfigListener;
29import org.onosproject.kubevirtnode.api.KubevirtNode;
30import org.onosproject.kubevirtnode.api.KubevirtNodeAdminService;
Jian Li304dca42020-12-27 23:22:46 +090031import org.osgi.service.component.annotations.Activate;
32import org.osgi.service.component.annotations.Component;
33import org.osgi.service.component.annotations.Deactivate;
34import org.osgi.service.component.annotations.Reference;
35import org.osgi.service.component.annotations.ReferenceCardinality;
36import org.slf4j.Logger;
37
38import java.util.Objects;
39import java.util.concurrent.ExecutorService;
40
41import static java.util.concurrent.Executors.newSingleThreadExecutor;
42import static org.onlab.util.Tools.groupedThreads;
43import static org.onosproject.kubevirtnode.api.KubevirtApiConfig.State.CONNECTED;
44import static org.onosproject.kubevirtnode.api.KubevirtApiConfigService.APP_ID;
Jian Li304dca42020-12-27 23:22:46 +090045import static org.onosproject.kubevirtnode.api.KubevirtNode.Type.WORKER;
Daniel Park81bd46b2021-02-18 20:38:46 +090046import static org.onosproject.kubevirtnode.util.KubevirtNodeUtil.buildKubevirtNode;
Jian Li304dca42020-12-27 23:22:46 +090047import static org.onosproject.kubevirtnode.util.KubevirtNodeUtil.k8sClient;
48import static org.slf4j.LoggerFactory.getLogger;
49
50/**
51 * Handles the state of KubeVirt API server configuration.
52 */
53@Component(immediate = true)
54public class DefaultKubevirtApiConfigHandler {
55
56 private final Logger log = getLogger(getClass());
57
Jian Li304dca42020-12-27 23:22:46 +090058 private static final long SLEEP_MS = 10000; // we wait 10s
59
60 @Reference(cardinality = ReferenceCardinality.MANDATORY)
61 protected CoreService coreService;
62
63 @Reference(cardinality = ReferenceCardinality.MANDATORY)
64 protected LeadershipService leadershipService;
65
66 @Reference(cardinality = ReferenceCardinality.MANDATORY)
67 protected ClusterService clusterService;
68
69 @Reference(cardinality = ReferenceCardinality.MANDATORY)
70 protected KubevirtApiConfigAdminService configAdminService;
71
72 @Reference(cardinality = ReferenceCardinality.MANDATORY)
73 protected KubevirtNodeAdminService nodeAdminService;
74
75 private final ExecutorService eventExecutor = newSingleThreadExecutor(
76 groupedThreads(this.getClass().getSimpleName(), "event-handler", log));
77
78 private final KubevirtApiConfigListener configListener = new InternalKubevirtApiConfigListener();
79
80 private ApplicationId appId;
81 private NodeId localNode;
82
83 @Activate
84 protected void activate() {
85 appId = coreService.getAppId(APP_ID);
86 localNode = clusterService.getLocalNode().id();
87 leadershipService.runForLeadership(appId.name());
88 configAdminService.addListener(configListener);
89
90 log.info("Started");
91 }
92
93 @Deactivate
94 protected void deactivate() {
95 configAdminService.removeListener(configListener);
96 leadershipService.withdraw(appId.name());
97 eventExecutor.shutdown();
98
99 log.info("Stopped");
100 }
101
102 /**
103 * Checks the validity of the given kubernetes API server configuration.
104 *
105 * @param config kubernetes API server configuration
106 * @return validity result
107 */
108 private boolean checkApiServerConfig(KubevirtApiConfig config) {
109 KubernetesClient k8sClient = k8sClient(config);
110 return k8sClient != null && k8sClient.getApiVersion() != null;
111 }
112
113 private void bootstrapKubevirtNodes(KubevirtApiConfig config) {
114 KubernetesClient k8sClient = k8sClient(config);
115
116 if (k8sClient == null) {
117 log.warn("Failed to connect to kubernetes API server");
118 return;
119 }
120
121 for (Node node : k8sClient.nodes().list().getItems()) {
122 KubevirtNode kubevirtNode = buildKubevirtNode(node);
Jian Li2b35ec72021-01-21 16:45:02 +0900123 // we always provision VMs to worker nodes, so only need to install
124 // flow rules in worker nodes
125 if (kubevirtNode.type() == WORKER) {
126 nodeAdminService.createNode(kubevirtNode);
127 }
Jian Li304dca42020-12-27 23:22:46 +0900128 }
129 }
130
Jian Li304dca42020-12-27 23:22:46 +0900131 private class InternalKubevirtApiConfigListener implements KubevirtApiConfigListener {
132
133 private boolean isRelevantHelper() {
134 return Objects.equals(localNode, leadershipService.getLeader(appId.name()));
135 }
136
137 @Override
138 public void event(KubevirtApiConfigEvent event) {
139 switch (event.type()) {
140 case KUBEVIRT_API_CONFIG_CREATED:
141 eventExecutor.execute(() -> processConfigCreation(event.subject()));
142 break;
143 default:
144 break;
145 }
146 }
147
148 private void processConfigCreation(KubevirtApiConfig config) {
149 if (!isRelevantHelper()) {
150 return;
151 }
152
153 if (checkApiServerConfig(config)) {
154 KubevirtApiConfig newConfig = config.updateState(CONNECTED);
155 configAdminService.updateApiConfig(newConfig);
156
157 bootstrapKubevirtNodes(config);
158 }
159 }
160 }
161}