blob: fce69d7f3775e358cb410a28dd1b8fc3fe95ad57 [file] [log] [blame]
Daniel Park734b5532022-09-26 15:13:59 +09001/*
2 * Copyright 2022-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 com.google.common.collect.ImmutableSet;
19import org.onlab.util.KryoNamespace;
20import org.onosproject.core.ApplicationId;
21import org.onosproject.core.CoreService;
22import org.onosproject.kubevirtnetworking.api.DefaultKubernetesExternalLb;
23import org.onosproject.kubevirtnetworking.api.KubernetesExternalLb;
24import org.onosproject.kubevirtnetworking.api.KubernetesExternalLbEvent;
25import org.onosproject.kubevirtnetworking.api.KubernetesExternalLbStore;
26import org.onosproject.kubevirtnetworking.api.KubernetesExternalLbStoreDelegate;
27import org.onosproject.store.AbstractStore;
28import org.onosproject.store.serializers.KryoNamespaces;
29import org.onosproject.store.service.ConsistentMap;
30import org.onosproject.store.service.MapEvent;
31import org.onosproject.store.service.MapEventListener;
32import org.onosproject.store.service.Serializer;
33import org.onosproject.store.service.StorageService;
34import org.onosproject.store.service.Versioned;
35import org.osgi.service.component.annotations.Activate;
36import org.osgi.service.component.annotations.Component;
37import org.osgi.service.component.annotations.Deactivate;
38import org.osgi.service.component.annotations.Reference;
39import org.osgi.service.component.annotations.ReferenceCardinality;
40import org.slf4j.Logger;
41
42import java.util.Collection;
43import java.util.Set;
44import java.util.concurrent.ExecutorService;
45
46import static com.google.common.base.Preconditions.checkArgument;
47import static java.util.concurrent.Executors.newSingleThreadExecutor;
48import static org.onlab.util.Tools.groupedThreads;
49import static org.onosproject.kubevirtnetworking.api.KubernetesExternalLbEvent.Type.KUBERNETES_EXTERNAL_LOAD_BALANCER_CREATED;
50import static org.onosproject.kubevirtnetworking.api.KubernetesExternalLbEvent.Type.KUBERNETES_EXTERNAL_LOAD_BALANCER_REMOVED;
51import static org.onosproject.kubevirtnetworking.api.KubernetesExternalLbEvent.Type.KUBERNETES_EXTERNAL_LOAD_BALANCER_UPDATED;
52import static org.slf4j.LoggerFactory.getLogger;
53
54/**
55 * Implementation of kubernetes external lb store using consistent map.
56 */
57@Component(immediate = true, service = KubernetesExternalLbStore.class)
58public class DistributedKubernetesExternalLbStore
59 extends AbstractStore<KubernetesExternalLbEvent, KubernetesExternalLbStoreDelegate>
60 implements KubernetesExternalLbStore {
61
62 private final Logger log = getLogger(getClass());
63
64 private static final String ERR_NOT_FOUND = " does not exist";
65 private static final String ERR_DUPLICATE = " already exists";
66 private static final String APP_ID = "org.onosproject.kubevirtnetwork";
67
68 private static final KryoNamespace SERIALIZER_KUBERNETES_EXTERNAL_LB = KryoNamespace.newBuilder()
69 .register(KryoNamespaces.API)
70 .register(KubernetesExternalLb.class)
71 .register(DefaultKubernetesExternalLb.class)
72 .register(Collection.class)
73 .build();
74
75 @Reference(cardinality = ReferenceCardinality.MANDATORY)
76 protected CoreService coreService;
77
78 @Reference(cardinality = ReferenceCardinality.MANDATORY)
79 protected StorageService storageService;
80
81 private final ExecutorService eventExecutor = newSingleThreadExecutor(
82 groupedThreads(this.getClass().getSimpleName(), "event-handler", log));
83
84 private final MapEventListener<String, KubernetesExternalLb> lbMapEventListener =
85 new KubernetesExternalLbMapListener();
86
87 private ConsistentMap<String, KubernetesExternalLb> lbStore;
88
89 @Activate
90 protected void activate() {
91 ApplicationId appId = coreService.registerApplication(APP_ID);
92 lbStore = storageService.<String, KubernetesExternalLb>consistentMapBuilder()
93 .withSerializer(Serializer.using(SERIALIZER_KUBERNETES_EXTERNAL_LB))
94 .withName("kubernetes-lbstore")
95 .withApplicationId(appId)
96 .build();
97
98 lbStore.addListener(lbMapEventListener);
99 log.info("Started");
100 }
101
102 @Deactivate
103 protected void deactivate() {
104 lbStore.removeListener(lbMapEventListener);
105 eventExecutor.shutdown();
106 log.info("Stopped");
107 }
108
109 @Override
110 public void createLoadBalancer(KubernetesExternalLb lb) {
111 lbStore.compute(lb.serviceName(), (seviceName, existing) -> {
112 final String error = lb.serviceName() + ERR_DUPLICATE;
113 checkArgument(existing == null, error);
114 return lb;
115 });
116 }
117
118 @Override
119 public void updateLoadBalancer(KubernetesExternalLb lb) {
120 lbStore.compute(lb.serviceName(), (seviceName, existing) -> {
121 final String error = lb.serviceName() + ERR_NOT_FOUND;
122 checkArgument(existing != null, error);
123 return lb;
124 });
125 }
126
127 @Override
128 public KubernetesExternalLb removeLoadBalancer(String serviceName) {
129
130 Versioned<KubernetesExternalLb> lb = lbStore.remove(serviceName);
131
132 if (lb == null) {
133 final String error = serviceName + ERR_NOT_FOUND;
134 throw new IllegalArgumentException(error);
135 }
136 return lb.value();
137 }
138
139 @Override
140 public KubernetesExternalLb loadBalancer(String serviceName) {
141 return lbStore.asJavaMap().get(serviceName);
142 }
143
144 @Override
145 public Set<KubernetesExternalLb> loadBalancers() {
146 return ImmutableSet.copyOf(lbStore.asJavaMap().values());
147 }
148
149 @Override
150 public void clear() {
151 lbStore.clear();
152 }
153
154 private class KubernetesExternalLbMapListener implements MapEventListener<String, KubernetesExternalLb> {
155 @Override
156 public void event(MapEvent<String, KubernetesExternalLb> event) {
157 switch (event.type()) {
158 case INSERT:
159 eventExecutor.execute(() ->
160 notifyDelegate(new KubernetesExternalLbEvent(
161 KUBERNETES_EXTERNAL_LOAD_BALANCER_CREATED, event.newValue().value())));
162 break;
163 case UPDATE:
164 eventExecutor.execute(() ->
165 notifyDelegate(new KubernetesExternalLbEvent(
166 KUBERNETES_EXTERNAL_LOAD_BALANCER_UPDATED, event.newValue().value())));
167 break;
168 case REMOVE:
169 eventExecutor.execute(() ->
170 notifyDelegate(new KubernetesExternalLbEvent(
171 KUBERNETES_EXTERNAL_LOAD_BALANCER_REMOVED, event.newValue().value())));
172 break;
173 default:
174 //do nothing
175 break;
176 }
177 }
178 }
179}