blob: f9e062b002204f7263d1ecd5e1c8dbcdfb952096 [file] [log] [blame]
Thomas Vachuska0d933862018-04-06 00:29:30 -07001/*
2 * Copyright 2018-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 */
16
17package org.onosproject.layout;
18
19import com.google.common.base.MoreObjects;
20import com.google.common.collect.ArrayListMultimap;
21import com.google.common.collect.ListMultimap;
22import org.onosproject.net.Device;
23import org.onosproject.net.DeviceId;
24import org.onosproject.net.ElementId;
25import org.onosproject.net.Host;
26import org.onosproject.net.HostId;
27import org.onosproject.net.config.NetworkConfigService;
28import org.onosproject.net.config.basics.BasicDeviceConfig;
29import org.onosproject.net.config.basics.BasicHostConfig;
30import org.onosproject.net.device.DeviceService;
31import org.onosproject.net.host.HostService;
32import org.onosproject.net.link.LinkService;
33
34import java.util.Collection;
35
36/**
37 * Represents a topology layout algorithm.
38 */
39public abstract class LayoutAlgorithm {
40
41 public static final String SPINE = "spine";
42 public static final String AGGREGATION = "aggregation";
43 public static final String LEAF = "leaf";
44 public static final String ACCESS = "access";
45 public static final String GATEWAY = "gateway";
46 public static final String COMPUTE = "compute";
47
48 protected DeviceService deviceService;
49 protected HostService hostService;
50 protected LinkService linkService;
51 protected NetworkConfigService netConfigService;
52
53 protected ListMultimap<String, DeviceId> deviceCategories = ArrayListMultimap.create();
54 protected ListMultimap<String, HostId> hostCategories = ArrayListMultimap.create();
55
56
57 /**
58 * Initializes layout algorithm for operating on device and host inventory.
59 *
60 * @param deviceService device service
61 * @param hostService host service
62 * @param linkService link service
63 * @param networkConfigService net config service
64 */
65 protected void init(DeviceService deviceService,
66 HostService hostService,
67 LinkService linkService,
68 NetworkConfigService networkConfigService) {
69 this.deviceService = deviceService;
70 this.hostService = hostService;
71 this.linkService = linkService;
72 this.netConfigService = networkConfigService;
73 }
74
75 /**
76 * Places the specified device on the layout grid.
77 *
78 * @param id device identifier
79 * @param x grid X
80 * @param y grid Y
81 */
82 protected void place(DeviceId id, double x, double y) {
83 netConfigService.addConfig(id, BasicDeviceConfig.class)
84 .gridX(x).gridY(y).locType("grid").apply();
85 }
86
87 /**
88 * Places the specified device on the layout grid.
89 *
90 * @param id host identifier
91 * @param x grid X
92 * @param y grid Y
93 */
94 protected void place(HostId id, double x, double y) {
95 netConfigService.addConfig(id, BasicHostConfig.class)
96 .gridX(x).gridY(y).locType("grid").apply();
97 }
98
99 /**
100 * Computes grid coordinate for the i-th element of n-elements in a tier
101 * using a default gap of 400.
102 *
103 * @param i element index
104 * @param n number of elements
105 * @return grid Y
106 */
107 protected double c(int i, int n) {
108 return c(i, n, 400);
109 }
110
111 /**
112 * Computes grid coordinate for the i-th element of n-elements in a tier.
113 *
114 * @param i element index
115 * @param n number of elements
116 * @param gap gap width
117 * @return grid Y
118 */
119 protected double c(int i, int n, double gap) {
120 return c(i, n, gap, 0);
121 }
122
123 /**
124 * Computes grid coordinate for the i-th element of n-elements in a tier.
125 *
126 * @param i element index
127 * @param n number of elements
128 * @param gap gap width
129 * @param offset additional Y offset
130 * @return grid Y
131 */
132 protected double c(int i, int n, double gap, double offset) {
133 return gap * (i - 1) - (gap * (n - 1)) / 2 + offset;
134 }
135
136 /**
137 * Places the specified collection of hosts (all presumably connected to
138 * the same network device) in a block.
139 *
140 * @param hosts hosts to place
141 * @param gridX grid X of the top of the block
142 * @param gridY grid Y of the center of the block
143 * @param hostsPerRow number of hosts in a 'row'
144 * @param rowGap gap width between rows
145 * @param colGap gap width between columns
146 */
147 protected void placeHostBlock(Collection<HostId> hosts,
148 double gridX, double gridY, int hostsPerRow,
149 double rowGap, double colGap) {
150 double yStep = rowGap / hostsPerRow;
151 double y = gridY;
152 double x = gridX - (colGap * (hostsPerRow - 1)) / 2;
153 int i = 1;
154
155 for (HostId id : hosts) {
156 place(id, x, y);
157 if ((i % hostsPerRow) == 0) {
158 x = gridX - (colGap * (hostsPerRow - 1)) / 2;
159 } else {
160 x += colGap;
161 y += yStep;
162 }
163 i++;
164 }
165 }
166
167 /**
168 * Applies device and host classifications.
169 */
170 public void classify() {
171 deviceService.getDevices().forEach(this::classify);
172 hostService.getHosts().forEach(this::classify);
173 }
174
175 /**
176 * Classifies the specified device.
177 *
178 * @param device device to be classified
179 * @return true if classified
180 */
181 protected boolean classify(Device device) {
182 BasicDeviceConfig cfg = netConfigService.getConfig(device.id(), BasicDeviceConfig.class);
183 if (cfg != null && !cfg.roles().isEmpty()) {
184 cfg.roles().forEach(r -> deviceCategories.put(r, device.id()));
185 return true;
186 }
187 return false;
188 }
189
190 /**
191 * Classifies the specified host.
192 *
193 * @param host host to be classified
194 * @return true if classified
195 */
196 protected boolean classify(Host host) {
197 BasicHostConfig cfg = netConfigService.getConfig(host.id(), BasicHostConfig.class);
198 if (cfg != null && !cfg.roles().isEmpty()) {
199 cfg.roles().forEach(r -> hostCategories.put(r, host.id()));
200 return true;
201 }
202 return false;
203 }
204
205
206 /**
207 * Applies the specified layout algorithm.
208 */
209 abstract void apply();
210
211 @Override
212 public String toString() {
213 return MoreObjects.toStringHelper(this)
214 .add("deviceCategories", count(deviceCategories))
215 .add("hostCategories", count(hostCategories))
216 .toString();
217 }
218
219 private String count(ListMultimap<String, ? extends ElementId> categories) {
220 StringBuilder sb = new StringBuilder("[ ");
221 categories.keySet().forEach(k -> sb.append(k).append("=").append(categories.get(k).size()).append(" "));
222 return sb.append("]").toString();
223 }
224
225}