blob: c3277bc10aa0598bba35e056067f7f348910888c [file] [log] [blame]
Brian O'Connorcff03322015-02-03 15:28:59 -08001/*
2 * Copyright 2015 Open Networking Laboratory
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.net.intent;
17
Brian O'Connor9476fa12015-06-25 15:17:17 -040018import com.google.common.annotations.Beta;
Ray Milkey65cb59a2015-02-10 15:18:26 -080019import com.google.common.base.MoreObjects;
Brian O'Connorcff03322015-02-03 15:28:59 -080020import com.google.common.collect.ImmutableList;
Brian O'Connor5eb77c82015-03-02 18:09:39 -080021import org.onosproject.cluster.NodeId;
Brian O'Connorcff03322015-02-03 15:28:59 -080022import org.onosproject.store.Timestamp;
Jonathan Hart72175c22015-03-24 18:55:58 -070023import org.slf4j.Logger;
24import org.slf4j.LoggerFactory;
Brian O'Connorcff03322015-02-03 15:28:59 -080025
Brian O'Connorf0c5a052015-04-27 00:34:53 -070026import java.util.Collections;
Brian O'Connorcff03322015-02-03 15:28:59 -080027import java.util.List;
28import java.util.Objects;
29
Jonathan Hart0d18df32015-03-21 08:42:59 -070030import static com.google.common.base.Preconditions.checkNotNull;
Brian O'Connorf0c5a052015-04-27 00:34:53 -070031import static org.onosproject.net.intent.IntentState.*;
Jonathan Hart0d18df32015-03-21 08:42:59 -070032
Brian O'Connorcff03322015-02-03 15:28:59 -080033/**
34 * A wrapper class that contains an intents, its state, and other metadata for
35 * internal use.
36 */
Brian O'Connor9476fa12015-06-25 15:17:17 -040037@Beta
Brian O'Connorcff03322015-02-03 15:28:59 -080038public class IntentData { //FIXME need to make this "immutable"
39 // manager should be able to mutate a local copy while processing
Jonathan Hart72175c22015-03-24 18:55:58 -070040
41 private static final Logger log = LoggerFactory.getLogger(IntentData.class);
42
Jonathan Hart0d18df32015-03-21 08:42:59 -070043 private final Intent intent;
Brian O'Connorcff03322015-02-03 15:28:59 -080044
Brian O'Connorf0c5a052015-04-27 00:34:53 -070045 private final IntentState request; //TODO perhaps we want a full fledged object for requests
Brian O'Connorcff03322015-02-03 15:28:59 -080046 private IntentState state;
47 private Timestamp version;
Brian O'Connor5eb77c82015-03-02 18:09:39 -080048 private NodeId origin;
Brian O'Connor6d8e3172015-04-30 15:43:57 -070049 private int errorCount;
Brian O'Connorcff03322015-02-03 15:28:59 -080050
51 private List<Intent> installables;
52
Jonathan Hart0d18df32015-03-21 08:42:59 -070053 /**
54 * Creates a new intent data object.
55 *
56 * @param intent intent this metadata references
57 * @param state intent state
58 * @param version version of the intent for this key
59 */
Brian O'Connorcff03322015-02-03 15:28:59 -080060 public IntentData(Intent intent, IntentState state, Timestamp version) {
Sho SHIMIZU70b88d82016-01-19 14:27:22 -080061 checkNotNull(intent);
62 checkNotNull(state);
63
Brian O'Connorcff03322015-02-03 15:28:59 -080064 this.intent = intent;
65 this.state = state;
Brian O'Connorf0c5a052015-04-27 00:34:53 -070066 this.request = state;
Brian O'Connorcff03322015-02-03 15:28:59 -080067 this.version = version;
68 }
69
Jonathan Hart0d18df32015-03-21 08:42:59 -070070 /**
71 * Copy constructor.
72 *
73 * @param intentData intent data to copy
74 */
75 public IntentData(IntentData intentData) {
76 checkNotNull(intentData);
77
78 intent = intentData.intent;
79 state = intentData.state;
Brian O'Connorf0c5a052015-04-27 00:34:53 -070080 request = intentData.request;
Jonathan Hart0d18df32015-03-21 08:42:59 -070081 version = intentData.version;
82 origin = intentData.origin;
83 installables = intentData.installables;
Brian O'Connor6d8e3172015-04-30 15:43:57 -070084 errorCount = intentData.errorCount;
Brian O'Connorcff03322015-02-03 15:28:59 -080085 }
86
Jonathan Hart0d18df32015-03-21 08:42:59 -070087 // kryo constructor
88 protected IntentData() {
89 intent = null;
Brian O'Connorf0c5a052015-04-27 00:34:53 -070090 request = null;
Jonathan Hart0d18df32015-03-21 08:42:59 -070091 }
92
93 /**
94 * Returns the intent this metadata references.
95 *
96 * @return intent
97 */
Brian O'Connorcff03322015-02-03 15:28:59 -080098 public Intent intent() {
99 return intent;
100 }
101
Jonathan Hart0d18df32015-03-21 08:42:59 -0700102 /**
103 * Returns the state of the intent.
104 *
105 * @return intent state
106 */
Brian O'Connorcff03322015-02-03 15:28:59 -0800107 public IntentState state() {
108 return state;
109 }
110
Brian O'Connorf0c5a052015-04-27 00:34:53 -0700111 public IntentState request() {
112 return request;
113 }
114
Jonathan Hart0d18df32015-03-21 08:42:59 -0700115 /**
116 * Returns the intent key.
117 *
118 * @return intent key
119 */
Ray Milkey5b3717e2015-02-05 11:44:08 -0800120 public Key key() {
Brian O'Connorcff03322015-02-03 15:28:59 -0800121 return intent.key();
122 }
123
Jonathan Hart0d18df32015-03-21 08:42:59 -0700124 /**
125 * Returns the version of the intent for this key.
126 *
127 * @return intent version
128 */
Brian O'Connor2ba63fd2015-02-09 22:48:11 -0800129 public Timestamp version() {
130 return version;
131 }
132
Brian O'Connor5eb77c82015-03-02 18:09:39 -0800133 /**
Jonathan Hart0d18df32015-03-21 08:42:59 -0700134 * Sets the origin, which is the node that created the intent.
Brian O'Connor5eb77c82015-03-02 18:09:39 -0800135 *
136 * @param origin origin instance
137 */
138 public void setOrigin(NodeId origin) {
139 this.origin = origin;
140 }
141
Jonathan Hart0d18df32015-03-21 08:42:59 -0700142 /**
143 * Returns the origin node that created this intent.
144 *
145 * @return origin node ID
146 */
Brian O'Connor5eb77c82015-03-02 18:09:39 -0800147 public NodeId origin() {
148 return origin;
149 }
150
Jonathan Hart0d18df32015-03-21 08:42:59 -0700151 /**
152 * Updates the state of the intent to the given new state.
153 *
154 * @param newState new state of the intent
155 */
Brian O'Connorcff03322015-02-03 15:28:59 -0800156 public void setState(IntentState newState) {
157 this.state = newState;
158 }
159
Brian O'Connor2ba63fd2015-02-09 22:48:11 -0800160 /**
161 * Sets the version for this intent data.
162 * <p>
163 * The store should call this method only once when the IntentData is
164 * first passed into the pending map. Ideally, an IntentData is timestamped
165 * on the same thread that the called used to submit the intents.
166 * </p>
167 *
168 * @param version the version/timestamp for this intent data
169 */
170 public void setVersion(Timestamp version) {
171 this.version = version;
172 }
173
Jonathan Hart0d18df32015-03-21 08:42:59 -0700174 /**
Brian O'Connor6d8e3172015-04-30 15:43:57 -0700175 * Increments the error count for this intent.
176 */
177 public void incrementErrorCount() {
178 errorCount++;
179 }
180
181 /**
182 * Sets the error count for this intent.
183 *
184 * @param newCount new count
185 */
186 public void setErrorCount(int newCount) {
187 errorCount = newCount;
188 }
189
190 /**
191 * Returns the number of times that this intent has encountered an error
192 * during installation or withdrawal.
193 *
194 * @return error count
195 */
196 public int errorCount() {
197 return errorCount;
198 }
199
200 /**
Jonathan Hart0d18df32015-03-21 08:42:59 -0700201 * Sets the intent installables to the given list of intents.
202 *
203 * @param installables list of installables for this intent
204 */
Brian O'Connorcff03322015-02-03 15:28:59 -0800205 public void setInstallables(List<Intent> installables) {
206 this.installables = ImmutableList.copyOf(installables);
207 }
208
Jonathan Hart0d18df32015-03-21 08:42:59 -0700209 /**
210 * Returns the installables associated with this intent.
211 *
212 * @return list of installable intents
213 */
Brian O'Connorcff03322015-02-03 15:28:59 -0800214 public List<Intent> installables() {
Brian O'Connorf0c5a052015-04-27 00:34:53 -0700215 return installables != null ? installables : Collections.emptyList();
Brian O'Connorcff03322015-02-03 15:28:59 -0800216 }
217
Jonathan Hart72175c22015-03-24 18:55:58 -0700218 /**
219 * Determines whether an intent data update is allowed. The update must
220 * either have a higher version than the current data, or the state
221 * transition between two updates of the same version must be sane.
222 *
223 * @param currentData existing intent data in the store
224 * @param newData new intent data update proposal
225 * @return true if we can apply the update, otherwise false
226 */
227 public static boolean isUpdateAcceptable(IntentData currentData, IntentData newData) {
228
229 if (currentData == null) {
230 return true;
Sho SHIMIZU2c05f912015-04-10 14:23:16 -0700231 } else if (currentData.version().isOlderThan(newData.version())) {
Jonathan Hart72175c22015-03-24 18:55:58 -0700232 return true;
Sho SHIMIZU2c05f912015-04-10 14:23:16 -0700233 } else if (currentData.version().isNewerThan(newData.version())) {
Jonathan Hart72175c22015-03-24 18:55:58 -0700234 return false;
235 }
236
237 // current and new data versions are the same
238 IntentState currentState = currentData.state();
239 IntentState newState = newData.state();
240
241 switch (newState) {
242 case INSTALLING:
243 if (currentState == INSTALLING) {
244 return false;
245 }
246 // FALLTHROUGH
247 case INSTALLED:
248 if (currentState == INSTALLED) {
249 return false;
250 } else if (currentState == WITHDRAWING || currentState == WITHDRAWN
251 || currentState == PURGE_REQ) {
252 log.warn("Invalid state transition from {} to {} for intent {}",
253 currentState, newState, newData.key());
254 return false;
255 }
256 return true;
257
258 case WITHDRAWING:
259 if (currentState == WITHDRAWING) {
260 return false;
261 }
262 // FALLTHROUGH
263 case WITHDRAWN:
264 if (currentState == WITHDRAWN) {
265 return false;
266 } else if (currentState == INSTALLING || currentState == INSTALLED
267 || currentState == PURGE_REQ) {
268 log.warn("Invalid state transition from {} to {} for intent {}",
269 currentState, newState, newData.key());
270 return false;
271 }
272 return true;
273
274 case FAILED:
275 if (currentState == FAILED) {
276 return false;
277 }
278 return true;
279
Brian O'Connorf0c5a052015-04-27 00:34:53 -0700280 case CORRUPT:
281 if (currentState == CORRUPT) {
282 return false;
283 }
284 return true;
285
Jonathan Hart72175c22015-03-24 18:55:58 -0700286 case PURGE_REQ:
Brian O'Connor597934f2015-07-16 11:44:03 -0700287 // TODO we should enforce that only WITHDRAWN intents can be purged
Jonathan Hart72175c22015-03-24 18:55:58 -0700288 return true;
289
290 case COMPILING:
291 case RECOMPILING:
292 case INSTALL_REQ:
293 case WITHDRAW_REQ:
294 default:
295 log.warn("Invalid state {} for intent {}", newState, newData.key());
296 return false;
297 }
298 }
299
Brian O'Connorcff03322015-02-03 15:28:59 -0800300 @Override
301 public int hashCode() {
302 return Objects.hash(intent, version);
303 }
304
305 @Override
306 public boolean equals(Object obj) {
307 if (this == obj) {
308 return true;
309 }
310 if (obj == null || getClass() != obj.getClass()) {
311 return false;
312 }
313 final IntentData other = (IntentData) obj;
314 return Objects.equals(this.intent, other.intent)
315 && Objects.equals(this.version, other.version);
316 }
Ray Milkey65cb59a2015-02-10 15:18:26 -0800317
Jonathan Hart0d18df32015-03-21 08:42:59 -0700318 @Override
Ray Milkey65cb59a2015-02-10 15:18:26 -0800319 public String toString() {
320 return MoreObjects.toStringHelper(getClass())
321 .add("key", key())
322 .add("state", state())
323 .add("version", version())
Ray Milkey9f74c082015-02-11 15:40:16 -0800324 .add("intent", intent())
Jonathan Hart0d18df32015-03-21 08:42:59 -0700325 .add("origin", origin())
Jonathan Hartd0ba2172015-02-11 13:54:33 -0800326 .add("installables", installables())
Ray Milkey65cb59a2015-02-10 15:18:26 -0800327 .toString();
328 }
329
Brian O'Connorcff03322015-02-03 15:28:59 -0800330}