blob: 6a9c9aef182d7fe5124f1227afd07cffa328b7de [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
Ray Milkey65cb59a2015-02-10 15:18:26 -080018import com.google.common.base.MoreObjects;
Brian O'Connorcff03322015-02-03 15:28:59 -080019import com.google.common.collect.ImmutableList;
Brian O'Connor5eb77c82015-03-02 18:09:39 -080020import org.onosproject.cluster.NodeId;
Brian O'Connorcff03322015-02-03 15:28:59 -080021import org.onosproject.store.Timestamp;
Jonathan Hart72175c22015-03-24 18:55:58 -070022import org.slf4j.Logger;
23import org.slf4j.LoggerFactory;
Brian O'Connorcff03322015-02-03 15:28:59 -080024
Brian O'Connorf0c5a052015-04-27 00:34:53 -070025import java.util.Collections;
Brian O'Connorcff03322015-02-03 15:28:59 -080026import java.util.List;
27import java.util.Objects;
28
Jonathan Hart0d18df32015-03-21 08:42:59 -070029import static com.google.common.base.Preconditions.checkNotNull;
Brian O'Connorf0c5a052015-04-27 00:34:53 -070030import static org.onosproject.net.intent.IntentState.*;
Jonathan Hart0d18df32015-03-21 08:42:59 -070031
Brian O'Connorcff03322015-02-03 15:28:59 -080032/**
33 * A wrapper class that contains an intents, its state, and other metadata for
34 * internal use.
35 */
36public class IntentData { //FIXME need to make this "immutable"
37 // manager should be able to mutate a local copy while processing
Jonathan Hart72175c22015-03-24 18:55:58 -070038
39 private static final Logger log = LoggerFactory.getLogger(IntentData.class);
40
Jonathan Hart0d18df32015-03-21 08:42:59 -070041 private final Intent intent;
Brian O'Connorcff03322015-02-03 15:28:59 -080042
Brian O'Connorf0c5a052015-04-27 00:34:53 -070043 private final IntentState request; //TODO perhaps we want a full fledged object for requests
Brian O'Connorcff03322015-02-03 15:28:59 -080044 private IntentState state;
45 private Timestamp version;
Brian O'Connor5eb77c82015-03-02 18:09:39 -080046 private NodeId origin;
Brian O'Connorcff03322015-02-03 15:28:59 -080047
48 private List<Intent> installables;
49
Jonathan Hart0d18df32015-03-21 08:42:59 -070050 /**
51 * Creates a new intent data object.
52 *
53 * @param intent intent this metadata references
54 * @param state intent state
55 * @param version version of the intent for this key
56 */
Brian O'Connorcff03322015-02-03 15:28:59 -080057 public IntentData(Intent intent, IntentState state, Timestamp version) {
58 this.intent = intent;
59 this.state = state;
Brian O'Connorf0c5a052015-04-27 00:34:53 -070060 this.request = state;
Brian O'Connorcff03322015-02-03 15:28:59 -080061 this.version = version;
62 }
63
Jonathan Hart0d18df32015-03-21 08:42:59 -070064 /**
65 * Copy constructor.
66 *
67 * @param intentData intent data to copy
68 */
69 public IntentData(IntentData intentData) {
70 checkNotNull(intentData);
71
72 intent = intentData.intent;
73 state = intentData.state;
Brian O'Connorf0c5a052015-04-27 00:34:53 -070074 request = intentData.request;
Jonathan Hart0d18df32015-03-21 08:42:59 -070075 version = intentData.version;
76 origin = intentData.origin;
77 installables = intentData.installables;
Brian O'Connorcff03322015-02-03 15:28:59 -080078 }
79
Jonathan Hart0d18df32015-03-21 08:42:59 -070080 // kryo constructor
81 protected IntentData() {
82 intent = null;
Brian O'Connorf0c5a052015-04-27 00:34:53 -070083 request = null;
Jonathan Hart0d18df32015-03-21 08:42:59 -070084 }
85
86 /**
87 * Returns the intent this metadata references.
88 *
89 * @return intent
90 */
Brian O'Connorcff03322015-02-03 15:28:59 -080091 public Intent intent() {
92 return intent;
93 }
94
Jonathan Hart0d18df32015-03-21 08:42:59 -070095 /**
96 * Returns the state of the intent.
97 *
98 * @return intent state
99 */
Brian O'Connorcff03322015-02-03 15:28:59 -0800100 public IntentState state() {
101 return state;
102 }
103
Brian O'Connorf0c5a052015-04-27 00:34:53 -0700104 public IntentState request() {
105 return request;
106 }
107
Jonathan Hart0d18df32015-03-21 08:42:59 -0700108 /**
109 * Returns the intent key.
110 *
111 * @return intent key
112 */
Ray Milkey5b3717e2015-02-05 11:44:08 -0800113 public Key key() {
Brian O'Connorcff03322015-02-03 15:28:59 -0800114 return intent.key();
115 }
116
Jonathan Hart0d18df32015-03-21 08:42:59 -0700117 /**
118 * Returns the version of the intent for this key.
119 *
120 * @return intent version
121 */
Brian O'Connor2ba63fd2015-02-09 22:48:11 -0800122 public Timestamp version() {
123 return version;
124 }
125
Brian O'Connor5eb77c82015-03-02 18:09:39 -0800126 /**
Jonathan Hart0d18df32015-03-21 08:42:59 -0700127 * Sets the origin, which is the node that created the intent.
Brian O'Connor5eb77c82015-03-02 18:09:39 -0800128 *
129 * @param origin origin instance
130 */
131 public void setOrigin(NodeId origin) {
132 this.origin = origin;
133 }
134
Jonathan Hart0d18df32015-03-21 08:42:59 -0700135 /**
136 * Returns the origin node that created this intent.
137 *
138 * @return origin node ID
139 */
Brian O'Connor5eb77c82015-03-02 18:09:39 -0800140 public NodeId origin() {
141 return origin;
142 }
143
Jonathan Hart0d18df32015-03-21 08:42:59 -0700144 /**
145 * Updates the state of the intent to the given new state.
146 *
147 * @param newState new state of the intent
148 */
Brian O'Connorcff03322015-02-03 15:28:59 -0800149 public void setState(IntentState newState) {
150 this.state = newState;
151 }
152
Brian O'Connor2ba63fd2015-02-09 22:48:11 -0800153 /**
154 * Sets the version for this intent data.
155 * <p>
156 * The store should call this method only once when the IntentData is
157 * first passed into the pending map. Ideally, an IntentData is timestamped
158 * on the same thread that the called used to submit the intents.
159 * </p>
160 *
161 * @param version the version/timestamp for this intent data
162 */
163 public void setVersion(Timestamp version) {
164 this.version = version;
165 }
166
Jonathan Hart0d18df32015-03-21 08:42:59 -0700167 /**
168 * Sets the intent installables to the given list of intents.
169 *
170 * @param installables list of installables for this intent
171 */
Brian O'Connorcff03322015-02-03 15:28:59 -0800172 public void setInstallables(List<Intent> installables) {
173 this.installables = ImmutableList.copyOf(installables);
174 }
175
Jonathan Hart0d18df32015-03-21 08:42:59 -0700176 /**
177 * Returns the installables associated with this intent.
178 *
179 * @return list of installable intents
180 */
Brian O'Connorcff03322015-02-03 15:28:59 -0800181 public List<Intent> installables() {
Brian O'Connorf0c5a052015-04-27 00:34:53 -0700182 return installables != null ? installables : Collections.emptyList();
Brian O'Connorcff03322015-02-03 15:28:59 -0800183 }
184
Jonathan Hart72175c22015-03-24 18:55:58 -0700185 /**
186 * Determines whether an intent data update is allowed. The update must
187 * either have a higher version than the current data, or the state
188 * transition between two updates of the same version must be sane.
189 *
190 * @param currentData existing intent data in the store
191 * @param newData new intent data update proposal
192 * @return true if we can apply the update, otherwise false
193 */
194 public static boolean isUpdateAcceptable(IntentData currentData, IntentData newData) {
195
196 if (currentData == null) {
197 return true;
Sho SHIMIZU2c05f912015-04-10 14:23:16 -0700198 } else if (currentData.version().isOlderThan(newData.version())) {
Jonathan Hart72175c22015-03-24 18:55:58 -0700199 return true;
Sho SHIMIZU2c05f912015-04-10 14:23:16 -0700200 } else if (currentData.version().isNewerThan(newData.version())) {
Jonathan Hart72175c22015-03-24 18:55:58 -0700201 return false;
202 }
203
204 // current and new data versions are the same
205 IntentState currentState = currentData.state();
206 IntentState newState = newData.state();
207
208 switch (newState) {
209 case INSTALLING:
210 if (currentState == INSTALLING) {
211 return false;
212 }
213 // FALLTHROUGH
214 case INSTALLED:
215 if (currentState == INSTALLED) {
216 return false;
217 } else if (currentState == WITHDRAWING || currentState == WITHDRAWN
218 || currentState == PURGE_REQ) {
219 log.warn("Invalid state transition from {} to {} for intent {}",
220 currentState, newState, newData.key());
221 return false;
222 }
223 return true;
224
225 case WITHDRAWING:
226 if (currentState == WITHDRAWING) {
227 return false;
228 }
229 // FALLTHROUGH
230 case WITHDRAWN:
231 if (currentState == WITHDRAWN) {
232 return false;
233 } else if (currentState == INSTALLING || currentState == INSTALLED
234 || currentState == PURGE_REQ) {
235 log.warn("Invalid state transition from {} to {} for intent {}",
236 currentState, newState, newData.key());
237 return false;
238 }
239 return true;
240
241 case FAILED:
242 if (currentState == FAILED) {
243 return false;
244 }
245 return true;
246
Brian O'Connorf0c5a052015-04-27 00:34:53 -0700247 case CORRUPT:
248 if (currentState == CORRUPT) {
249 return false;
250 }
251 return true;
252
Jonathan Hart72175c22015-03-24 18:55:58 -0700253 case PURGE_REQ:
254 return true;
255
256 case COMPILING:
257 case RECOMPILING:
258 case INSTALL_REQ:
259 case WITHDRAW_REQ:
260 default:
261 log.warn("Invalid state {} for intent {}", newState, newData.key());
262 return false;
263 }
264 }
265
Brian O'Connorcff03322015-02-03 15:28:59 -0800266 @Override
267 public int hashCode() {
268 return Objects.hash(intent, version);
269 }
270
271 @Override
272 public boolean equals(Object obj) {
273 if (this == obj) {
274 return true;
275 }
276 if (obj == null || getClass() != obj.getClass()) {
277 return false;
278 }
279 final IntentData other = (IntentData) obj;
280 return Objects.equals(this.intent, other.intent)
281 && Objects.equals(this.version, other.version);
282 }
Ray Milkey65cb59a2015-02-10 15:18:26 -0800283
Jonathan Hart0d18df32015-03-21 08:42:59 -0700284 @Override
Ray Milkey65cb59a2015-02-10 15:18:26 -0800285 public String toString() {
286 return MoreObjects.toStringHelper(getClass())
287 .add("key", key())
288 .add("state", state())
289 .add("version", version())
Ray Milkey9f74c082015-02-11 15:40:16 -0800290 .add("intent", intent())
Jonathan Hart0d18df32015-03-21 08:42:59 -0700291 .add("origin", origin())
Jonathan Hartd0ba2172015-02-11 13:54:33 -0800292 .add("installables", installables())
Ray Milkey65cb59a2015-02-10 15:18:26 -0800293 .toString();
294 }
295
Brian O'Connorcff03322015-02-03 15:28:59 -0800296}