blob: 6d15ea84ef35bfaa9da35a6ecfeaa7a9da684987 [file] [log] [blame]
Luca Pretedce16f82016-11-22 13:11:56 -08001/*
Luca Prete99f6f282016-12-05 15:33:36 -08002 * Copyright 2015-present Open Networking Laboratory
Luca Pretedce16f82016-11-22 13:11:56 -08003 *
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
Luca Prete99f6f282016-12-05 15:33:36 -080014 * limitations under the License.
Luca Pretedce16f82016-11-22 13:11:56 -080015 */
16package org.onosproject.vpls.cli;
17
18import com.google.common.collect.Lists;
19import com.google.common.collect.SetMultimap;
20import com.google.common.collect.Sets;
21import org.apache.karaf.shell.commands.Argument;
22import org.apache.karaf.shell.commands.Command;
23import org.onosproject.cli.AbstractShellCommand;
24import org.onosproject.incubator.net.intf.Interface;
25import org.onosproject.incubator.net.intf.InterfaceService;
26import org.onosproject.net.EncapsulationType;
27import org.onosproject.vpls.config.VplsConfigService;
28
29import java.util.Collections;
30import java.util.List;
31import java.util.Map;
32import java.util.Optional;
33import java.util.Set;
34
35import static com.google.common.base.Strings.isNullOrEmpty;
36
37/**
38 * CLI to interact with the VPLS application.
39 */
40@Command(scope = "onos", name = "vpls",
41 description = "Manages the VPLS application")
42public class VplsCommand extends AbstractShellCommand {
43
44 // Color codes and style
45 private static final String BOLD = "\u001B[1m";
46 private static final String COLOR_ERROR = "\u001B[31m";
47 private static final String RESET = "\u001B[0m";
48
49 // Messages and string formatter
50 private static final String ENCAP_NOT_FOUND =
51 COLOR_ERROR + "Encapsulation type " + BOLD + "%s" + RESET +
52 COLOR_ERROR + " not found" + RESET;
53
54 private static final String IFACE_NOT_FOUND =
55 COLOR_ERROR + "Interface " + BOLD + "%s" + RESET + COLOR_ERROR +
56 " not found" + RESET;
57
58 private static final String IFACE_ALREADY_ASSOCIATED =
59 COLOR_ERROR + "Interface " + BOLD + "%s" + RESET + COLOR_ERROR +
60 " already associated to VPLS " + BOLD + "%s" + RESET +
61 COLOR_ERROR + "" + RESET;
62
63 private static final String SEPARATOR = "----------------";
64
65 private static final String VPLS_ALREADY_EXISTS =
66 COLOR_ERROR + "VPLS " + BOLD + "%s" + RESET + COLOR_ERROR +
67 " already exists" + RESET;
68
69 private static final String VPLS_COMMAND_NOT_FOUND =
70 COLOR_ERROR + "VPLS command " + BOLD + "%s" + RESET + COLOR_ERROR +
71 " not found" + RESET;
72
73 private static final String VPLS_DISPLAY = "VPLS name: " + BOLD +
74 "%s" + RESET + "\nAssociated interfaces: %s\nEncapsulation: %s";
75
76 private static final String VPLS_LIST_TITLE =
77 BOLD + "Configured VPLSs" + RESET;
78
79 private static final String VPLS_NOT_FOUND =
80 COLOR_ERROR + "VPLS " + BOLD + "%s" + RESET + COLOR_ERROR +
81 " not found" + RESET;
82
83 private static final String IFACE_NOT_ASSOCIATED =
84 COLOR_ERROR + "Interface " + BOLD + "%s" + RESET + COLOR_ERROR +
85 " cannot be removed from VPLS " + BOLD + "%s" + RESET +
86 COLOR_ERROR + ". The interface is associated to another" +
87 "VPLS (" + BOLD + "%s" + RESET + COLOR_ERROR + ")" + RESET;
88
89 private static VplsConfigService vplsConfigService =
90 get(VplsConfigService.class);
91 private static InterfaceService interfaceService =
92 get(InterfaceService.class);
93
94 @Argument(index = 0, name = "command", description = "Command name (add|" +
95 "clean|create|delete|list|removeIface|set-encap|show)",
96 required = true, multiValued = false)
97 String command = null;
98
99 @Argument(index = 1, name = "vplsName", description = "The name of the VPLS",
100 required = false, multiValued = false)
101 String vplsName = null;
102
103 @Argument(index = 2, name = "optArg", description = "The interface name for" +
104 "all commands; the encapsulation type for set-encap",
105 required = false, multiValued = false)
106 String optArg = null;
107
108 @Override
109 protected void execute() {
110 VplsCommandEnum enumCommand = VplsCommandEnum.enumFromString(command);
111 if (enumCommand != null) {
112 switch (enumCommand) {
113 case ADD_IFACE:
114 addIface(vplsName, optArg);
115 break;
116 case CLEAN:
117 clean();
118 break;
119 case CREATE:
120 create(vplsName);
121 break;
122 case DELETE:
123 delete(vplsName);
124 break;
125 case LIST:
126 list();
127 break;
128 case REMOVE_IFACE:
129 removeIface(vplsName, optArg);
130 break;
131 case SET_ENCAP:
132 setEncap(vplsName, optArg);
133 break;
134 case SHOW:
135 show(vplsName);
136 break;
137 default:
138 print(VPLS_COMMAND_NOT_FOUND, command);
139 }
140 }
141 }
142
143 /**
144 * Adds an inteterface to a VPLS.
145 *
146 * @param vplsName the name of the VLPS
147 * @param ifaceName the name of the interface to add
148 */
149 private void addIface(String vplsName, String ifaceName) {
150 // Check if the VPLS exists
151 if (!vplsExists(vplsName)) {
152 print(VPLS_NOT_FOUND, vplsName);
153 return;
154 }
155 // Check if the interface exists
156 if (!ifaceExists(ifaceName)) {
157 print(IFACE_NOT_FOUND, ifaceName);
158 return;
159 }
160 // Check if the interface is already associated to a VPLS
161 if (isIfaceAssociated(ifaceName)) {
162 print(IFACE_ALREADY_ASSOCIATED,
163 ifaceName, vplsNameFromIfaceName(ifaceName));
164 return;
165 }
166
167 vplsConfigService.addIface(vplsName, ifaceName);
168 }
169
170 /**
171 * Cleans the VPLS configuration.
172 */
173 private void clean() {
174 vplsConfigService.cleanVplsConfig();
175 }
176
177 /**
178 * Creates a new VPLS.
179 *
180 * @param vplsName the name of the VLPS
181 */
182 private void create(String vplsName) {
183 if (vplsExists(vplsName)) {
184 print(VPLS_ALREADY_EXISTS, vplsName);
185 return;
186 }
187 vplsConfigService.addVpls(vplsName, Sets.newHashSet(), null);
188 }
189
190 /**
191 * Deletes a VPLS.
192 *
193 * @param vplsName the name of the VLPS
194 */
195 private void delete(String vplsName) {
196 if (!vplsExists(vplsName)) {
197 print(VPLS_NOT_FOUND, vplsName);
198 return;
199 }
200 vplsConfigService.removeVpls(vplsName);
201 }
202
203 /**
204 * Lists the configured VPLSs.
205 */
206 private void list() {
207 List<String> vplsNames = Lists.newArrayList(vplsConfigService.vplsNames());
208 Collections.sort(vplsNames);
209
210 print(VPLS_LIST_TITLE);
211 print(SEPARATOR);
212 vplsNames.forEach(vpls -> {
213 print(vpls);
214 });
215 }
216
217 /**
218 * Removes an interface from a VPLS.
219 *
220 * @param vplsName the name of the VLPS
221 * @param ifaceName the name of the interface to remove
222 */
223 private void removeIface(String vplsName, String ifaceName) {
224 if (!vplsExists(vplsName)) {
225 print(VPLS_NOT_FOUND, vplsName);
226 return;
227 }
228 if (!ifaceExists(ifaceName)) {
229 print(IFACE_NOT_FOUND, ifaceName);
230 return;
231 }
232 String vplsNameFromIfaceName = vplsNameFromIfaceName(ifaceName);
233 if (!vplsNameFromIfaceName.equals(vplsName)) {
234 print(IFACE_NOT_ASSOCIATED, ifaceName, vplsName, vplsNameFromIfaceName);
235 return;
236 }
237 vplsConfigService.removeIface(ifaceName);
238 }
239
240 /**
241 * Sets the encapsulation type for a VPLS.
242 *
243 * @param vplsName the name of the VPLS
244 * @param encap the encapsulation type
245 */
246 private void setEncap(String vplsName, String encap) {
247 if (!vplsExists(vplsName)) {
248 print(VPLS_NOT_FOUND, vplsName);
249 return;
250 }
251 EncapsulationType encapType = EncapsulationType.enumFromString(encap);
252 if (encapType.equals(EncapsulationType.NONE) &&
253 !encapType.toString().equals(encap)) {
254 print(ENCAP_NOT_FOUND, encap);
255 return;
256 }
257 vplsConfigService.setEncap(vplsName, encap);
258 }
259
260 /**
261 * Shows the details of one or more VPLSs.
262 *
263 * @param vplsName the name of the VPLS
264 */
265 private void show(String vplsName) {
266 List<String> vplsNames = Lists.newArrayList(vplsConfigService.vplsNames());
267 Collections.sort(vplsNames);
268
269 Map<String, EncapsulationType> encapByVplsName =
270 vplsConfigService.encapByVplsName();
271
272 print(VPLS_LIST_TITLE);
273 print(SEPARATOR);
274 if (!isNullOrEmpty(vplsName)) {
275 // A VPLS name is provided. Check first if the VPLS exists
276 if (vplsExists(vplsName)) {
277 print(VPLS_DISPLAY,
278 vplsName,
279 ifacesFromVplsName(vplsName).toString(),
280 encapByVplsName.get(vplsName).toString());
281 } else {
282 print(VPLS_NOT_FOUND, vplsName);
283 }
284 } else {
285 // No VPLS names are provided. Display all VPLSs configured
286 vplsNames.forEach(v -> {
287 print(VPLS_DISPLAY,
288 v,
289 ifacesFromVplsName(v).toString(),
290 encapByVplsName.get(v).toString());
291 print(SEPARATOR);
292 });
293 }
294 }
295
296 /**
297 * States if a VPLS exists or not.
298 *
299 * @param vplsName the name of the VPLS
300 * @return true if the VPLS exists; false otherwise
301 */
302 private static boolean vplsExists(String vplsName) {
303 return vplsConfigService.vplsNames().contains(vplsName);
304 }
305
306 /**
307 * States if an interface is defined or not in the system.
308 *
309 * @param ifaceName the name of the interface
310 * @return true if the interface is defined; false otherwise
311 */
312 private static boolean ifaceExists(String ifaceName) {
313 return vplsConfigService.allIfaces()
314 .stream()
315 .anyMatch(iface -> iface.name().equals(ifaceName));
316 }
317
318 /**
319 * States if an interface is already associated to a VPLS.
320 *
321 * @param ifaceName the name of the interface
322 * @return true if the interface is already associated to a VPLS; false
323 * otherwise
324 */
325 private static boolean isIfaceAssociated(String ifaceName) {
326 return vplsConfigService.ifaces()
327 .stream()
328 .anyMatch(iface -> iface.name().equals(ifaceName));
329 }
330
331 /**
332 * Returns the name of a VPLS, given the name of an interface associated to
333 * it.
334 *
335 * @param ifaceName the name of the interface
336 * @return the name of the VPLS that has the interface configured; null if
337 * the interface does not exist or is not associated to any VPLS
338 */
339 private static String vplsNameFromIfaceName(String ifaceName) {
340 String vplsName = null;
341
342 Optional<String> optVplsName = vplsConfigService.ifacesByVplsName()
343 .entries()
344 .stream()
345 .filter((entry -> entry.getValue().name().equals(ifaceName)))
346 .map(Map.Entry::getKey)
347 .findFirst();
348
349 if (optVplsName.isPresent()) {
350 vplsName = optVplsName.get();
351 }
352
353 return vplsName;
354 }
355
356 /**
357 * Returns a list of interfaces associated to a VPLS, given a VPLS name.
358 *
359 * @param vplsName the name of the VPLS
360 * @return the set of interfaces associated to the given VPLS; null if the
361 * VPLS is not found
362 */
363 private static Set<String> ifacesFromVplsName(String vplsName) {
364 if (!vplsExists(vplsName)) {
365 return null;
366 }
367 SetMultimap<String, Interface> ifacesByVplsName =
368 vplsConfigService.ifacesByVplsName();
369 Set<String> ifaceNames = Sets.newHashSet();
370
371 ifacesByVplsName.get(vplsName).forEach(iface -> ifaceNames.add(iface.name()));
372
373 return ifaceNames;
374 }
375}