blob: 4c7e83d10248de8a4b13c05f836477548cc7a43d [file] [log] [blame]
Jian Lib1cd0b02019-02-21 16:41:40 +09001/*
2 * Copyright 2019-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.k8snetworking.cli;
17
18import com.google.common.collect.Lists;
19import io.fabric8.kubernetes.api.model.Endpoints;
20import io.fabric8.kubernetes.api.model.Pod;
Jian Li1cf51882019-02-26 14:41:20 +090021import io.fabric8.kubernetes.api.model.extensions.Ingress;
Jian Lif4523d82019-07-07 01:06:09 +090022import io.fabric8.kubernetes.api.model.networking.NetworkPolicy;
Jian Lib1cd0b02019-02-21 16:41:40 +090023import io.fabric8.kubernetes.client.KubernetesClient;
24import org.apache.karaf.shell.api.action.Command;
25import org.apache.karaf.shell.api.action.lifecycle.Service;
Jian Li3d1111e2019-02-22 02:02:13 +090026import org.onlab.packet.IpAddress;
27import org.onlab.packet.MacAddress;
Jian Lib1cd0b02019-02-21 16:41:40 +090028import org.onosproject.cli.AbstractShellCommand;
Jian Li3d1111e2019-02-22 02:02:13 +090029import org.onosproject.k8snetworking.api.DefaultK8sPort;
Jian Lib1cd0b02019-02-21 16:41:40 +090030import org.onosproject.k8snetworking.api.K8sEndpointsAdminService;
Jian Li1cf51882019-02-26 14:41:20 +090031import org.onosproject.k8snetworking.api.K8sIngressAdminService;
Jian Li3d1111e2019-02-22 02:02:13 +090032import org.onosproject.k8snetworking.api.K8sNetworkAdminService;
Jian Lif4523d82019-07-07 01:06:09 +090033import org.onosproject.k8snetworking.api.K8sNetworkPolicyAdminService;
Jian Lib1cd0b02019-02-21 16:41:40 +090034import org.onosproject.k8snetworking.api.K8sPodAdminService;
Jian Li3d1111e2019-02-22 02:02:13 +090035import org.onosproject.k8snetworking.api.K8sPort;
Jian Lib1cd0b02019-02-21 16:41:40 +090036import org.onosproject.k8snetworking.api.K8sServiceAdminService;
37import org.onosproject.k8snetworking.util.K8sNetworkingUtil;
38import org.onosproject.k8snode.api.K8sApiConfig;
39import org.onosproject.k8snode.api.K8sApiConfigService;
Jian Li3d1111e2019-02-22 02:02:13 +090040import org.onosproject.net.DeviceId;
41import org.onosproject.net.PortNumber;
Jian Lib1cd0b02019-02-21 16:41:40 +090042
43import java.util.List;
Jian Li3d1111e2019-02-22 02:02:13 +090044import java.util.Map;
45
46import static org.onosproject.k8snetworking.api.K8sPort.State.INACTIVE;
Jian Lib1cd0b02019-02-21 16:41:40 +090047
48/**
49 * Synchronizes kubernetes states.
50 */
51@Service
52@Command(scope = "onos", name = "k8s-sync-states",
53 description = "Synchronizes all kubernetes states")
54public class K8sSyncStateCommand extends AbstractShellCommand {
55
56 private static final String POD_FORMAT = "%-50s%-15s%-15s%-30s";
57 private static final String SERVICE_FORMAT = "%-50s%-30s%-30s";
58 private static final String ENDPOINTS_FORMAT = "%-50s%-50s%-20s";
Jian Li1cf51882019-02-26 14:41:20 +090059 private static final String INGRESS_FORMAT = "%-50s%-15s%-30s";
Jian Lif4523d82019-07-07 01:06:09 +090060 private static final String NETWORK_POLICY_FORMAT = "%-50s%-15s%-30s";
Jian Lib1cd0b02019-02-21 16:41:40 +090061
Jian Li3d1111e2019-02-22 02:02:13 +090062 private static final String PORT_ID = "portId";
63 private static final String DEVICE_ID = "deviceId";
64 private static final String PORT_NUMBER = "portNumber";
65 private static final String IP_ADDRESS = "ipAddress";
66 private static final String MAC_ADDRESS = "macAddress";
67 private static final String NETWORK_ID = "networkId";
68
Jian Lib1cd0b02019-02-21 16:41:40 +090069 @Override
70 protected void doExecute() {
71 K8sApiConfigService configService = get(K8sApiConfigService.class);
72 K8sPodAdminService podAdminService = get(K8sPodAdminService.class);
73 K8sServiceAdminService serviceAdminService =
74 get(K8sServiceAdminService.class);
Jian Li1cf51882019-02-26 14:41:20 +090075 K8sIngressAdminService ingressAdminService =
76 get(K8sIngressAdminService.class);
Jian Lib1cd0b02019-02-21 16:41:40 +090077 K8sEndpointsAdminService endpointsAdminService =
78 get(K8sEndpointsAdminService.class);
Jian Li3d1111e2019-02-22 02:02:13 +090079 K8sNetworkAdminService networkAdminService =
80 get(K8sNetworkAdminService.class);
Jian Lif4523d82019-07-07 01:06:09 +090081 K8sNetworkPolicyAdminService networkPolicyAdminService =
82 get(K8sNetworkPolicyAdminService.class);
Jian Lib1cd0b02019-02-21 16:41:40 +090083
84 K8sApiConfig config =
85 configService.apiConfigs().stream().findAny().orElse(null);
86 if (config == null) {
87 log.error("Failed to find valid kubernetes API configuration.");
88 return;
89 }
90
91 KubernetesClient client = K8sNetworkingUtil.k8sClient(config);
92
93 if (client == null) {
94 log.error("Failed to connect to kubernetes API server.");
95 return;
96 }
97
98 print("Synchronizing kubernetes services");
99 print(SERVICE_FORMAT, "Name", "Cluster IP", "Ports");
Jian Liaf081522019-06-19 20:53:07 +0900100 client.services().inAnyNamespace().list().getItems().forEach(svc -> {
Jian Lib1cd0b02019-02-21 16:41:40 +0900101 if (serviceAdminService.service(svc.getMetadata().getUid()) != null) {
102 serviceAdminService.updateService(svc);
103 } else {
104 serviceAdminService.createService(svc);
105 }
106 printService(svc);
107 });
108
109 print("\nSynchronizing kubernetes endpoints");
110 print(ENDPOINTS_FORMAT, "Name", "IP Addresses", "Ports");
Jian Liaf081522019-06-19 20:53:07 +0900111 client.endpoints().inAnyNamespace().list().getItems().forEach(ep -> {
Jian Lib1cd0b02019-02-21 16:41:40 +0900112 if (endpointsAdminService.endpoints(ep.getMetadata().getUid()) != null) {
113 endpointsAdminService.updateEndpoints(ep);
114 } else {
115 endpointsAdminService.createEndpoints(ep);
116 }
117 printEndpoints(ep);
118 });
119
120 print("\nSynchronizing kubernetes pods");
121 print(POD_FORMAT, "Name", "Namespace", "IP", "Containers");
Jian Liaf081522019-06-19 20:53:07 +0900122 client.pods().inAnyNamespace().list().getItems().forEach(pod -> {
Jian Lib1cd0b02019-02-21 16:41:40 +0900123 if (podAdminService.pod(pod.getMetadata().getUid()) != null) {
124 podAdminService.updatePod(pod);
125 } else {
126 podAdminService.createPod(pod);
127 }
Jian Li3d1111e2019-02-22 02:02:13 +0900128
129 syncPortFromPod(pod, networkAdminService);
130
Jian Lib1cd0b02019-02-21 16:41:40 +0900131 printPod(pod);
132 });
Jian Li1cf51882019-02-26 14:41:20 +0900133
134 print("\nSynchronizing kubernetes ingresses");
135 print(INGRESS_FORMAT, "Name", "Namespace", "LB Addresses");
Jian Liaf081522019-06-19 20:53:07 +0900136 client.extensions().ingresses().inAnyNamespace().list().getItems().forEach(ingress -> {
Jian Li1cf51882019-02-26 14:41:20 +0900137 if (ingressAdminService.ingress(ingress.getMetadata().getUid()) != null) {
138 ingressAdminService.updateIngress(ingress);
139 } else {
140 ingressAdminService.createIngress(ingress);
141 }
142 printIngresses(ingress);
143 });
144
Jian Lif4523d82019-07-07 01:06:09 +0900145 print("\nSynchronizing kubernetes network policies");
146 print(NETWORK_POLICY_FORMAT, "Name", "Namespace", "Types");
147 client.network().networkPolicies().inAnyNamespace().list().getItems().forEach(policy -> {
148 if (networkPolicyAdminService.networkPolicy(policy.getMetadata().getUid()) != null) {
149 networkPolicyAdminService.updateNetworkPolicy(policy);
150 } else {
151 networkPolicyAdminService.createNetworkPolicy(policy);
152 }
153 printNetworkPolicy(policy);
154 });
Jian Li1cf51882019-02-26 14:41:20 +0900155 }
156
157 private void printIngresses(Ingress ingress) {
158
159 List<String> lbIps = Lists.newArrayList();
160
161 ingress.getStatus().getLoadBalancer()
162 .getIngress().forEach(i -> lbIps.add(i.getIp()));
163
164 print(INGRESS_FORMAT,
165 ingress.getMetadata().getName(),
166 ingress.getMetadata().getNamespace(),
167 lbIps.isEmpty() ? "" : lbIps);
Jian Lib1cd0b02019-02-21 16:41:40 +0900168 }
169
170 private void printEndpoints(Endpoints endpoints) {
171 List<String> ips = Lists.newArrayList();
172 List<Integer> ports = Lists.newArrayList();
173
174 endpoints.getSubsets().forEach(e -> {
175 e.getAddresses().forEach(a -> ips.add(a.getIp()));
176 e.getPorts().forEach(p -> ports.add(p.getPort()));
177 });
178
179 print(ENDPOINTS_FORMAT,
180 endpoints.getMetadata().getName(),
181 ips.isEmpty() ? "" : ips,
182 ports.isEmpty() ? "" : ports);
183 }
184
185 private void printService(io.fabric8.kubernetes.api.model.Service service) {
186
187 List<Integer> ports = Lists.newArrayList();
188
189 service.getSpec().getPorts().forEach(p -> ports.add(p.getPort()));
190
191 print(SERVICE_FORMAT,
192 service.getMetadata().getName(),
193 service.getSpec().getClusterIP(),
194 ports.isEmpty() ? "" : ports);
195 }
196
197 private void printPod(Pod pod) {
198
199 List<String> containers = Lists.newArrayList();
200
201 pod.getSpec().getContainers().forEach(c -> containers.add(c.getName()));
202
203 print(POD_FORMAT,
204 pod.getMetadata().getName(),
205 pod.getMetadata().getNamespace(),
206 pod.getStatus().getPodIP(),
207 containers.isEmpty() ? "" : containers);
208 }
Jian Li3d1111e2019-02-22 02:02:13 +0900209
Jian Lif4523d82019-07-07 01:06:09 +0900210 private void printNetworkPolicy(NetworkPolicy policy) {
211 print(NETWORK_POLICY_FORMAT,
212 policy.getMetadata().getName(),
213 policy.getMetadata().getNamespace(),
214 policy.getSpec().getPolicyTypes().isEmpty() ?
215 "" : policy.getSpec().getPolicyTypes());
216 }
217
Jian Li3d1111e2019-02-22 02:02:13 +0900218 private void syncPortFromPod(Pod pod, K8sNetworkAdminService adminService) {
219 Map<String, String> annotations = pod.getMetadata().getAnnotations();
220 if (annotations != null && !annotations.isEmpty() &&
221 annotations.get(PORT_ID) != null) {
222 String portId = annotations.get(PORT_ID);
223
224 K8sPort oldPort = adminService.port(portId);
225
226 String networkId = annotations.get(NETWORK_ID);
227 DeviceId deviceId = DeviceId.deviceId(annotations.get(DEVICE_ID));
228 PortNumber portNumber = PortNumber.portNumber(annotations.get(PORT_NUMBER));
229 IpAddress ipAddress = IpAddress.valueOf(annotations.get(IP_ADDRESS));
230 MacAddress macAddress = MacAddress.valueOf(annotations.get(MAC_ADDRESS));
231
232 K8sPort newPort = DefaultK8sPort.builder()
233 .portId(portId)
234 .networkId(networkId)
235 .deviceId(deviceId)
236 .ipAddress(ipAddress)
237 .macAddress(macAddress)
238 .portNumber(portNumber)
239 .state(INACTIVE)
240 .build();
241
242 if (oldPort == null) {
243 adminService.createPort(newPort);
244 } else {
245 adminService.updatePort(newPort);
246 }
247 }
248 }
Jian Lib1cd0b02019-02-21 16:41:40 +0900249}