blob: 7b73f69a91d3355b14455e182713896471c85533 [file] [log] [blame]
Jian Lid5e8ea82021-01-18 00:19:31 +09001/*
2 * Copyright 2021-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.kubevirtnetworking.impl;
17
18import io.fabric8.kubernetes.api.model.Pod;
Jian Lid5e8ea82021-01-18 00:19:31 +090019import org.onosproject.cluster.ClusterService;
20import org.onosproject.cluster.LeadershipService;
21import org.onosproject.cluster.NodeId;
22import org.onosproject.core.ApplicationId;
23import org.onosproject.core.CoreService;
Jian Lid5e8ea82021-01-18 00:19:31 +090024import org.onosproject.kubevirtnetworking.api.KubevirtNetworkAdminService;
25import org.onosproject.kubevirtnetworking.api.KubevirtPodAdminService;
26import org.onosproject.kubevirtnetworking.api.KubevirtPodEvent;
27import org.onosproject.kubevirtnetworking.api.KubevirtPodListener;
28import org.onosproject.kubevirtnetworking.api.KubevirtPort;
29import org.onosproject.kubevirtnetworking.api.KubevirtPortAdminService;
30import org.onosproject.kubevirtnode.api.KubevirtApiConfigService;
Jian Li7d3a0c82021-03-24 15:24:18 +090031import org.onosproject.kubevirtnode.api.KubevirtNode;
Daniel Parke7e3d6a2021-03-10 07:49:11 +090032import org.onosproject.kubevirtnode.api.KubevirtNodeService;
Jian Lid5e8ea82021-01-18 00:19:31 +090033import org.onosproject.mastership.MastershipService;
34import org.onosproject.net.device.DeviceService;
35import org.onosproject.net.driver.DriverService;
36import org.osgi.service.component.annotations.Activate;
37import org.osgi.service.component.annotations.Component;
38import org.osgi.service.component.annotations.Deactivate;
39import org.osgi.service.component.annotations.Reference;
40import org.osgi.service.component.annotations.ReferenceCardinality;
41import org.slf4j.Logger;
42
43import java.util.Map;
44import java.util.Objects;
Jian Li3831f0c2021-03-12 18:03:58 +090045import java.util.Set;
Jian Lid5e8ea82021-01-18 00:19:31 +090046import java.util.concurrent.ExecutorService;
47
Jian Li7d3a0c82021-03-24 15:24:18 +090048import static java.lang.Thread.sleep;
Jian Lid5e8ea82021-01-18 00:19:31 +090049import static java.util.concurrent.Executors.newSingleThreadExecutor;
50import static org.onlab.util.Tools.groupedThreads;
51import static org.onosproject.kubevirtnetworking.api.Constants.KUBEVIRT_NETWORKING_APP_ID;
Jian Li3831f0c2021-03-12 18:03:58 +090052import static org.onosproject.kubevirtnetworking.util.KubevirtNetworkingUtil.getPorts;
Jian Lid5e8ea82021-01-18 00:19:31 +090053import static org.slf4j.LoggerFactory.getLogger;
54
55/**
56 * Associates the kubevirt container port and pod.
57 */
58@Component(immediate = true)
59public class KubevirtPodPortMapper {
60
61 private final Logger log = getLogger(getClass());
62
63 private static final String NETWORK_STATUS_KEY = "k8s.v1.cni.cncf.io/network-status";
64 private static final String NAME = "name";
65 private static final String IPS = "ips";
66 private static final String NETWORK_PREFIX = "default/";
Jian Li7d3a0c82021-03-24 15:24:18 +090067 private static final long SLEEP_MS = 2000; // we wait 2s
Jian Lid5e8ea82021-01-18 00:19:31 +090068
69 @Reference(cardinality = ReferenceCardinality.MANDATORY)
70 protected CoreService coreService;
71
72 @Reference(cardinality = ReferenceCardinality.MANDATORY)
73 protected MastershipService mastershipService;
74
75 @Reference(cardinality = ReferenceCardinality.MANDATORY)
76 protected ClusterService clusterService;
77
78 @Reference(cardinality = ReferenceCardinality.MANDATORY)
79 protected LeadershipService leadershipService;
80
81 @Reference(cardinality = ReferenceCardinality.MANDATORY)
82 protected DeviceService deviceService;
83
84 @Reference(cardinality = ReferenceCardinality.MANDATORY)
85 protected DriverService driverService;
86
87 @Reference(cardinality = ReferenceCardinality.MANDATORY)
88 protected KubevirtPortAdminService kubevirtPortAdminService;
89
90 @Reference(cardinality = ReferenceCardinality.MANDATORY)
91 protected KubevirtNetworkAdminService kubevirtNetworkAdminService;
92
93 @Reference(cardinality = ReferenceCardinality.MANDATORY)
94 protected KubevirtPodAdminService kubevirtPodAdminService;
95
96 @Reference(cardinality = ReferenceCardinality.MANDATORY)
97 protected KubevirtApiConfigService kubevirtApiConfigService;
98
Daniel Parke7e3d6a2021-03-10 07:49:11 +090099 @Reference(cardinality = ReferenceCardinality.MANDATORY)
100 protected KubevirtNodeService kubevirtNodeService;
101
Jian Lid5e8ea82021-01-18 00:19:31 +0900102 private final ExecutorService eventExecutor = newSingleThreadExecutor(
103 groupedThreads(this.getClass().getSimpleName(), "event-handler"));
104
105 private final InternalKubevirtPodListener kubevirtPodListener =
106 new InternalKubevirtPodListener();
107
108 private ApplicationId appId;
109 private NodeId localNodeId;
110
111 @Activate
112 protected void activate() {
113 appId = coreService.registerApplication(KUBEVIRT_NETWORKING_APP_ID);
114 localNodeId = clusterService.getLocalNode().id();
115 leadershipService.runForLeadership(appId.name());
116 kubevirtPodAdminService.addListener(kubevirtPodListener);
117
118 log.info("Started");
119 }
120
121 @Deactivate
122 protected void deactivate() {
123 kubevirtPodAdminService.removeListener(kubevirtPodListener);
124 leadershipService.withdraw(appId.name());
125 eventExecutor.shutdown();
126
127 log.info("Stopped");
128 }
129
130 private class InternalKubevirtPodListener implements KubevirtPodListener {
131
132 private boolean isRelevantHelper() {
133 return Objects.equals(localNodeId, leadershipService.getLeader(appId.name()));
134 }
135
136 @Override
137 public void event(KubevirtPodEvent event) {
138 switch (event.type()) {
139 case KUBEVIRT_POD_UPDATED:
140 eventExecutor.execute(() -> processPodUpdate(event.subject()));
141 break;
Jian Lid5e8ea82021-01-18 00:19:31 +0900142 case KUBEVIRT_POD_CREATED:
Jian Li7d3a0c82021-03-24 15:24:18 +0900143 case KUBEVIRT_POD_REMOVED:
Jian Lid5e8ea82021-01-18 00:19:31 +0900144 default:
145 // do nothing
146 break;
147 }
148 }
149
Jian Li7d3a0c82021-03-24 15:24:18 +0900150 private void processPodUpdate(Pod pod) {
Jian Li2417ab72021-02-02 17:35:12 +0900151 if (!isRelevantHelper()) {
152 return;
153 }
154
Jian Li2417ab72021-02-02 17:35:12 +0900155 Map<String, String> annots = pod.getMetadata().getAnnotations();
156 if (annots == null) {
157 return;
158 }
159
160 if (!annots.containsKey(NETWORK_STATUS_KEY)) {
161 return;
162 }
163
Jian Li7d3a0c82021-03-24 15:24:18 +0900164 KubevirtNode node = kubevirtNodeService.node(pod.getSpec().getNodeName());
165
166 if (node == null) {
167 try {
168 // we wait until all k8s nodes are available
169 sleep(SLEEP_MS);
170 } catch (InterruptedException e) {
171 e.printStackTrace();
Jian Li2417ab72021-02-02 17:35:12 +0900172 }
Jian Li2417ab72021-02-02 17:35:12 +0900173 }
174
Jian Li7d3a0c82021-03-24 15:24:18 +0900175 Set<KubevirtPort> ports =
176 getPorts(kubevirtNodeService, kubevirtNetworkAdminService.networks(), pod);
Jian Li3831f0c2021-03-12 18:03:58 +0900177 if (ports.size() == 0) {
Jian Li2417ab72021-02-02 17:35:12 +0900178 return;
179 }
180
Jian Li3831f0c2021-03-12 18:03:58 +0900181 ports.forEach(port -> {
Jian Li7d3a0c82021-03-24 15:24:18 +0900182 KubevirtPort existing = kubevirtPortAdminService.port(port.macAddress());
Jian Li2417ab72021-02-02 17:35:12 +0900183
Jian Li7d3a0c82021-03-24 15:24:18 +0900184 if (existing != null) {
185 if (port.deviceId() != null && existing.deviceId() == null) {
186 KubevirtPort updated = existing.updateDeviceId(port.deviceId());
187 // internal we update device ID of kubevirt port
188 kubevirtPortAdminService.updatePort(updated);
Jian Li3831f0c2021-03-12 18:03:58 +0900189 }
190 }
Jian Li3831f0c2021-03-12 18:03:58 +0900191 });
Jian Lid5e8ea82021-01-18 00:19:31 +0900192 }
193 }
194}