blob: 24759378d44e0608f84a9e11da4a2d23afbb9237 [file] [log] [blame]
Thomas Vachuskae586b792015-03-26 13:59:38 -07001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2015-present Open Networking Laboratory
Thomas Vachuskae586b792015-03-26 13:59:38 -07003 *
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.ui.impl;
17
Simon Hunt86943082017-06-15 13:18:42 -070018import com.fasterxml.jackson.databind.node.ArrayNode;
Thomas Vachuskae586b792015-03-26 13:59:38 -070019import com.fasterxml.jackson.databind.node.ObjectNode;
20import com.google.common.collect.ImmutableSet;
Bri Prebilic Cole9467a232015-05-06 16:59:05 -070021import org.onlab.packet.IpAddress;
Thomas Vachuska58eded62015-03-31 12:04:03 -070022import org.onosproject.net.AnnotationKeys;
Bri Prebilic Cole19a32dd2015-03-26 18:00:03 -070023import org.onosproject.net.Host;
Simon Hunt86943082017-06-15 13:18:42 -070024import org.onosproject.net.HostId;
25import org.onosproject.net.HostLocation;
Simon Hunt10618f62017-06-15 19:30:52 -070026import org.onosproject.net.config.NetworkConfigService;
27import org.onosproject.net.config.basics.BasicHostConfig;
Bri Prebilic Cole19a32dd2015-03-26 18:00:03 -070028import org.onosproject.net.host.HostService;
Simon Huntd2747a02015-04-30 22:41:16 -070029import org.onosproject.ui.RequestHandler;
Simon Hunta0ddb022015-05-01 09:53:01 -070030import org.onosproject.ui.UiMessageHandler;
Bri Prebilic Cole9467a232015-05-06 16:59:05 -070031import org.onosproject.ui.table.CellFormatter;
Simon Hunt3d1b0652015-05-05 17:27:24 -070032import org.onosproject.ui.table.TableModel;
Simon Huntabd16f62015-05-01 13:14:40 -070033import org.onosproject.ui.table.TableRequestHandler;
Simon Hunt3d1b0652015-05-05 17:27:24 -070034import org.onosproject.ui.table.cell.HostLocationFormatter;
Simon Hunt86943082017-06-15 13:18:42 -070035import org.slf4j.Logger;
36import org.slf4j.LoggerFactory;
Thomas Vachuskae586b792015-03-26 13:59:38 -070037
Simon Hunt86943082017-06-15 13:18:42 -070038import java.util.ArrayList;
Simon Huntd2747a02015-04-30 22:41:16 -070039import java.util.Collection;
Simon Hunt86943082017-06-15 13:18:42 -070040import java.util.Collections;
Simon Hunt10618f62017-06-15 19:30:52 -070041import java.util.Iterator;
Simon Hunt86943082017-06-15 13:18:42 -070042import java.util.List;
Bri Prebilic Cole9467a232015-05-06 16:59:05 -070043import java.util.Set;
Thomas Vachuskae586b792015-03-26 13:59:38 -070044
Simon Hunt10618f62017-06-15 19:30:52 -070045import static com.google.common.base.Strings.emptyToNull;
Thomas Vachuska58eded62015-03-31 12:04:03 -070046import static com.google.common.base.Strings.isNullOrEmpty;
Simon Hunt86943082017-06-15 13:18:42 -070047import static org.onosproject.net.HostId.hostId;
Thomas Vachuska58eded62015-03-31 12:04:03 -070048
Thomas Vachuskae586b792015-03-26 13:59:38 -070049/**
50 * Message handler for host view related messages.
51 */
Simon Hunta0ddb022015-05-01 09:53:01 -070052public class HostViewMessageHandler extends UiMessageHandler {
Thomas Vachuskae586b792015-03-26 13:59:38 -070053
Simon Huntd2747a02015-04-30 22:41:16 -070054 private static final String HOST_DATA_REQ = "hostDataRequest";
Simon Huntabd16f62015-05-01 13:14:40 -070055 private static final String HOST_DATA_RESP = "hostDataResponse";
56 private static final String HOSTS = "hosts";
57
Simon Hunt86943082017-06-15 13:18:42 -070058 private static final String HOST_DETAILS_REQ = "hostDetailsRequest";
59 private static final String HOST_DETAILS_RESP = "hostDetailsResponse";
60 private static final String DETAILS = "details";
61
62 private static final String HOST_NAME_CHANGE_REQ = "hostNameChangeRequest";
63 private static final String HOST_NAME_CHANGE_RESP = "hostNameChangeResponse";
64
Simon Huntabd16f62015-05-01 13:14:40 -070065 private static final String TYPE_IID = "_iconid_type";
Simon Hunt86943082017-06-15 13:18:42 -070066 private static final String NAME = "name";
Simon Huntabd16f62015-05-01 13:14:40 -070067 private static final String ID = "id";
68 private static final String MAC = "mac";
69 private static final String VLAN = "vlan";
Simon Hunt10618f62017-06-15 19:30:52 -070070 private static final String IP = "ip";
Simon Huntabd16f62015-05-01 13:14:40 -070071 private static final String IPS = "ips";
72 private static final String LOCATION = "location";
Simon Hunt86943082017-06-15 13:18:42 -070073 private static final String LOCATIONS = "locations";
74 private static final String CONFIGURED = "configured";
75
Simon Hunt10618f62017-06-15 19:30:52 -070076 private static final String DASH = "-";
Simon Huntabd16f62015-05-01 13:14:40 -070077
78 private static final String HOST_ICON_PREFIX = "hostIcon_";
Simon Huntd2747a02015-04-30 22:41:16 -070079
Simon Hunt3d1b0652015-05-05 17:27:24 -070080 private static final String[] COL_IDS = {
Simon Hunt86943082017-06-15 13:18:42 -070081 TYPE_IID, NAME, ID, MAC, VLAN, CONFIGURED, IPS, LOCATION
Simon Hunt3d1b0652015-05-05 17:27:24 -070082 };
Thomas Vachuskae586b792015-03-26 13:59:38 -070083
Simon Hunt86943082017-06-15 13:18:42 -070084 private final Logger log = LoggerFactory.getLogger(getClass());
85
Thomas Vachuskae586b792015-03-26 13:59:38 -070086 @Override
Simon Huntda580882015-05-12 20:58:18 -070087 protected Collection<RequestHandler> createRequestHandlers() {
Simon Hunt86943082017-06-15 13:18:42 -070088 return ImmutableSet.of(
89 new HostDataRequest(),
90 new DetailRequestHandler(),
91 new NameChangeHandler()
92 );
93 }
94
95 private String getTypeIconId(Host host) {
96 String hostType = host.annotations().value(AnnotationKeys.TYPE);
97 return HOST_ICON_PREFIX +
98 (isNullOrEmpty(hostType) ? "endstation" : hostType);
99 }
100
Simon Hunt10618f62017-06-15 19:30:52 -0700101 // Returns the first of the given set of IP addresses as a string.
102 private String ip(Set<IpAddress> ipAddresses) {
103 Iterator<IpAddress> it = ipAddresses.iterator();
104 return it.hasNext() ? it.next().toString() : "unknown";
105 }
106
107 private boolean useDefaultName(String nameAnnotated) {
108 return isNullOrEmpty(nameAnnotated) || DASH.equals(nameAnnotated);
109 }
110
Simon Hunt86943082017-06-15 13:18:42 -0700111 // returns the "friendly name" for the host
112 private String getHostName(Host host) {
Simon Hunt10618f62017-06-15 19:30:52 -0700113 String name = host.annotations().value(AnnotationKeys.NAME);
114 return useDefaultName(name) ? ip(host.ipAddresses()) : name;
Simon Huntd2747a02015-04-30 22:41:16 -0700115 }
116
Simon Huntabd16f62015-05-01 13:14:40 -0700117 // handler for host table requests
118 private final class HostDataRequest extends TableRequestHandler {
Jian Li69f66632016-01-15 12:27:42 -0800119 private static final String NO_ROWS_MESSAGE = "No hosts found";
120
Simon Huntd2747a02015-04-30 22:41:16 -0700121 private HostDataRequest() {
Simon Huntabd16f62015-05-01 13:14:40 -0700122 super(HOST_DATA_REQ, HOST_DATA_RESP, HOSTS);
Simon Huntd2747a02015-04-30 22:41:16 -0700123 }
124
125 @Override
Simon Hunt3d1b0652015-05-05 17:27:24 -0700126 protected String[] getColumnIds() {
127 return COL_IDS;
Simon Hunt44aa2f82015-04-30 15:01:35 -0700128 }
Simon Hunt44aa2f82015-04-30 15:01:35 -0700129
Simon Hunt3d1b0652015-05-05 17:27:24 -0700130 @Override
Jian Li8baf4472016-01-15 15:08:09 -0800131 protected String noRowsMessage(ObjectNode payload) {
Jian Li69f66632016-01-15 12:27:42 -0800132 return NO_ROWS_MESSAGE;
133 }
134
135 @Override
Simon Hunt3d1b0652015-05-05 17:27:24 -0700136 protected TableModel createTableModel() {
137 TableModel tm = super.createTableModel();
138 tm.setFormatter(LOCATION, HostLocationFormatter.INSTANCE);
Bri Prebilic Cole9467a232015-05-06 16:59:05 -0700139 tm.setFormatter(IPS, new IpSetFormatter());
Simon Hunt3d1b0652015-05-05 17:27:24 -0700140 return tm;
141 }
Thomas Vachuskae586b792015-03-26 13:59:38 -0700142
Simon Hunt3d1b0652015-05-05 17:27:24 -0700143 @Override
144 protected void populateTable(TableModel tm, ObjectNode payload) {
145 HostService hs = get(HostService.class);
146 for (Host host : hs.getHosts()) {
147 populateRow(tm.addRow(), host);
148 }
149 }
Thomas Vachuskae586b792015-03-26 13:59:38 -0700150
Simon Hunt3d1b0652015-05-05 17:27:24 -0700151 private void populateRow(TableModel.Row row, Host host) {
152 row.cell(TYPE_IID, getTypeIconId(host))
Simon Hunt86943082017-06-15 13:18:42 -0700153 .cell(NAME, getHostName(host))
Simon Hunt3d1b0652015-05-05 17:27:24 -0700154 .cell(ID, host.id())
155 .cell(MAC, host.mac())
156 .cell(VLAN, host.vlan())
Simon Hunt86943082017-06-15 13:18:42 -0700157 .cell(CONFIGURED, host.configured())
Simon Hunt3d1b0652015-05-05 17:27:24 -0700158 .cell(IPS, host.ipAddresses())
159 .cell(LOCATION, host.location());
Simon Hunt86943082017-06-15 13:18:42 -0700160 // Note: leave complete list of all LOCATIONS to the details panel
Thomas Vachuska58eded62015-03-31 12:04:03 -0700161 }
Bri Prebilic Cole9467a232015-05-06 16:59:05 -0700162
163 private final class IpSetFormatter implements CellFormatter {
164 private static final String COMMA = ", ";
165
166 @Override
167 public String format(Object value) {
168 Set<IpAddress> ips = (Set<IpAddress>) value;
169 if (ips.isEmpty()) {
Simon Hunt10618f62017-06-15 19:30:52 -0700170 return "(No IP Addresses)";
Bri Prebilic Cole9467a232015-05-06 16:59:05 -0700171 }
172 StringBuilder sb = new StringBuilder();
173 for (IpAddress ip : ips) {
174 sb.append(ip.toString())
175 .append(COMMA);
176 }
Simon Hunt86943082017-06-15 13:18:42 -0700177 return removeTrailingComma(sb).toString();
Bri Prebilic Cole9467a232015-05-06 16:59:05 -0700178 }
179
180 private StringBuilder removeTrailingComma(StringBuilder sb) {
181 int pos = sb.lastIndexOf(COMMA);
182 sb.delete(pos, sb.length());
183 return sb;
184 }
185 }
Thomas Vachuskae586b792015-03-26 13:59:38 -0700186 }
Simon Hunt86943082017-06-15 13:18:42 -0700187
188
189 private final class DetailRequestHandler extends RequestHandler {
190 private DetailRequestHandler() {
191 super(HOST_DETAILS_REQ);
192 }
193
194 @Override
195 public void process(ObjectNode payload) {
196 String id = string(payload, ID, "");
197
198 HostId hostId = hostId(id);
199 HostService service = get(HostService.class);
200 Host host = service.getHost(hostId);
201 ObjectNode data = objectNode();
202
203 data.put(TYPE_IID, getTypeIconId(host))
204 .put(NAME, getHostName(host))
205 .put(ID, hostId.toString())
Simon Hunt10618f62017-06-15 19:30:52 -0700206 .put(IP, ip(host.ipAddresses()))
Simon Hunt86943082017-06-15 13:18:42 -0700207 .put(MAC, host.mac().toString())
208 .put(VLAN, host.vlan().toString())
209 .put(CONFIGURED, host.configured())
210 .put(LOCATION, host.location().toString());
211
212 List<IpAddress> sortedIps = new ArrayList<>(host.ipAddresses());
213 Collections.sort(sortedIps);
214 ArrayNode ips = arrayNode();
215 for (IpAddress ip : sortedIps) {
216 ips.add(ip.toString());
217 }
218 data.set(IPS, ips);
219
220 List<HostLocation> sortedLocs = new ArrayList<>(host.locations());
221 Collections.sort(sortedLocs);
222 ArrayNode locs = arrayNode();
223 for (HostLocation hl : sortedLocs) {
224 locs.add(hl.toString());
225 }
226 data.set(LOCATIONS, locs);
227
228 ObjectNode root = objectNode();
229 root.set(DETAILS, data);
230
231 sendMessage(HOST_DETAILS_RESP, root);
232 }
233 }
234
235 private final class NameChangeHandler extends RequestHandler {
Simon Hunt10618f62017-06-15 19:30:52 -0700236 private NameChangeHandler() {
Simon Hunt86943082017-06-15 13:18:42 -0700237 super(HOST_NAME_CHANGE_REQ);
238 }
239
240 @Override
241 public void process(ObjectNode payload) {
Simon Hunt10618f62017-06-15 19:30:52 -0700242 HostId hostId = hostId(string(payload, ID, ""));
243 String name = emptyToNull(string(payload, NAME, null));
244 log.debug("Name change request: {} -- '{}'", hostId, name);
Simon Hunt86943082017-06-15 13:18:42 -0700245
Simon Hunt10618f62017-06-15 19:30:52 -0700246 NetworkConfigService service = get(NetworkConfigService.class);
247 BasicHostConfig cfg =
248 service.addConfig(hostId, BasicHostConfig.class);
Simon Hunt86943082017-06-15 13:18:42 -0700249
Simon Hunt10618f62017-06-15 19:30:52 -0700250 // Name attribute missing from the payload (or empty string)
251 // means that the friendly name should be unset.
252 cfg.name(name);
253 cfg.apply();
254 sendMessage(HOST_NAME_CHANGE_RESP, payload);
Simon Hunt86943082017-06-15 13:18:42 -0700255 }
256 }
Thomas Vachuskae586b792015-03-26 13:59:38 -0700257}