blob: d32a071da031ce6e2e1ffed7c149a359781fadb7 [file] [log] [blame]
Jian Li23c8be22018-02-13 11:34:15 +09001/*
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 */
16package org.onosproject.openstacknode.codec;
17
Jian Lie6312162018-03-21 21:41:00 +090018import com.fasterxml.jackson.databind.JsonNode;
19import com.fasterxml.jackson.databind.node.ArrayNode;
Jian Li23c8be22018-02-13 11:34:15 +090020import com.fasterxml.jackson.databind.node.ObjectNode;
21import org.onlab.packet.IpAddress;
22import org.onosproject.codec.CodecContext;
23import org.onosproject.codec.JsonCodec;
24import org.onosproject.net.DeviceId;
Jian Li789fadb2018-07-10 13:59:47 +090025import org.onosproject.net.behaviour.ControllerInfo;
26import org.onosproject.openstacknode.api.DefaultOpenstackNode;
Daniel Parkd02d7bd2018-08-23 23:04:31 +090027import org.onosproject.openstacknode.api.DpdkConfig;
Jian Lic704b672018-09-04 18:52:53 +090028import org.onosproject.openstacknode.api.KeystoneConfig;
29import org.onosproject.openstacknode.api.NeutronConfig;
Jian Li23c8be22018-02-13 11:34:15 +090030import org.onosproject.openstacknode.api.NodeState;
Jian Li27841662018-04-14 01:59:47 +090031import org.onosproject.openstacknode.api.OpenstackAuth;
Jian Li23c8be22018-02-13 11:34:15 +090032import org.onosproject.openstacknode.api.OpenstackNode;
Jian Lie6312162018-03-21 21:41:00 +090033import org.onosproject.openstacknode.api.OpenstackPhyInterface;
Daniel Parkdeefa702018-07-17 17:55:51 +090034import org.onosproject.openstacknode.api.OpenstackSshAuth;
Jian Lic704b672018-09-04 18:52:53 +090035import org.onosproject.openstacknode.api.DefaultKeystoneConfig;
Jian Li23c8be22018-02-13 11:34:15 +090036import org.slf4j.Logger;
37
Jian Lie6312162018-03-21 21:41:00 +090038import java.util.ArrayList;
39import java.util.List;
40import java.util.stream.IntStream;
41
Jian Li23c8be22018-02-13 11:34:15 +090042import static com.google.common.base.Preconditions.checkNotNull;
43import static org.onlab.util.Tools.nullIsIllegal;
Jian Li27841662018-04-14 01:59:47 +090044import static org.onosproject.openstacknode.api.Constants.CONTROLLER;
Jian Li23c8be22018-02-13 11:34:15 +090045import static org.onosproject.openstacknode.api.Constants.DATA_IP;
46import static org.onosproject.openstacknode.api.Constants.GATEWAY;
47import static org.onosproject.openstacknode.api.Constants.HOST_NAME;
48import static org.onosproject.openstacknode.api.Constants.MANAGEMENT_IP;
49import static org.onosproject.openstacknode.api.Constants.UPLINK_PORT;
50import static org.onosproject.openstacknode.api.Constants.VLAN_INTF_NAME;
51import static org.slf4j.LoggerFactory.getLogger;
52
53/**
54 * Openstack node codec used for serializing and de-serializing JSON string.
55 */
56public final class OpenstackNodeCodec extends JsonCodec<OpenstackNode> {
57
58 private final Logger log = getLogger(getClass());
59
60 private static final String TYPE = "type";
61 private static final String INTEGRATION_BRIDGE = "integrationBridge";
Jian Li5ca0be82018-02-27 13:08:04 +090062 private static final String STATE = "state";
Jian Lie6312162018-03-21 21:41:00 +090063 private static final String PHYSICAL_INTERFACES = "phyIntfs";
Jian Li789fadb2018-07-10 13:59:47 +090064 private static final String CONTROLLERS = "controllers";
Jian Lic704b672018-09-04 18:52:53 +090065 private static final String KEYSTONE_CONFIG = "keystoneConfig";
66 private static final String ENDPOINT = "endpoint";
Jian Li27841662018-04-14 01:59:47 +090067 private static final String AUTHENTICATION = "authentication";
Jian Lic704b672018-09-04 18:52:53 +090068 private static final String NEUTRON_CONFIG = "neutronConfig";
Daniel Parkdeefa702018-07-17 17:55:51 +090069 private static final String SSH_AUTH = "sshAuth";
Daniel Parkd02d7bd2018-08-23 23:04:31 +090070 private static final String DPDK_CONFIG = "dpdkConfig";
Jian Li23c8be22018-02-13 11:34:15 +090071
72 private static final String MISSING_MESSAGE = " is required in OpenstackNode";
73
74 @Override
75 public ObjectNode encode(OpenstackNode node, CodecContext context) {
76 checkNotNull(node, "Openstack node cannot be null");
77
78 ObjectNode result = context.mapper().createObjectNode()
79 .put(HOST_NAME, node.hostname())
80 .put(TYPE, node.type().name())
Jian Li92d42fc2018-05-25 16:23:49 +090081 .put(STATE, node.state().name())
Daniel Parkd02d7bd2018-08-23 23:04:31 +090082 .put(MANAGEMENT_IP, node.managementIp().toString());
Jian Li23c8be22018-02-13 11:34:15 +090083
84 OpenstackNode.NodeType type = node.type();
85
86 if (type == OpenstackNode.NodeType.GATEWAY) {
87 result.put(UPLINK_PORT, node.uplinkPort());
88 }
89
Jian Lie3141542018-08-13 18:05:43 +090090 if (type == OpenstackNode.NodeType.CONTROLLER) {
Jian Lic704b672018-09-04 18:52:53 +090091
92 ObjectNode keystoneConfigJson = context.codec(KeystoneConfig.class)
93 .encode(node.keystoneConfig(), context);
94
95 result.set(KEYSTONE_CONFIG, keystoneConfigJson);
96 }
97
98 if (node.neutronConfig() != null) {
99 ObjectNode neutronConfigJson = context.codec(NeutronConfig.class)
100 .encode(node.neutronConfig(), context);
101
102 result.set(NEUTRON_CONFIG, neutronConfigJson);
Jian Li27841662018-04-14 01:59:47 +0900103 }
104
Jian Lie3141542018-08-13 18:05:43 +0900105 if (node.intgBridge() != null) {
106 result.put(INTEGRATION_BRIDGE, node.intgBridge().toString());
107 }
108
Jian Li23c8be22018-02-13 11:34:15 +0900109 if (node.vlanIntf() != null) {
110 result.put(VLAN_INTF_NAME, node.vlanIntf());
111 }
112
113 if (node.dataIp() != null) {
114 result.put(DATA_IP, node.dataIp().toString());
115 }
116
Jian Lie6312162018-03-21 21:41:00 +0900117 ArrayNode phyIntfs = context.mapper().createArrayNode();
118 node.phyIntfs().forEach(phyIntf -> {
Jian Lic704b672018-09-04 18:52:53 +0900119 ObjectNode phyIntfJson =
120 context.codec(OpenstackPhyInterface.class).encode(phyIntf, context);
Jian Lie6312162018-03-21 21:41:00 +0900121 phyIntfs.add(phyIntfJson);
122 });
123 result.set(PHYSICAL_INTERFACES, phyIntfs);
124
Jian Li789fadb2018-07-10 13:59:47 +0900125 ArrayNode controllers = context.mapper().createArrayNode();
126 node.controllers().forEach(controller -> {
Jian Lic704b672018-09-04 18:52:53 +0900127 ObjectNode controllerJson =
128 context.codec(ControllerInfo.class).encode(controller, context);
Jian Li789fadb2018-07-10 13:59:47 +0900129 controllers.add(controllerJson);
130 });
131
Daniel Parkdeefa702018-07-17 17:55:51 +0900132 if (node.sshAuthInfo() != null) {
133 ObjectNode sshAuthJson = context.codec(OpenstackSshAuth.class)
134 .encode(node.sshAuthInfo(), context);
135 result.set(SSH_AUTH, sshAuthJson);
Jian Li27841662018-04-14 01:59:47 +0900136 }
137
Daniel Parkd02d7bd2018-08-23 23:04:31 +0900138 if (node.dpdkConfig() != null) {
139 ObjectNode dpdkConfigJson = context.codec(DpdkConfig.class)
140 .encode(node.dpdkConfig(), context);
141 result.set(DPDK_CONFIG, dpdkConfigJson);
Daniel Park7e8c4d82018-08-13 23:47:49 +0900142 }
143
Jian Li23c8be22018-02-13 11:34:15 +0900144 return result;
145 }
146
147 @Override
148 public OpenstackNode decode(ObjectNode json, CodecContext context) {
149 if (json == null || !json.isObject()) {
150 return null;
151 }
152
153 String hostname = nullIsIllegal(json.get(HOST_NAME).asText(),
154 HOST_NAME + MISSING_MESSAGE);
155 String type = nullIsIllegal(json.get(TYPE).asText(),
156 TYPE + MISSING_MESSAGE);
Jian Li92d42fc2018-05-25 16:23:49 +0900157 String mIp = nullIsIllegal(json.get(MANAGEMENT_IP).asText(),
158 MANAGEMENT_IP + MISSING_MESSAGE);
Jian Li23c8be22018-02-13 11:34:15 +0900159
160 DefaultOpenstackNode.Builder nodeBuilder = DefaultOpenstackNode.builder()
161 .hostname(hostname)
162 .type(OpenstackNode.NodeType.valueOf(type))
Jian Li92d42fc2018-05-25 16:23:49 +0900163 .state(NodeState.INIT)
164 .managementIp(IpAddress.valueOf(mIp));
Jian Li23c8be22018-02-13 11:34:15 +0900165
166 if (type.equals(GATEWAY)) {
167 nodeBuilder.uplinkPort(nullIsIllegal(json.get(UPLINK_PORT).asText(),
168 UPLINK_PORT + MISSING_MESSAGE));
169 }
Jian Lie3141542018-08-13 18:05:43 +0900170 if (type.equals(CONTROLLER)) {
Jian Lic704b672018-09-04 18:52:53 +0900171
172 JsonNode keystoneConfigJson = json.get(KEYSTONE_CONFIG);
173
174 KeystoneConfig keystoneConfig;
175 if (keystoneConfigJson != null) {
176 final JsonCodec<KeystoneConfig> keystoneConfigCodec =
177 context.codec(KeystoneConfig.class);
178 keystoneConfig = keystoneConfigCodec.decode((ObjectNode)
179 keystoneConfigJson.deepCopy(), context);
180 } else {
181 JsonNode authJson = json.get(AUTHENTICATION);
182 final JsonCodec<OpenstackAuth> authCodec = context.codec(OpenstackAuth.class);
183 OpenstackAuth auth = authCodec.decode((ObjectNode) authJson.deepCopy(), context);
184
185 String endpoint = nullIsIllegal(json.get(ENDPOINT).asText(),
186 ENDPOINT + MISSING_MESSAGE);
187
188 keystoneConfig = DefaultKeystoneConfig.builder()
189 .authentication(auth)
190 .endpoint(endpoint)
191 .build();
192 }
193
194 nodeBuilder.keystoneConfig(keystoneConfig);
Jian Li27841662018-04-14 01:59:47 +0900195 }
Jian Li23c8be22018-02-13 11:34:15 +0900196 if (json.get(VLAN_INTF_NAME) != null) {
197 nodeBuilder.vlanIntf(json.get(VLAN_INTF_NAME).asText());
198 }
199 if (json.get(DATA_IP) != null) {
200 nodeBuilder.dataIp(IpAddress.valueOf(json.get(DATA_IP).asText()));
201 }
202
Jian Lie3141542018-08-13 18:05:43 +0900203 JsonNode intBridgeJson = json.get(INTEGRATION_BRIDGE);
204 if (intBridgeJson != null) {
205 nodeBuilder.intgBridge(DeviceId.deviceId(intBridgeJson.asText()));
206 }
207
Jian Lie6312162018-03-21 21:41:00 +0900208 // parse physical interfaces
209 List<OpenstackPhyInterface> phyIntfs = new ArrayList<>();
210 JsonNode phyIntfsJson = json.get(PHYSICAL_INTERFACES);
211 if (phyIntfsJson != null) {
Jian Li27841662018-04-14 01:59:47 +0900212
213 final JsonCodec<OpenstackPhyInterface>
214 phyIntfCodec = context.codec(OpenstackPhyInterface.class);
215
Jian Lie6312162018-03-21 21:41:00 +0900216 IntStream.range(0, phyIntfsJson.size()).forEach(i -> {
217 ObjectNode intfJson = get(phyIntfsJson, i);
218 phyIntfs.add(phyIntfCodec.decode(intfJson, context));
219 });
220 }
221 nodeBuilder.phyIntfs(phyIntfs);
222
Jian Li789fadb2018-07-10 13:59:47 +0900223 // parse customized controllers
224 List<ControllerInfo> controllers = new ArrayList<>();
225 JsonNode controllersJson = json.get(CONTROLLERS);
226 if (controllersJson != null) {
227
228 final JsonCodec<ControllerInfo>
229 controllerCodec = context.codec(ControllerInfo.class);
230
231 IntStream.range(0, controllersJson.size()).forEach(i -> {
232 ObjectNode controllerJson = get(controllersJson, i);
233 controllers.add(controllerCodec.decode(controllerJson, context));
234 });
235 }
236 nodeBuilder.controllers(controllers);
237
Jian Lic704b672018-09-04 18:52:53 +0900238 // parse neutron config
239 JsonNode neutronConfigJson = json.get(NEUTRON_CONFIG);
240 if (neutronConfigJson != null) {
241 final JsonCodec<NeutronConfig> neutronConfigJsonCodec =
242 context.codec(NeutronConfig.class);
Jian Li27841662018-04-14 01:59:47 +0900243
Jian Lic704b672018-09-04 18:52:53 +0900244 NeutronConfig neutronConfig =
245 neutronConfigJsonCodec.decode((ObjectNode)
246 neutronConfigJson.deepCopy(), context);
247 nodeBuilder.neutronConfig(neutronConfig);
Jian Li27841662018-04-14 01:59:47 +0900248 }
249
Daniel Parkdeefa702018-07-17 17:55:51 +0900250 // parse ssh authentication
251 JsonNode sshAuthJson = json.get(SSH_AUTH);
Daniel Parkd02d7bd2018-08-23 23:04:31 +0900252 if (sshAuthJson != null) {
Jian Lic704b672018-09-04 18:52:53 +0900253 final JsonCodec<OpenstackSshAuth> sshAuthJsonCodec =
254 context.codec(OpenstackSshAuth.class);
Daniel Parkdeefa702018-07-17 17:55:51 +0900255
Jian Lic704b672018-09-04 18:52:53 +0900256 OpenstackSshAuth sshAuth = sshAuthJsonCodec.decode((ObjectNode)
257 sshAuthJson.deepCopy(), context);
Daniel Parkdeefa702018-07-17 17:55:51 +0900258 nodeBuilder.sshAuthInfo(sshAuth);
259 }
260
Daniel Parkd02d7bd2018-08-23 23:04:31 +0900261 JsonNode dpdkConfigJson = json.get(DPDK_CONFIG);
262 if (dpdkConfigJson != null) {
Jian Lic704b672018-09-04 18:52:53 +0900263 final JsonCodec<DpdkConfig> dpdkConfigJsonCodec =
264 context.codec(DpdkConfig.class);
Daniel Parkd02d7bd2018-08-23 23:04:31 +0900265
Jian Lic704b672018-09-04 18:52:53 +0900266 DpdkConfig dpdkConfig = dpdkConfigJsonCodec.decode((ObjectNode)
267 dpdkConfigJson.deepCopy(), context);
Daniel Parkd02d7bd2018-08-23 23:04:31 +0900268 nodeBuilder.dpdkConfig(dpdkConfig);
269 }
270
Jian Li23c8be22018-02-13 11:34:15 +0900271 log.trace("node is {}", nodeBuilder.build().toString());
272
273 return nodeBuilder.build();
274 }
275}