blob: 8bd31d93a88e4cfd99bca1db68a1359406f8c7b7 [file] [log] [blame]
Jian Lic87b23b2017-04-24 15:28:10 +09001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2017-present Open Networking Foundation
Jian Lic87b23b2017-04-24 15:28:10 +09003 *
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.mapping.cli;
17
Jian Lida1dfa62017-04-25 01:56:19 +090018import com.fasterxml.jackson.databind.JsonNode;
19import com.fasterxml.jackson.databind.ObjectMapper;
20import com.fasterxml.jackson.databind.node.ArrayNode;
21import com.fasterxml.jackson.databind.node.ObjectNode;
Ray Milkey86ad7bb2018-09-27 12:32:28 -070022import org.apache.karaf.shell.api.action.Argument;
23import org.apache.karaf.shell.api.action.Command;
24import org.apache.karaf.shell.api.action.Option;
Ray Milkey7a2dee52018-09-28 10:58:28 -070025import org.apache.karaf.shell.api.action.lifecycle.Service;
Jian Lic87b23b2017-04-24 15:28:10 +090026import org.onosproject.cli.AbstractShellCommand;
Jian Lida1dfa62017-04-25 01:56:19 +090027import org.onosproject.mapping.MappingEntry;
Jian Lic87b23b2017-04-24 15:28:10 +090028import org.onosproject.mapping.MappingKey;
29import org.onosproject.mapping.MappingTreatment;
30import org.onosproject.mapping.MappingValue;
31import org.onosproject.mapping.MappingService;
32import org.onosproject.mapping.MappingStore;
33import org.onosproject.net.Device;
34import org.onosproject.net.DeviceId;
35import org.onosproject.net.device.DeviceService;
36
37import java.util.List;
38
39import static com.google.common.collect.Lists.newArrayList;
40
41/**
42 * A command for querying mapping information.
43 */
Ray Milkey7a2dee52018-09-28 10:58:28 -070044@Service
Jian Lic87b23b2017-04-24 15:28:10 +090045@Command(scope = "onos", name = "mappings",
46 description = "Lists mappings")
47public class MappingsListCommand extends AbstractShellCommand {
48
Jian Li6e960ef2017-05-03 16:38:19 +090049 private static final String DB = "database";
50 private static final String CACHE = "cache";
Jian Lic87b23b2017-04-24 15:28:10 +090051
52 private static final String SUMMARY_FORMAT = "deviceId=%s, mappingCount=%d";
53 private static final String MAPPING_ID_FORMAT = " id=%s";
Jian Lida1dfa62017-04-25 01:56:19 +090054 private static final String MAPPING_STATE_FORMAT = " state=%s";
Jian Lic87b23b2017-04-24 15:28:10 +090055 private static final String MAPPING_KEY_FORMAT = " key=%s";
56 private static final String MAPPING_VALUE_FORMAT = " value=";
57 private static final String MAPPING_ACTION_FORMAT = " action=%s";
58 private static final String MAPPING_TREATMENTS_FORMAT = " treatments=";
59 private static final String MAPPING_TREATMENT_LONG_FORMAT =
60 " address=%s, instructions=%s";
61 private static final String MAPPING_TREATMENT_SHORT_FORMAT = " %s";
Jian Lida1dfa62017-04-25 01:56:19 +090062 private static final String JSON_FORMAT = "%s";
Jian Lic87b23b2017-04-24 15:28:10 +090063
Jian Li6e960ef2017-05-03 16:38:19 +090064 private static final String TYPE_NOT_NULL = "Mapping store type should not be null";
65 private static final String TYPE_ILLEGAL = "Mapping store type is not correct";
66
Jian Lic87b23b2017-04-24 15:28:10 +090067 @Argument(index = 0, name = "type",
68 description = "Shows mappings with specified type",
69 required = true, multiValued = false)
70 private String type = null;
71
72 @Argument(index = 1, name = "deviceId", description = "Device identity",
73 required = false, multiValued = false)
74 private String deviceId = null;
75
76 @Option(name = "-s", aliases = "--short",
77 description = "Print more succinct output for each mapping",
78 required = false, multiValued = false)
79 private boolean shortOutput = false;
80
81 private MappingService mappingService =
82 AbstractShellCommand.get(MappingService.class);
Jian Lida1dfa62017-04-25 01:56:19 +090083 private List<MappingEntry> mappings;
Jian Lic87b23b2017-04-24 15:28:10 +090084
85 @Override
Ray Milkey86ad7bb2018-09-27 12:32:28 -070086 protected void doExecute() {
Jian Lic87b23b2017-04-24 15:28:10 +090087
Jian Li6e960ef2017-05-03 16:38:19 +090088 MappingStore.Type typeEnum = getTypeEnum(type);
Jian Lic87b23b2017-04-24 15:28:10 +090089
90 DeviceService deviceService = get(DeviceService.class);
91 Iterable<Device> devices = deviceService.getDevices();
92
Jian Lida1dfa62017-04-25 01:56:19 +090093 if (outputJson()) {
94 print(JSON_FORMAT, json(typeEnum, devices));
Jian Lic87b23b2017-04-24 15:28:10 +090095 } else {
Jian Lida1dfa62017-04-25 01:56:19 +090096 if (deviceId != null) {
97 mappings = newArrayList(mappingService.getMappingEntries(typeEnum,
98 DeviceId.deviceId(deviceId)));
99 printMappings(DeviceId.deviceId(deviceId), mappings);
Jian Lic87b23b2017-04-24 15:28:10 +0900100
Jian Lida1dfa62017-04-25 01:56:19 +0900101 } else {
102
103 for (Device d : devices) {
104 mappings = newArrayList(mappingService.getMappingEntries(typeEnum, d.id()));
105 printMappings(d.id(), mappings);
106 }
Jian Lic87b23b2017-04-24 15:28:10 +0900107 }
108 }
109 }
110
111 /**
112 * Prints out mapping information.
113 *
114 * @param deviceId device identifier
115 * @param mappings a collection of mapping
116 */
Jian Lida1dfa62017-04-25 01:56:19 +0900117 private void printMappings(DeviceId deviceId, List<MappingEntry> mappings) {
Jian Lic87b23b2017-04-24 15:28:10 +0900118
119 print(SUMMARY_FORMAT, deviceId, mappings.size());
120
Jian Lida1dfa62017-04-25 01:56:19 +0900121 for (MappingEntry m : mappings) {
Jian Lic87b23b2017-04-24 15:28:10 +0900122 print(MAPPING_ID_FORMAT, Long.toHexString(m.id().value()));
Jian Lida1dfa62017-04-25 01:56:19 +0900123 print(MAPPING_STATE_FORMAT, m.state().name());
Jian Lic87b23b2017-04-24 15:28:10 +0900124 print(MAPPING_KEY_FORMAT, printMappingKey(m.key()));
125 printMappingValue(m.value());
126 }
127 }
128
129 /**
130 * Prints out mapping key.
131 *
132 * @param key mapping key
133 * @return string format of mapping key
134 */
135 private String printMappingKey(MappingKey key) {
136 StringBuilder builder = new StringBuilder();
137
138 if (key.address() != null) {
139 builder.append(key.address().toString());
140 }
141
142 return builder.toString();
143 }
144
145 /**
146 * Prints out mapping value.
147 *
148 * @param value mapping value
149 * @return string format of mapping value
150 */
151 private void printMappingValue(MappingValue value) {
152
153 print(MAPPING_VALUE_FORMAT);
154
155 if (value.action() != null) {
156 print(MAPPING_ACTION_FORMAT, value.action().toString());
157 }
158
159 if (!value.treatments().isEmpty()) {
160 print(MAPPING_TREATMENTS_FORMAT);
161 for (MappingTreatment treatment : value.treatments()) {
162 printMappingTreatment(treatment);
163 }
164 }
165
166 }
167
168 /**
169 * Prints out mapping treatment.
170 *
171 * @param treatment mapping treatment
172 * @return string format of mapping treatment
173 */
174 private void printMappingTreatment(MappingTreatment treatment) {
175 if (treatment != null) {
176 if (shortOutput) {
177 print(MAPPING_TREATMENT_SHORT_FORMAT, treatment.address());
178 } else {
179 print(MAPPING_TREATMENT_LONG_FORMAT, treatment.address(),
180 treatment.instructions());
181 }
182 }
183 }
Jian Lida1dfa62017-04-25 01:56:19 +0900184
185 /**
Jian Li6e960ef2017-05-03 16:38:19 +0900186 * Returns corresponding type enumeration based on the given
187 * string formatted type.
188 *
189 * @param type string formatted type
190 * @return type enumeration
191 */
192 private MappingStore.Type getTypeEnum(String type) {
193
194 if (type == null) {
195 throw new IllegalArgumentException(TYPE_NOT_NULL);
196 }
197
198 switch (type) {
199 case DB:
200 return MappingStore.Type.MAP_DATABASE;
201 case CACHE:
202 return MappingStore.Type.MAP_CACHE;
203 default:
204 throw new IllegalArgumentException(TYPE_ILLEGAL);
205 }
206 }
207
208 /**
Jian Lida1dfa62017-04-25 01:56:19 +0900209 * Generates JSON object with the mappings of the given device.
210 *
211 * @param mapper object mapper
212 * @param device device
213 * @param mappings a collection of mappings
214 * @return JSON object
215 */
216 private ObjectNode json(ObjectMapper mapper, Device device, List<MappingEntry> mappings) {
217 ObjectNode result = mapper.createObjectNode();
218 ArrayNode array = mapper.createArrayNode();
219
220 mappings.forEach(mapping -> array.add(jsonForEntity(mapping, MappingEntry.class)));
221
222 result.put("device", device.id().toString())
223 .put("mappingCount", mappings.size())
224 .set("mappings", array);
225 return result;
226 }
227
228 /**
229 * Generates JSON object with the mappings of all devices.
230 *
231 * @param type mapping store type
232 * @param devices a collection of devices
233 * @return JSON object
234 */
235 private JsonNode json(MappingStore.Type type, Iterable<Device> devices) {
236 ObjectMapper mapper = new ObjectMapper();
237 ArrayNode result = mapper.createArrayNode();
238 for (Device device : devices) {
239 result.add(json(mapper, device,
240 newArrayList(mappingService.getMappingEntries(type, device.id()))));
241 }
242 return result;
243 }
244}