mirror of
https://github.com/opennetworkinglab/onos.git
synced 2026-05-05 04:06:49 +02:00
'Static data model implementation in Worklet
Change-Id: Ic5eeb26eaea547523befd509f9f48281cb4c2031
This commit is contained in:
parent
dabd84f606
commit
09251881bc
@ -0,0 +1,170 @@
|
||||
/*
|
||||
* Copyright 2019-present Open Networking Foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.onosproject.workflow.api;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.node.ArrayNode;
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import com.google.common.base.MoreObjects;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import static org.slf4j.LoggerFactory.getLogger;
|
||||
|
||||
/**
|
||||
* Class for default worklet description.
|
||||
*/
|
||||
public final class DefaultWorkletDescription implements WorkletDescription {
|
||||
|
||||
protected static final Logger log = getLogger(DefaultWorkletDescription.class);
|
||||
|
||||
/**
|
||||
* worklet Name.
|
||||
*/
|
||||
private String tag;
|
||||
|
||||
/**
|
||||
* worklet data model.
|
||||
*/
|
||||
private JsonDataModelTree data;
|
||||
|
||||
/**
|
||||
* Constructor of worklet description.
|
||||
*
|
||||
* @param builder worklet description builder
|
||||
*/
|
||||
public DefaultWorkletDescription(DefaultWorkletDescription.Builder builder) {
|
||||
this.tag = builder.tag;
|
||||
this.data = builder.data;
|
||||
}
|
||||
|
||||
public DefaultWorkletDescription(String tag) {
|
||||
this.tag = tag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String tag() {
|
||||
return this.tag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonDataModelTree data() {
|
||||
return this.data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return MoreObjects.toStringHelper(getClass())
|
||||
.add("tag", tag())
|
||||
.add("data", data())
|
||||
.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets builder instance.
|
||||
*
|
||||
* @return builder instance
|
||||
*/
|
||||
public static DefaultWorkletDescription.Builder builder() {
|
||||
return new DefaultWorkletDescription.Builder();
|
||||
}
|
||||
|
||||
/**
|
||||
* Builder for worklet description.
|
||||
*/
|
||||
public static class Builder {
|
||||
|
||||
/**
|
||||
* worklet name.
|
||||
*/
|
||||
private String tag;
|
||||
|
||||
/**
|
||||
* static data model tree.
|
||||
*/
|
||||
JsonDataModelTree data = new JsonDataModelTree();
|
||||
|
||||
/**
|
||||
* Sets worklet name.
|
||||
*
|
||||
* @param tag worklet name
|
||||
* @return builder
|
||||
*/
|
||||
public DefaultWorkletDescription.Builder name(String tag) {
|
||||
this.tag = tag;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public DefaultWorkletDescription.Builder staticDataModel(String path, String value) throws WorkflowException {
|
||||
|
||||
data.setAt(path, value);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public DefaultWorkletDescription.Builder staticDataModel(String path, Integer value) throws WorkflowException {
|
||||
|
||||
data.setAt(path, value);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public DefaultWorkletDescription.Builder staticDataModel(String path, Boolean value) throws WorkflowException {
|
||||
|
||||
data.setAt(path, value);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public DefaultWorkletDescription.Builder staticDataModel(String path, JsonNode value) throws WorkflowException {
|
||||
|
||||
data.setAt(path, value);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public DefaultWorkletDescription.Builder staticDataModel(String path, ArrayNode value)
|
||||
throws WorkflowException {
|
||||
|
||||
data.setAt(path, value);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public DefaultWorkletDescription.Builder staticDataModel(String path, ObjectNode value)
|
||||
throws WorkflowException {
|
||||
|
||||
data.setAt(path, value);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Builds worklet description from builder.
|
||||
*
|
||||
* @return instance of worklet description
|
||||
* @throws WorkflowException workflow exception
|
||||
*/
|
||||
public DefaultWorkletDescription build() {
|
||||
|
||||
return new DefaultWorkletDescription(this);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@ -27,6 +27,7 @@ import java.lang.reflect.Modifier;
|
||||
import java.net.URI;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.onosproject.workflow.api.CheckCondition.check;
|
||||
@ -42,9 +43,9 @@ public final class ImmutableListWorkflow extends AbstractWorkflow {
|
||||
private String initWorkletType;
|
||||
|
||||
/**
|
||||
* List of worklet.
|
||||
* List of worklet description.
|
||||
*/
|
||||
private List<String> workletTypeList;
|
||||
private List<WorkletDescription> workletDescList;
|
||||
|
||||
/**
|
||||
* Set of workflow attributes.
|
||||
@ -52,6 +53,7 @@ public final class ImmutableListWorkflow extends AbstractWorkflow {
|
||||
private Set<WorkflowAttribute> attributes;
|
||||
|
||||
private static JsonDataModelInjector dataModelInjector = new JsonDataModelInjector();
|
||||
private static StaticDataModelInjector staticDataModelInjector = new StaticDataModelInjector();
|
||||
|
||||
/**
|
||||
* Constructor of ImmutableListWorkflow.
|
||||
@ -61,7 +63,7 @@ public final class ImmutableListWorkflow extends AbstractWorkflow {
|
||||
private ImmutableListWorkflow(Builder builder) {
|
||||
super(builder.id);
|
||||
this.initWorkletType = builder.initWorkletType;
|
||||
workletTypeList = ImmutableList.copyOf(builder.workletTypeList);
|
||||
workletDescList = ImmutableList.copyOf(builder.workletDescList);
|
||||
attributes = ImmutableSet.copyOf(builder.attributes);
|
||||
}
|
||||
|
||||
@ -84,12 +86,11 @@ public final class ImmutableListWorkflow extends AbstractWorkflow {
|
||||
|
||||
ProgramCounter pc = current.clone();
|
||||
|
||||
for (int i = current.workletIndex(); i < workletTypeList.size(); pc = increased(pc), i++) {
|
||||
for (int i = current.workletIndex(); i < workletDescList.size(); pc = increased(pc), i++) {
|
||||
|
||||
if (cnt++ > Worklet.MAX_WORKS) {
|
||||
throw new WorkflowException("Maximum worklet execution exceeded");
|
||||
}
|
||||
|
||||
if (pc.isCompleted()) {
|
||||
return pc;
|
||||
}
|
||||
@ -119,6 +120,12 @@ public final class ImmutableListWorkflow extends AbstractWorkflow {
|
||||
} else {
|
||||
// isNext is read only. It does not perform 'inhale'.
|
||||
dataModelInjector.inject(worklet, context);
|
||||
WorkletDescription workletDesc = getWorkletDesc(pc);
|
||||
if (Objects.nonNull(workletDesc)) {
|
||||
if (!(workletDesc.tag().equals("INIT") || workletDesc.tag().equals("COMPLETED"))) {
|
||||
staticDataModelInjector.inject(worklet, workletDesc);
|
||||
}
|
||||
}
|
||||
if (worklet.isNext(context)) {
|
||||
return pc;
|
||||
}
|
||||
@ -132,18 +139,18 @@ public final class ImmutableListWorkflow extends AbstractWorkflow {
|
||||
public ProgramCounter increased(ProgramCounter pc) throws WorkflowException {
|
||||
|
||||
int increaedIndex = pc.workletIndex() + 1;
|
||||
if (increaedIndex >= workletTypeList.size()) {
|
||||
if (increaedIndex >= workletDescList.size()) {
|
||||
throw new WorkflowException("Out of bound in program counter(" + pc + ")");
|
||||
}
|
||||
|
||||
String workletType = workletTypeList.get(increaedIndex);
|
||||
return ProgramCounter.valueOf(workletType, increaedIndex);
|
||||
WorkletDescription workletDesc = workletDescList.get(increaedIndex);
|
||||
return ProgramCounter.valueOf(workletDesc.tag(), increaedIndex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Worklet getWorkletInstance(ProgramCounter pc) throws WorkflowException {
|
||||
|
||||
return getWorkletInstance(workletTypeList.get(pc.workletIndex()));
|
||||
return getWorkletInstance(workletDescList.get(pc.workletIndex()).tag());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -191,10 +198,21 @@ public final class ImmutableListWorkflow extends AbstractWorkflow {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getWorkletTypeList() {
|
||||
return ImmutableList.copyOf(workletTypeList);
|
||||
public List<WorkletDescription> getWorkletDescList() {
|
||||
return ImmutableList.copyOf(workletDescList);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WorkletDescription getWorkletDesc(ProgramCounter pc) {
|
||||
Optional<WorkletDescription> workletDescription = workletDescList.stream().filter(a -> Objects.equals(a.tag(),
|
||||
workletDescList.get(pc.workletIndex()).tag())).findAny();
|
||||
if (workletDescription.isPresent()) {
|
||||
return workletDescription.get();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets index of class in worklet type list.
|
||||
*
|
||||
@ -202,8 +220,8 @@ public final class ImmutableListWorkflow extends AbstractWorkflow {
|
||||
* @return index of class in worklet type list
|
||||
*/
|
||||
private int getClassIndex(Class aClass) {
|
||||
for (int i = 0; i < workletTypeList.size(); i++) {
|
||||
if (Objects.equals(aClass.getName(), workletTypeList.get(i))) {
|
||||
for (int i = 0; i < workletDescList.size(); i++) {
|
||||
if (Objects.equals(aClass.getName(), workletDescList.get(i))) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
@ -247,7 +265,7 @@ public final class ImmutableListWorkflow extends AbstractWorkflow {
|
||||
}
|
||||
return Objects.equals(this.id(), ((ImmutableListWorkflow) obj).id())
|
||||
&& Objects.equals(this.initWorkletType, ((ImmutableListWorkflow) obj).initWorkletType)
|
||||
&& Objects.equals(this.workletTypeList, ((ImmutableListWorkflow) obj).workletTypeList)
|
||||
&& Objects.equals(this.workletDescList, ((ImmutableListWorkflow) obj).workletDescList)
|
||||
&& Objects.equals(this.attributes, ((ImmutableListWorkflow) obj).attributes);
|
||||
}
|
||||
|
||||
@ -256,7 +274,7 @@ public final class ImmutableListWorkflow extends AbstractWorkflow {
|
||||
return MoreObjects.toStringHelper(getClass())
|
||||
.add("id", id())
|
||||
.add("initWorklet", initWorkletType)
|
||||
.add("workList", workletTypeList)
|
||||
.add("workList", workletDescList)
|
||||
.add("attributes", attributes)
|
||||
.toString();
|
||||
}
|
||||
@ -277,7 +295,7 @@ public final class ImmutableListWorkflow extends AbstractWorkflow {
|
||||
|
||||
private URI id;
|
||||
private String initWorkletType;
|
||||
private final List<String> workletTypeList = Lists.newArrayList();
|
||||
private final List<WorkletDescription> workletDescList = Lists.newArrayList();
|
||||
private final Set<WorkflowAttribute> attributes = Sets.newHashSet();
|
||||
|
||||
/**
|
||||
@ -288,7 +306,7 @@ public final class ImmutableListWorkflow extends AbstractWorkflow {
|
||||
*/
|
||||
public Builder id(URI uri) {
|
||||
this.id = uri;
|
||||
workletTypeList.add(Worklet.Common.INIT.tag());
|
||||
workletDescList.add(new DefaultWorkletDescription(Worklet.Common.INIT.tag()));
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -310,7 +328,7 @@ public final class ImmutableListWorkflow extends AbstractWorkflow {
|
||||
* @return builder
|
||||
*/
|
||||
public Builder chain(String workletClassName) {
|
||||
workletTypeList.add(workletClassName);
|
||||
workletDescList.add(new DefaultWorkletDescription(workletClassName));
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -331,8 +349,13 @@ public final class ImmutableListWorkflow extends AbstractWorkflow {
|
||||
* @return instance of ImmutableListWorkflow
|
||||
*/
|
||||
public ImmutableListWorkflow build() {
|
||||
workletTypeList.add(Worklet.Common.COMPLETED.tag());
|
||||
workletDescList.add(new DefaultWorkletDescription(Worklet.Common.COMPLETED.tag()));
|
||||
return new ImmutableListWorkflow(this);
|
||||
}
|
||||
|
||||
public Builder chain(DefaultWorkletDescription workletDesc) {
|
||||
workletDescList.add(workletDesc);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -56,6 +56,7 @@ public final class JsonDataModelTree implements DataModelTree {
|
||||
|
||||
/**
|
||||
* Constructor of JsonDataModelTree.
|
||||
*
|
||||
* @param root root node of json data model tree
|
||||
*/
|
||||
public JsonDataModelTree(JsonNode root) {
|
||||
@ -169,7 +170,8 @@ public final class JsonDataModelTree implements DataModelTree {
|
||||
|
||||
/**
|
||||
* Allocates json data model tree on json pointer path with specific leaf type.
|
||||
* @param ptr json pointer to allocate
|
||||
*
|
||||
* @param ptr json pointer to allocate
|
||||
* @param leaftype type of leaf node
|
||||
* @return json data model tree
|
||||
* @throws WorkflowException workflow exception
|
||||
@ -194,6 +196,7 @@ public final class JsonDataModelTree implements DataModelTree {
|
||||
|
||||
/**
|
||||
* Gets root json node.
|
||||
*
|
||||
* @return root json node
|
||||
* @throws WorkflowException workflow exception
|
||||
*/
|
||||
@ -203,6 +206,7 @@ public final class JsonDataModelTree implements DataModelTree {
|
||||
|
||||
/**
|
||||
* Gets root json node as ObjectNode (MAP type).
|
||||
*
|
||||
* @return root json node as ObjectNode
|
||||
* @throws WorkflowException workflow exception
|
||||
*/
|
||||
@ -212,6 +216,7 @@ public final class JsonDataModelTree implements DataModelTree {
|
||||
|
||||
/**
|
||||
* Gets root json node as ArrayNode (Array type).
|
||||
*
|
||||
* @return root json node as ArrayNode
|
||||
* @throws WorkflowException workflow exception
|
||||
*/
|
||||
@ -221,6 +226,7 @@ public final class JsonDataModelTree implements DataModelTree {
|
||||
|
||||
/**
|
||||
* Gets json node on specific path.
|
||||
*
|
||||
* @param path path of json node
|
||||
* @return json node on specific path
|
||||
* @throws WorkflowException workflow exception
|
||||
@ -232,6 +238,7 @@ public final class JsonDataModelTree implements DataModelTree {
|
||||
|
||||
/**
|
||||
* Gets json node on specific json pointer.
|
||||
*
|
||||
* @param ptr json pointer
|
||||
* @return json node on specific json pointer.
|
||||
* @throws WorkflowException workflow exception
|
||||
@ -246,6 +253,7 @@ public final class JsonDataModelTree implements DataModelTree {
|
||||
|
||||
/**
|
||||
* Gets json node on specific path as ObjectNode.
|
||||
*
|
||||
* @param path path of json node
|
||||
* @return ObjectNode type json node on specific path
|
||||
* @throws WorkflowException workflow exception
|
||||
@ -257,6 +265,7 @@ public final class JsonDataModelTree implements DataModelTree {
|
||||
|
||||
/**
|
||||
* Gets json node on specific json pointer as ObjectNode.
|
||||
*
|
||||
* @param ptr json pointer
|
||||
* @return ObjectNode type json node on specific json pointer.
|
||||
* @throws WorkflowException workflow exception
|
||||
@ -277,6 +286,7 @@ public final class JsonDataModelTree implements DataModelTree {
|
||||
|
||||
/**
|
||||
* Gets json node on specific path as ArrayNode.
|
||||
*
|
||||
* @param path path of json node
|
||||
* @return ArrayNode type json node on specific path
|
||||
* @throws WorkflowException workflow exception
|
||||
@ -288,6 +298,7 @@ public final class JsonDataModelTree implements DataModelTree {
|
||||
|
||||
/**
|
||||
* Gets json node on specific json pointer as ArrayNode.
|
||||
*
|
||||
* @param ptr json pointer
|
||||
* @return ArrayNode type json node on specific json pointer.
|
||||
* @throws WorkflowException workflow exception
|
||||
@ -308,6 +319,7 @@ public final class JsonDataModelTree implements DataModelTree {
|
||||
|
||||
/**
|
||||
* Gets text node on specific path.
|
||||
*
|
||||
* @param path path of json node
|
||||
* @return text on specific path
|
||||
* @throws WorkflowException workflow exception
|
||||
@ -319,6 +331,7 @@ public final class JsonDataModelTree implements DataModelTree {
|
||||
|
||||
/**
|
||||
* Gets text on specific json pointer.
|
||||
*
|
||||
* @param ptr json pointer
|
||||
* @return text on specific json pointer
|
||||
* @throws WorkflowException workflow exception
|
||||
@ -339,6 +352,7 @@ public final class JsonDataModelTree implements DataModelTree {
|
||||
|
||||
/**
|
||||
* Gets integer node on specific path.
|
||||
*
|
||||
* @param path path of json node
|
||||
* @return integer on specific path
|
||||
* @throws WorkflowException workflow exception
|
||||
@ -350,6 +364,7 @@ public final class JsonDataModelTree implements DataModelTree {
|
||||
|
||||
/**
|
||||
* Gets integer on specific json pointer.
|
||||
*
|
||||
* @param ptr json pointer
|
||||
* @return integer on specific json pointer
|
||||
* @throws WorkflowException workflow exception
|
||||
@ -370,6 +385,7 @@ public final class JsonDataModelTree implements DataModelTree {
|
||||
|
||||
/**
|
||||
* Gets boolean on specific path.
|
||||
*
|
||||
* @param path path of json node
|
||||
* @return boolean on specific path
|
||||
* @throws WorkflowException workflow exception
|
||||
@ -381,6 +397,7 @@ public final class JsonDataModelTree implements DataModelTree {
|
||||
|
||||
/**
|
||||
* Gets boolean on specific json pointer.
|
||||
*
|
||||
* @param ptr json pointer
|
||||
* @return boolean on specific json pointer
|
||||
* @throws WorkflowException workflow exception
|
||||
@ -401,6 +418,7 @@ public final class JsonDataModelTree implements DataModelTree {
|
||||
|
||||
/**
|
||||
* Sets text on specific json path.
|
||||
*
|
||||
* @param path json path
|
||||
* @param text text to set
|
||||
* @throws WorkflowException workflow exception
|
||||
@ -412,18 +430,21 @@ public final class JsonDataModelTree implements DataModelTree {
|
||||
|
||||
/**
|
||||
* Sets text on the specific json pointer.
|
||||
* @param ptr json pointer
|
||||
*
|
||||
* @param ptr json pointer
|
||||
* @param text text to set
|
||||
* @throws WorkflowException workflow exception
|
||||
*/
|
||||
public void setAt(JsonPointer ptr, String text) throws WorkflowException {
|
||||
TextNode textNode = TextNode.valueOf(text);
|
||||
|
||||
attach(ptr, textNode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets boolean on specific json path.
|
||||
* @param path json path
|
||||
*
|
||||
* @param path json path
|
||||
* @param isTrue boolean to set
|
||||
* @throws WorkflowException workflow exception
|
||||
*/
|
||||
@ -432,9 +453,84 @@ public final class JsonDataModelTree implements DataModelTree {
|
||||
setAt(ptr, isTrue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets text on the specific json pointer.
|
||||
*
|
||||
* @param ptr json pointer
|
||||
* @param jsonNode jsonNode to set
|
||||
* @throws WorkflowException workflow exception
|
||||
*/
|
||||
public void setAt(JsonPointer ptr, JsonNode jsonNode) throws WorkflowException {
|
||||
JsonNode node = jsonNode;
|
||||
attach(ptr, node);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets boolean on specific json path.
|
||||
*
|
||||
* @param path json path
|
||||
* @param jsonNode jsonNode to set
|
||||
* @throws WorkflowException workflow exception
|
||||
*/
|
||||
public void setAt(String path, JsonNode jsonNode) throws WorkflowException {
|
||||
JsonPointer ptr = JsonPointer.compile(path);
|
||||
setAt(ptr, jsonNode);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets text on the specific json pointer.
|
||||
*
|
||||
* @param ptr json pointer
|
||||
* @param arrayNode arrayNode to set
|
||||
* @throws WorkflowException workflow exception
|
||||
*/
|
||||
public void setAt(JsonPointer ptr, ArrayNode arrayNode) throws WorkflowException {
|
||||
ArrayNode node = arrayNode;
|
||||
attach(ptr, node);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets boolean on specific json path.
|
||||
*
|
||||
* @param path json path
|
||||
* @param arrayNode arrayNode to set
|
||||
* @throws WorkflowException workflow exception
|
||||
*/
|
||||
public void setAt(String path, ArrayNode arrayNode) throws WorkflowException {
|
||||
JsonPointer ptr = JsonPointer.compile(path);
|
||||
setAt(ptr, arrayNode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets text on the specific json pointer.
|
||||
*
|
||||
* @param ptr json pointer
|
||||
* @param objectNode objectNode to set
|
||||
* @throws WorkflowException workflow exception
|
||||
*/
|
||||
public void setAt(JsonPointer ptr, ObjectNode objectNode) throws WorkflowException {
|
||||
ObjectNode node = objectNode;
|
||||
attach(ptr, node);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets boolean on specific json path.
|
||||
*
|
||||
* @param path json path
|
||||
* @param objectNode objectNode to set
|
||||
* @throws WorkflowException workflow exception
|
||||
*/
|
||||
public void setAt(String path, ObjectNode objectNode) throws WorkflowException {
|
||||
JsonPointer ptr = JsonPointer.compile(path);
|
||||
setAt(ptr, objectNode);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets boolean on the specific json pointer.
|
||||
* @param ptr json pointer
|
||||
*
|
||||
* @param ptr json pointer
|
||||
* @param isTrue boolean to set
|
||||
* @throws WorkflowException workflow exception
|
||||
*/
|
||||
@ -445,7 +541,8 @@ public final class JsonDataModelTree implements DataModelTree {
|
||||
|
||||
/**
|
||||
* Sets integer on specific json path.
|
||||
* @param path json path
|
||||
*
|
||||
* @param path json path
|
||||
* @param number number to set
|
||||
* @throws WorkflowException workflow exception
|
||||
*/
|
||||
@ -456,7 +553,8 @@ public final class JsonDataModelTree implements DataModelTree {
|
||||
|
||||
/**
|
||||
* Sets integer on the specific json pointer.
|
||||
* @param ptr json pointer
|
||||
*
|
||||
* @param ptr json pointer
|
||||
* @param number number to set
|
||||
* @throws WorkflowException workflow exception
|
||||
*/
|
||||
@ -467,8 +565,9 @@ public final class JsonDataModelTree implements DataModelTree {
|
||||
|
||||
/**
|
||||
* Allocates json data model tree on json pointer path with specific leaf type.
|
||||
* @param node current json node in the json tree path
|
||||
* @param ptr json pointer
|
||||
*
|
||||
* @param node current json node in the json tree path
|
||||
* @param ptr json pointer
|
||||
* @param leaftype leaf type to be allocated
|
||||
* @return allocated json node
|
||||
* @throws WorkflowException workflow exception
|
||||
@ -510,6 +609,7 @@ public final class JsonDataModelTree implements DataModelTree {
|
||||
|
||||
/**
|
||||
* Creating empty json node.
|
||||
*
|
||||
* @param type json node type to create
|
||||
* @return created json node
|
||||
* @throws WorkflowException workflow exception
|
||||
@ -528,6 +628,7 @@ public final class JsonDataModelTree implements DataModelTree {
|
||||
|
||||
/**
|
||||
* Gets the pretty json formatted string of this json data model tree.
|
||||
*
|
||||
* @return pretty json formatted string of this json data model tree
|
||||
*/
|
||||
public String formattedRootString() {
|
||||
|
||||
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2019-present Open Networking Foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.onosproject.workflow.api;
|
||||
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target(ElementType.FIELD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
|
||||
/**
|
||||
* Annotation for injecting static data model on work-let execution context.
|
||||
*/
|
||||
public @interface StaticDataModel {
|
||||
|
||||
/**
|
||||
* Path of data model.
|
||||
*
|
||||
* @return path of data model
|
||||
*/
|
||||
String path() default "/";
|
||||
|
||||
/**
|
||||
* Representing whether this data model is optional or not.
|
||||
*
|
||||
* @return optional or not
|
||||
*/
|
||||
boolean optional() default false;
|
||||
}
|
||||
@ -0,0 +1,317 @@
|
||||
/*
|
||||
* Copyright 2019-present Open Networking Foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.onosproject.workflow.api;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.node.ArrayNode;
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Map;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
||||
public class StaticDataModelInjector {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(StaticDataModelInjector.class);
|
||||
|
||||
/**
|
||||
* Injects data model to work-let.
|
||||
*
|
||||
* @param worklet work-let to be injected
|
||||
* @param workletDescription worklet description
|
||||
* @throws WorkflowException workflow exception
|
||||
*/
|
||||
public void inject(Worklet worklet, WorkletDescription workletDescription) throws WorkflowException {
|
||||
|
||||
handle(worklet, workletDescription, this::injectModel);
|
||||
}
|
||||
|
||||
private void handle(Worklet worklet, WorkletDescription workletDescription, DataModelFieldBehavior func)
|
||||
throws WorkflowException {
|
||||
Class cl = worklet.getClass();
|
||||
List<Field> fields = getInheritedFields(cl);
|
||||
if (Objects.isNull(fields)) {
|
||||
log.error("Invalid fields on {}", cl);
|
||||
return;
|
||||
}
|
||||
|
||||
for (Field field : fields) {
|
||||
Annotation[] annotations = field.getAnnotations();
|
||||
if (Objects.isNull(annotations)) {
|
||||
continue;
|
||||
}
|
||||
for (Annotation annotation : annotations) {
|
||||
if (!(annotation instanceof StaticDataModel)) {
|
||||
continue;
|
||||
}
|
||||
StaticDataModel model = (StaticDataModel) annotation;
|
||||
func.apply(worklet, workletDescription, field, model);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static List<Field> getInheritedFields(Class<?> type) {
|
||||
List<Field> fields = new ArrayList<Field>();
|
||||
|
||||
Class<?> cl = type;
|
||||
while (cl != null && cl != Object.class) {
|
||||
for (Field field : cl.getDeclaredFields()) {
|
||||
if (!field.isSynthetic()) {
|
||||
fields.add(field);
|
||||
}
|
||||
}
|
||||
cl = cl.getSuperclass();
|
||||
}
|
||||
return fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* Functional interface for json data model annotated field behavior.
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface DataModelFieldBehavior {
|
||||
void apply(Worklet worklet, WorkletDescription workletDescription, Field field, StaticDataModel model)
|
||||
throws WorkflowException;
|
||||
}
|
||||
|
||||
private static Map<Class, DataModelFieldBehavior> injectTypeMap = new HashMap<>();
|
||||
|
||||
static {
|
||||
injectTypeMap.put(String.class, StaticDataModelInjector::injectText);
|
||||
injectTypeMap.put(Integer.class, StaticDataModelInjector::injectInteger);
|
||||
injectTypeMap.put(Boolean.class, StaticDataModelInjector::injectBoolean);
|
||||
injectTypeMap.put(JsonNode.class, StaticDataModelInjector::injectJsonNode);
|
||||
injectTypeMap.put(ArrayNode.class, StaticDataModelInjector::injectArrayNode);
|
||||
injectTypeMap.put(ObjectNode.class, StaticDataModelInjector::injectObjectNode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Injects data model on the filed of work-let.
|
||||
*
|
||||
* @param worklet work-let
|
||||
* @param workletDescription worklet description
|
||||
* @param field the field of work-let
|
||||
* @param model data model for the field
|
||||
* @throws WorkflowException workflow exception
|
||||
*/
|
||||
private void injectModel(Worklet worklet, WorkletDescription workletDescription, Field field, StaticDataModel model)
|
||||
throws WorkflowException {
|
||||
|
||||
DataModelFieldBehavior behavior = injectTypeMap.get(field.getType());
|
||||
if (Objects.isNull(behavior)) {
|
||||
throw new WorkflowException("Not supported type(" + field.getType() + ")");
|
||||
}
|
||||
behavior.apply(worklet, workletDescription, field, model);
|
||||
}
|
||||
|
||||
/**
|
||||
* Injects text data model on the filed of work-let.
|
||||
*
|
||||
* @param worklet work-let
|
||||
* @param workletDescription worklet description
|
||||
* @param field the field of work-let
|
||||
* @param model text data model for the field
|
||||
* @throws WorkflowException workflow exception
|
||||
*/
|
||||
private static void injectText(Worklet worklet, WorkletDescription workletDescription, Field field,
|
||||
StaticDataModel model) throws WorkflowException {
|
||||
|
||||
String text = ((JsonDataModelTree) workletDescription.data()).textAt(model.path());
|
||||
if (Objects.isNull(text)) {
|
||||
if (model.optional()) {
|
||||
return;
|
||||
}
|
||||
throw new WorkflowException("Invalid array node data model on (" + model.path() + ")");
|
||||
}
|
||||
|
||||
|
||||
if (!(Objects.equals(field.getType(), String.class))) {
|
||||
throw new WorkflowException("Target field (" + field + ") is not String");
|
||||
}
|
||||
|
||||
try {
|
||||
field.setAccessible(true);
|
||||
field.set(worklet, text);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new WorkflowException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Injects integer data model on the filed of work-let.
|
||||
*
|
||||
* @param worklet work-let
|
||||
* @param workletDescription worklet description
|
||||
* @param field the field of work-let
|
||||
* @param model integer data model for the field
|
||||
* @throws WorkflowException workflow exception
|
||||
*/
|
||||
private static void injectInteger(Worklet worklet, WorkletDescription workletDescription, Field field,
|
||||
StaticDataModel model) throws WorkflowException {
|
||||
|
||||
Integer number = ((JsonDataModelTree) workletDescription.data()).intAt(model.path());
|
||||
if (Objects.isNull(number)) {
|
||||
if (model.optional()) {
|
||||
return;
|
||||
}
|
||||
throw new WorkflowException("Invalid array node data model on (" + model.path() + ")");
|
||||
}
|
||||
if (!(Objects.equals(field.getType(), Integer.class))) {
|
||||
throw new WorkflowException("Target field (" + field + ") is not Integer");
|
||||
}
|
||||
|
||||
try {
|
||||
field.setAccessible(true);
|
||||
field.set(worklet, number);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new WorkflowException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Injects boolean data model on the filed of work-let.
|
||||
*
|
||||
* @param worklet work-let
|
||||
* @param workletDescription worklet description
|
||||
* @param field the field of work-let
|
||||
* @param model boolean data model for the field
|
||||
* @throws WorkflowException workflow exception
|
||||
*/
|
||||
private static void injectBoolean(Worklet worklet, WorkletDescription workletDescription, Field field,
|
||||
StaticDataModel model) throws WorkflowException {
|
||||
|
||||
Boolean bool = ((JsonDataModelTree) workletDescription.data()).booleanAt(model.path());
|
||||
if (Objects.isNull(bool)) {
|
||||
if (model.optional()) {
|
||||
return;
|
||||
}
|
||||
throw new WorkflowException("Invalid boolean data model on (" + model.path() + ")");
|
||||
}
|
||||
|
||||
if (!(Objects.equals(field.getType(), Boolean.class))) {
|
||||
throw new WorkflowException("Target field (" + field + ") is not Boolean");
|
||||
}
|
||||
|
||||
try {
|
||||
field.setAccessible(true);
|
||||
field.set(worklet, bool);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new WorkflowException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Injects json node data model on the filed of work-let.
|
||||
*
|
||||
* @param worklet work-let
|
||||
* @param workletDescription worklet description
|
||||
* @param field the field of work-let
|
||||
* @param model json node data model for the field
|
||||
* @throws WorkflowException workflow exception
|
||||
*/
|
||||
private static void injectJsonNode(Worklet worklet, WorkletDescription workletDescription, Field field,
|
||||
StaticDataModel model) throws WorkflowException {
|
||||
|
||||
JsonNode jsonNode = ((JsonDataModelTree) workletDescription.data()).nodeAt(model.path());
|
||||
if (Objects.isNull(jsonNode)) {
|
||||
if (model.optional()) {
|
||||
return;
|
||||
}
|
||||
throw new WorkflowException("Invalid json node data model on (" + model.path() + ")");
|
||||
}
|
||||
|
||||
if (!(Objects.equals(field.getType(), JsonNode.class))) {
|
||||
throw new WorkflowException("Target field (" + field + ") is not JsonNode");
|
||||
}
|
||||
|
||||
try {
|
||||
field.setAccessible(true);
|
||||
field.set(worklet, jsonNode);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new WorkflowException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Injects json array node data model on the filed of work-let.
|
||||
*
|
||||
* @param worklet work-let
|
||||
* @param workletDescription worklet description
|
||||
* @param field the field of work-let
|
||||
* @param model json array node data model for the field
|
||||
* @throws WorkflowException workflow exception
|
||||
*/
|
||||
private static void injectArrayNode(Worklet worklet, WorkletDescription workletDescription, Field field,
|
||||
StaticDataModel model) throws WorkflowException {
|
||||
|
||||
ArrayNode arrayNode = ((JsonDataModelTree) workletDescription.data()).arrayAt(model.path());
|
||||
if (Objects.isNull(arrayNode)) {
|
||||
if (model.optional()) {
|
||||
return;
|
||||
}
|
||||
throw new WorkflowException("Invalid array node data model on (" + model.path() + ")");
|
||||
}
|
||||
|
||||
if (!(Objects.equals(field.getType(), ArrayNode.class))) {
|
||||
throw new WorkflowException("Target field (" + field + ") is not ArrayNode");
|
||||
}
|
||||
|
||||
try {
|
||||
field.setAccessible(true);
|
||||
field.set(worklet, arrayNode);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new WorkflowException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Injects json object node data model on the filed of work-let.
|
||||
*
|
||||
* @param worklet work-let
|
||||
* @param workletDescription worklet description
|
||||
* @param field the field of work-let
|
||||
* @param model json object node data model for the field
|
||||
* @throws WorkflowException workflow exception
|
||||
*/
|
||||
private static void injectObjectNode(Worklet worklet, WorkletDescription workletDescription, Field field,
|
||||
StaticDataModel model) throws WorkflowException {
|
||||
|
||||
ObjectNode objNode = ((JsonDataModelTree) workletDescription.data()).objectAt(model.path());
|
||||
if (Objects.isNull(objNode)) {
|
||||
if (model.optional()) {
|
||||
return;
|
||||
}
|
||||
throw new WorkflowException("Invalid object node data model on (" + model.path() + ")");
|
||||
}
|
||||
|
||||
if (!(Objects.equals(field.getType(), ObjectNode.class))) {
|
||||
throw new WorkflowException("Target field (" + field + ") is not ObjectNode");
|
||||
}
|
||||
|
||||
try {
|
||||
field.setAccessible(true);
|
||||
field.set(worklet, objNode);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new WorkflowException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -26,12 +26,14 @@ public interface Workflow {
|
||||
|
||||
/**
|
||||
* Id of workflow.
|
||||
*
|
||||
* @return id
|
||||
*/
|
||||
URI id();
|
||||
|
||||
/**
|
||||
* Returns init worklet.
|
||||
*
|
||||
* @param context workflow context
|
||||
* @return init worklet
|
||||
* @throws WorkflowException workflow exception
|
||||
@ -40,6 +42,7 @@ public interface Workflow {
|
||||
|
||||
/**
|
||||
* Returns next program counter.
|
||||
*
|
||||
* @param context workflow context
|
||||
* @return next program counter
|
||||
* @throws WorkflowException workflow exception
|
||||
@ -48,6 +51,7 @@ public interface Workflow {
|
||||
|
||||
/**
|
||||
* Gets increased program coounter.
|
||||
*
|
||||
* @param pc program counter
|
||||
* @return increased program counter
|
||||
* @throws WorkflowException workflow exception
|
||||
@ -56,6 +60,7 @@ public interface Workflow {
|
||||
|
||||
/**
|
||||
* Returns instance of worklet.
|
||||
*
|
||||
* @param pc program counter
|
||||
* @return instance of worklet
|
||||
* @throws WorkflowException workflow exception
|
||||
@ -64,6 +69,7 @@ public interface Workflow {
|
||||
|
||||
/**
|
||||
* Returns instance of worklet.
|
||||
*
|
||||
* @param workletType class name of worklet
|
||||
* @return instance of worklet
|
||||
* @throws WorkflowException workflow exception
|
||||
@ -72,8 +78,9 @@ public interface Workflow {
|
||||
|
||||
/**
|
||||
* Builds workflow context.
|
||||
*
|
||||
* @param workplace workplace of system workflow
|
||||
* @param data data model of system workflow context
|
||||
* @param data data model of system workflow context
|
||||
* @return workflow context
|
||||
* @throws WorkflowException workflow exception
|
||||
*/
|
||||
@ -81,8 +88,9 @@ public interface Workflow {
|
||||
|
||||
/**
|
||||
* Builds system workflow context.
|
||||
*
|
||||
* @param workplace workplace of system workflow
|
||||
* @param data data model of system workflow context
|
||||
* @param data data model of system workflow context
|
||||
* @return system workflow context
|
||||
* @throws WorkflowException workflow exception
|
||||
*/
|
||||
@ -90,13 +98,23 @@ public interface Workflow {
|
||||
|
||||
/**
|
||||
* Returns workflow attributes.
|
||||
*
|
||||
* @return attributes
|
||||
*/
|
||||
Set<WorkflowAttribute> attributes();
|
||||
|
||||
/**
|
||||
* Returns worklet type list.
|
||||
* @return worklet type
|
||||
* Returns worklet desc list.
|
||||
*
|
||||
* @return worklet description list
|
||||
*/
|
||||
List<String> getWorkletTypeList();
|
||||
List<WorkletDescription> getWorkletDescList();
|
||||
|
||||
/**
|
||||
* Returns worklet description.
|
||||
* @param pc program counter
|
||||
* @return worklet description list
|
||||
*/
|
||||
WorkletDescription getWorkletDesc(ProgramCounter pc);
|
||||
|
||||
}
|
||||
|
||||
@ -25,18 +25,21 @@ public interface WorkflowStore {
|
||||
|
||||
/**
|
||||
* Registers workflow.
|
||||
*
|
||||
* @param workflow registering workflow
|
||||
*/
|
||||
void register(Workflow workflow);
|
||||
|
||||
/**
|
||||
* Unregisters workflow.
|
||||
*
|
||||
* @param id id of workflow
|
||||
*/
|
||||
void unregister(URI id);
|
||||
|
||||
/**
|
||||
* Gets workflow.
|
||||
*
|
||||
* @param id id of workflow
|
||||
* @return workflow
|
||||
*/
|
||||
@ -44,27 +47,32 @@ public interface WorkflowStore {
|
||||
|
||||
/**
|
||||
* Gets all workflow.
|
||||
*
|
||||
* @return collection of workflow
|
||||
*/
|
||||
Collection<Workflow> getAll();
|
||||
|
||||
/**
|
||||
* Registers local class loader.
|
||||
*
|
||||
* @param loader class loader
|
||||
*/
|
||||
void registerLocal(ClassLoader loader);
|
||||
|
||||
/**
|
||||
* Unregisters local class loader.
|
||||
*
|
||||
* @param loader class loader
|
||||
*/
|
||||
void unregisterLocal(ClassLoader loader);
|
||||
|
||||
/**
|
||||
* Gets class from registered class loaders.
|
||||
*
|
||||
* @param name name of class
|
||||
* @return class
|
||||
* @throws ClassNotFoundException class not found exception
|
||||
*/
|
||||
Class getClass(String name) throws ClassNotFoundException;
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2019-present Open Networking Foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.onosproject.workflow.api;
|
||||
|
||||
|
||||
public interface WorkletDescription {
|
||||
|
||||
/**
|
||||
* Gets worklet name.
|
||||
*
|
||||
* @return worklet name
|
||||
*/
|
||||
String tag();
|
||||
|
||||
/**
|
||||
* Gets worklet data model.
|
||||
*
|
||||
* @return worklet data model
|
||||
*/
|
||||
JsonDataModelTree data();
|
||||
|
||||
|
||||
}
|
||||
@ -122,8 +122,8 @@ public class WorkFlowTestCommand extends AbstractShellCommand {
|
||||
for (int i = 0; i <= num; i++) {
|
||||
String wpName = "test_name-" + i;
|
||||
invoke("sample.workflow-0", wpName);
|
||||
invoke("sample.workflow-1", wpName);
|
||||
invoke("sample.workflow-2", wpName);
|
||||
// invoke("sample.workflow-1", wpName);
|
||||
// invoke("sample.workflow-2", wpName);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -19,6 +19,15 @@ import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Sets;
|
||||
import org.onlab.util.KryoNamespace;
|
||||
import org.onosproject.store.service.EventuallyConsistentMap;
|
||||
import org.onosproject.store.service.StorageService;
|
||||
import org.onosproject.store.service.WallClockTimestamp;
|
||||
import org.onosproject.workflow.api.AbstractWorkflow;
|
||||
import org.onosproject.workflow.api.ImmutableListWorkflow;
|
||||
import org.onosproject.workflow.api.Workflow;
|
||||
import org.onosproject.workflow.api.WorkflowAttribute;
|
||||
import org.onosproject.workflow.api.WorkflowStore;
|
||||
import org.onosproject.workflow.api.WorkletDescription;
|
||||
import org.osgi.service.component.annotations.Activate;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
import org.osgi.service.component.annotations.Deactivate;
|
||||
@ -27,18 +36,10 @@ import org.osgi.service.component.annotations.ReferenceCardinality;
|
||||
import org.slf4j.Logger;
|
||||
import org.onosproject.core.ApplicationId;
|
||||
import org.onosproject.core.CoreService;
|
||||
import org.onosproject.workflow.api.AbstractWorkflow;
|
||||
import org.onosproject.workflow.api.ImmutableListWorkflow;
|
||||
import org.onosproject.workflow.api.Workflow;
|
||||
import org.onosproject.workflow.api.WorkflowAttribute;
|
||||
import org.onosproject.workflow.api.WorkflowStore;
|
||||
import org.onosproject.net.group.GroupEvent;
|
||||
import org.onosproject.net.group.GroupStoreDelegate;
|
||||
import org.onosproject.store.AbstractStore;
|
||||
import org.onosproject.store.serializers.KryoNamespaces;
|
||||
import org.onosproject.store.service.EventuallyConsistentMap;
|
||||
import org.onosproject.store.service.StorageService;
|
||||
import org.onosproject.store.service.WallClockTimestamp;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Collection;
|
||||
@ -51,7 +52,7 @@ import static org.slf4j.LoggerFactory.getLogger;
|
||||
|
||||
@Component(immediate = true, service = WorkflowStore.class)
|
||||
public class ECWorkFlowStore
|
||||
extends AbstractStore<GroupEvent, GroupStoreDelegate> implements WorkflowStore {
|
||||
extends AbstractStore<GroupEvent, GroupStoreDelegate> implements WorkflowStore {
|
||||
|
||||
private final Logger log = getLogger(getClass());
|
||||
|
||||
@ -77,6 +78,7 @@ public class ECWorkFlowStore
|
||||
.register(Workflow.class)
|
||||
.register(AbstractWorkflow.class)
|
||||
.register(ImmutableListWorkflow.class)
|
||||
.register(WorkletDescription.class)
|
||||
.register(List.class)
|
||||
.register(ImmutableList.class)
|
||||
.register(Class.class)
|
||||
@ -101,7 +103,6 @@ public class ECWorkFlowStore
|
||||
@Deactivate
|
||||
public void deactivate() {
|
||||
workflowStore.destroy();
|
||||
|
||||
log.info("Stopped");
|
||||
}
|
||||
|
||||
|
||||
@ -49,6 +49,8 @@ import org.onosproject.workflow.api.Workplace;
|
||||
import org.onosproject.workflow.api.WorkplaceStore;
|
||||
import org.onosproject.workflow.api.WorkplaceStoreDelegate;
|
||||
import org.onosproject.workflow.api.WorkflowExecutionService;
|
||||
import org.onosproject.workflow.api.WorkletDescription;
|
||||
import org.onosproject.workflow.api.StaticDataModelInjector;
|
||||
import org.onosproject.event.AbstractListenerManager;
|
||||
import org.onosproject.event.Event;
|
||||
import org.onosproject.net.intent.WorkPartitionService;
|
||||
@ -126,6 +128,7 @@ public class WorkFlowEngine extends AbstractListenerManager<WorkflowDataEvent, W
|
||||
private TimerChain timerChain = new TimerChain();
|
||||
|
||||
private JsonDataModelInjector dataModelInjector = new JsonDataModelInjector();
|
||||
private StaticDataModelInjector staticDataModelInjector = new StaticDataModelInjector();
|
||||
|
||||
public static final String APPID = "org.onosproject.workflow";
|
||||
private ApplicationId appId;
|
||||
@ -273,11 +276,11 @@ public class WorkFlowEngine extends AbstractListenerManager<WorkflowDataEvent, W
|
||||
EventTask eventtask = null;
|
||||
try {
|
||||
eventtask = EventTask.builder()
|
||||
.event(event)
|
||||
.eventHint(eventHint)
|
||||
.context(context)
|
||||
.programCounter(pc)
|
||||
.build();
|
||||
.event(event)
|
||||
.eventHint(eventHint)
|
||||
.context(context)
|
||||
.programCounter(pc)
|
||||
.build();
|
||||
} catch (WorkflowException e) {
|
||||
log.error("Exception: ", e);
|
||||
}
|
||||
@ -358,6 +361,7 @@ public class WorkFlowEngine extends AbstractListenerManager<WorkflowDataEvent, W
|
||||
|
||||
/**
|
||||
* Checks whether this workflow data job is relevant to this ONOS node.
|
||||
*
|
||||
* @param job workflow data
|
||||
* @return checking result
|
||||
*/
|
||||
@ -368,6 +372,7 @@ public class WorkFlowEngine extends AbstractListenerManager<WorkflowDataEvent, W
|
||||
|
||||
/**
|
||||
* Gets hash of the string.
|
||||
*
|
||||
* @param str string to get a hash
|
||||
* @return hash value
|
||||
*/
|
||||
@ -404,6 +409,7 @@ public class WorkFlowEngine extends AbstractListenerManager<WorkflowDataEvent, W
|
||||
|
||||
/**
|
||||
* Initializes worklet execution.
|
||||
*
|
||||
* @param context workflow context
|
||||
*/
|
||||
private void initWorkletExecution(WorkflowContext context) {
|
||||
@ -418,6 +424,7 @@ public class WorkFlowEngine extends AbstractListenerManager<WorkflowDataEvent, W
|
||||
|
||||
/**
|
||||
* Processes handler tasks.
|
||||
*
|
||||
* @param tasks handler tasks
|
||||
* @return handler tasks processed
|
||||
*/
|
||||
@ -440,6 +447,7 @@ public class WorkFlowEngine extends AbstractListenerManager<WorkflowDataEvent, W
|
||||
|
||||
/**
|
||||
* Executes event task.
|
||||
*
|
||||
* @param task event task
|
||||
* @return event task
|
||||
*/
|
||||
@ -530,6 +538,7 @@ public class WorkFlowEngine extends AbstractListenerManager<WorkflowDataEvent, W
|
||||
|
||||
/**
|
||||
* Executes event timeout task.
|
||||
*
|
||||
* @param task event timeout task
|
||||
* @return handler task
|
||||
*/
|
||||
@ -576,6 +585,14 @@ public class WorkFlowEngine extends AbstractListenerManager<WorkflowDataEvent, W
|
||||
log.trace("{} task:{}, context: {}", latestContext.name(), task, latestContext);
|
||||
|
||||
dataModelInjector.inject(worklet, latestContext);
|
||||
|
||||
WorkletDescription workletDesc = workflow.getWorkletDesc(task.programCounter());
|
||||
if (Objects.nonNull(workletDesc)) {
|
||||
if (!(workletDesc.tag().equals("INIT") || workletDesc.tag().equals("COMPLETED"))) {
|
||||
staticDataModelInjector.inject(worklet, workletDesc);
|
||||
}
|
||||
}
|
||||
|
||||
worklet.timeout(latestContext);
|
||||
dataModelInjector.inhale(worklet, latestContext);
|
||||
|
||||
@ -605,6 +622,7 @@ public class WorkFlowEngine extends AbstractListenerManager<WorkflowDataEvent, W
|
||||
|
||||
/**
|
||||
* Executes timeout task.
|
||||
*
|
||||
* @param task time out task
|
||||
* @return handler task
|
||||
*/
|
||||
@ -644,6 +662,14 @@ public class WorkFlowEngine extends AbstractListenerManager<WorkflowDataEvent, W
|
||||
log.trace("{} context: {}", latestContext.name(), latestContext);
|
||||
|
||||
dataModelInjector.inject(worklet, latestContext);
|
||||
|
||||
WorkletDescription workletDesc = workflow.getWorkletDesc(task.programCounter());
|
||||
if (Objects.nonNull(workletDesc)) {
|
||||
if (!(workletDesc.tag().equals("INIT") || workletDesc.tag().equals("COMPLETED"))) {
|
||||
staticDataModelInjector.inject(worklet, workletDesc);
|
||||
}
|
||||
}
|
||||
|
||||
worklet.timeout(latestContext);
|
||||
dataModelInjector.inhale(worklet, latestContext);
|
||||
|
||||
@ -682,8 +708,8 @@ public class WorkFlowEngine extends AbstractListenerManager<WorkflowDataEvent, W
|
||||
List<CompletableFuture<WorkflowData>> futures = operations.stream()
|
||||
.map(
|
||||
x -> CompletableFuture.completedFuture(x)
|
||||
.thenApplyAsync(WorkFlowEngine.this::execWorkflow, workflowExecutor)
|
||||
.exceptionally(e -> null)
|
||||
.thenApplyAsync(WorkFlowEngine.this::execWorkflow, workflowExecutor)
|
||||
.exceptionally(e -> null)
|
||||
)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
@ -699,6 +725,7 @@ public class WorkFlowEngine extends AbstractListenerManager<WorkflowDataEvent, W
|
||||
|
||||
/**
|
||||
* Executes workflow.
|
||||
*
|
||||
* @param dataModelContainer workflow data model container(workflow or workplace)
|
||||
* @return
|
||||
*/
|
||||
@ -715,6 +742,7 @@ public class WorkFlowEngine extends AbstractListenerManager<WorkflowDataEvent, W
|
||||
|
||||
/**
|
||||
* Executes workflow context.
|
||||
*
|
||||
* @param context workflow context
|
||||
* @return workflow context
|
||||
*/
|
||||
@ -759,7 +787,16 @@ public class WorkFlowEngine extends AbstractListenerManager<WorkflowDataEvent, W
|
||||
log.info("{} worklet.process:{}", latestContext.name(), worklet.tag());
|
||||
log.trace("{} context: {}", latestContext.name(), latestContext);
|
||||
|
||||
|
||||
dataModelInjector.inject(worklet, latestContext);
|
||||
|
||||
WorkletDescription workletDesc = workflow.getWorkletDesc(pc);
|
||||
if (Objects.nonNull(workletDesc)) {
|
||||
if (!(workletDesc.tag().equals("INIT") || workletDesc.tag().equals("COMPLETED"))) {
|
||||
staticDataModelInjector.inject(worklet, workletDesc);
|
||||
}
|
||||
}
|
||||
|
||||
worklet.process(latestContext);
|
||||
dataModelInjector.inhale(worklet, latestContext);
|
||||
|
||||
@ -832,6 +869,7 @@ public class WorkFlowEngine extends AbstractListenerManager<WorkflowDataEvent, W
|
||||
|
||||
/**
|
||||
* Execute workplace.
|
||||
*
|
||||
* @param workplace workplace
|
||||
* @return workplace
|
||||
*/
|
||||
|
||||
@ -40,6 +40,7 @@ import org.onosproject.workflow.api.Workflow;
|
||||
import org.onosproject.workflow.api.Worklet;
|
||||
import org.onosproject.workflow.api.WorkflowContext;
|
||||
import org.onosproject.workflow.api.JsonDataModel;
|
||||
import org.onosproject.workflow.api.WorkletDescription;
|
||||
import org.osgi.service.component.annotations.Activate;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
import org.osgi.service.component.annotations.Deactivate;
|
||||
@ -174,9 +175,9 @@ public class WorkflowManager implements WorkflowService {
|
||||
|
||||
List<String> errors = new ArrayList<>();
|
||||
|
||||
for (String workletType : workflow.getWorkletTypeList()) {
|
||||
for (WorkletDescription workletType : workflow.getWorkletDescList()) {
|
||||
|
||||
Worklet worklet = workflow.getWorkletInstance(workletType);
|
||||
Worklet worklet = workflow.getWorkletInstance(workletType.tag());
|
||||
if (Worklet.Common.COMPLETED.equals(worklet) || Worklet.Common.INIT.equals(worklet)) {
|
||||
continue;
|
||||
}
|
||||
@ -203,7 +204,8 @@ public class WorkflowManager implements WorkflowService {
|
||||
String path = matcher.group(1);
|
||||
|
||||
WorkletDataModelFieldDesc desc =
|
||||
new WorkletDataModelFieldDesc(workletType, path, field.getType(), jsonDataModel.optional());
|
||||
new WorkletDataModelFieldDesc(workletType.tag(), path, field.getType(),
|
||||
jsonDataModel.optional());
|
||||
|
||||
WorkletDataModelFieldDesc existing = descMap.get(path);
|
||||
|
||||
@ -296,9 +298,9 @@ public class WorkflowManager implements WorkflowService {
|
||||
throw new WorkflowDataModelException(workflow.id(), worklowDescJson, errors);
|
||||
}
|
||||
|
||||
for (String workletType : workflow.getWorkletTypeList()) {
|
||||
for (WorkletDescription workletType : workflow.getWorkletDescList()) {
|
||||
|
||||
Worklet worklet = workflow.getWorkletInstance(workletType);
|
||||
Worklet worklet = workflow.getWorkletInstance(workletType.tag());
|
||||
if (Worklet.Common.COMPLETED.equals(worklet) || Worklet.Common.INIT.equals(worklet)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -29,6 +29,8 @@ import org.onosproject.workflow.api.WorkflowContext;
|
||||
import org.onosproject.workflow.api.WorkflowException;
|
||||
import org.onosproject.workflow.api.WorkflowService;
|
||||
import org.onosproject.workflow.api.WorkflowStore;
|
||||
import org.onosproject.workflow.api.StaticDataModel;
|
||||
import org.onosproject.workflow.api.DefaultWorkletDescription;
|
||||
import org.osgi.service.component.annotations.Activate;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
import org.osgi.service.component.annotations.Deactivate;
|
||||
@ -64,8 +66,7 @@ public class SampleWorkflow {
|
||||
try {
|
||||
registerWorkflows();
|
||||
} catch (WorkflowException e) {
|
||||
log.error("exception: " + e);
|
||||
e.printStackTrace();
|
||||
log.error("invalid workflow");
|
||||
}
|
||||
}
|
||||
|
||||
@ -76,14 +77,17 @@ public class SampleWorkflow {
|
||||
|
||||
/**
|
||||
* Registers example workflows.
|
||||
*
|
||||
* @throws WorkflowException wfex
|
||||
*/
|
||||
private void registerWorkflows() throws WorkflowException {
|
||||
public void registerWorkflows() throws WorkflowException {
|
||||
// registering class-loader
|
||||
workflowStore.registerLocal(this.getClass().getClassLoader());
|
||||
|
||||
// registering new workflow definition
|
||||
URI uri = URI.create("sample.workflow-0");
|
||||
Workflow workflow = ImmutableListWorkflow.builder()
|
||||
Workflow workflow = null;
|
||||
workflow = ImmutableListWorkflow.builder()
|
||||
.id(uri)
|
||||
.chain(SampleWorklet1.class.getName())
|
||||
.chain(SampleWorklet2.class.getName())
|
||||
@ -125,6 +129,16 @@ public class SampleWorkflow {
|
||||
.build();
|
||||
workflowService.register(workflow);
|
||||
|
||||
// registering new workflow definition
|
||||
uri = URI.create("sample.workflow-static-datamodel");
|
||||
workflow = ImmutableListWorkflow.builder()
|
||||
.id(uri)
|
||||
.chain(DefaultWorkletDescription.builder()
|
||||
.name(SampleWorklet6.class.getName())
|
||||
.staticDataModel("/sample", "value")
|
||||
.build())
|
||||
.build();
|
||||
workflowService.register(workflow);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -142,8 +156,10 @@ public class SampleWorkflow {
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Allocates or gets data model.
|
||||
*
|
||||
* @param context workflow context
|
||||
* @return json object node
|
||||
* @throws WorkflowException workflow exception
|
||||
@ -161,6 +177,7 @@ public class SampleWorkflow {
|
||||
|
||||
/**
|
||||
* Gets data model.
|
||||
*
|
||||
* @param context workflow context
|
||||
* @return json object node
|
||||
* @throws WorkflowException workflow exception
|
||||
@ -172,6 +189,7 @@ public class SampleWorkflow {
|
||||
|
||||
/**
|
||||
* Sleeps for 'ms' milli seconds.
|
||||
*
|
||||
* @param ms milli seconds to sleep
|
||||
*/
|
||||
protected void sleep(long ms) {
|
||||
@ -198,7 +216,6 @@ public class SampleWorkflow {
|
||||
node.put("work1", "done");
|
||||
log.info("workflow-process {}-{}", context.workplaceName(), this.getClass().getSimpleName());
|
||||
sleep(30);
|
||||
|
||||
context.completed(); //Complete the job of worklet in the process
|
||||
}
|
||||
|
||||
@ -226,6 +243,7 @@ public class SampleWorkflow {
|
||||
node.put("work2", "done");
|
||||
log.info("workflow-process {}-{}", context.workplaceName(), this.getClass().getSimpleName());
|
||||
sleep(50);
|
||||
|
||||
intCount++;
|
||||
|
||||
context.waitFor(50L); //Timeout will happen after 50 milli seconds.
|
||||
@ -243,6 +261,7 @@ public class SampleWorkflow {
|
||||
sleep(50);
|
||||
return !node.has("work2");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class SampleWorklet3 extends AbsSampleWorklet {
|
||||
@ -342,4 +361,32 @@ public class SampleWorkflow {
|
||||
return !node.has("work6");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Class for sample worklet-7 to test workflow datamodel exception.
|
||||
*/
|
||||
public static class SampleWorklet7 extends AbsSampleWorklet {
|
||||
|
||||
@StaticDataModel(path = "/sample")
|
||||
String value;
|
||||
|
||||
@Override
|
||||
public void process(WorkflowContext context) throws WorkflowException {
|
||||
ObjectNode node = getDataModel(context);
|
||||
node.put("work7", "done");
|
||||
log.info("inside worklet - static data model {}", value);
|
||||
log.info("workflow-process {}-{}", context.workplaceName(), this.getClass().getSimpleName());
|
||||
sleep(10);
|
||||
context.completed();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNext(WorkflowContext context) throws WorkflowException {
|
||||
ObjectNode node = allocOrGetModel(context);
|
||||
log.info("workflow-isNext {}-{}", context.workplaceName(), this.getClass().getSimpleName());
|
||||
sleep(10);
|
||||
return !node.has("work7");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -21,6 +21,8 @@ import org.onosproject.workflow.api.Workflow;
|
||||
import org.onosproject.workflow.api.WorkflowExecutionService;
|
||||
import org.onosproject.workflow.api.WorkflowStore;
|
||||
import org.onosproject.workflow.api.WorkplaceStore;
|
||||
import org.onosproject.workflow.api.DefaultWorkletDescription;
|
||||
import org.onosproject.workflow.api.WorkflowException;
|
||||
import org.osgi.service.component.annotations.Activate;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
import org.osgi.service.component.annotations.Deactivate;
|
||||
@ -57,6 +59,8 @@ public class OfOverlayWorkflow {
|
||||
|
||||
private ScheduledExecutorService eventMapTriggerExecutor;
|
||||
|
||||
private static final String BRIDGE_NAME = "/bridgeName";
|
||||
|
||||
@Activate
|
||||
public void activate() {
|
||||
log.info("Activated");
|
||||
@ -77,108 +81,117 @@ public class OfOverlayWorkflow {
|
||||
* Registers workflows.
|
||||
*/
|
||||
private void registerWorkflows() {
|
||||
// registering class-loader
|
||||
workflowStore.registerLocal(this.getClass().getClassLoader());
|
||||
try {
|
||||
// registering class-loader
|
||||
workflowStore.registerLocal(this.getClass().getClassLoader());
|
||||
|
||||
// registering new workflow definition
|
||||
URI uri = URI.create("of-overlay.workflow-nova");
|
||||
Workflow workflow = ImmutableListWorkflow.builder()
|
||||
.id(uri)
|
||||
//.attribute(WorkflowAttribute.REMOVE_AFTER_COMPLETE)
|
||||
.chain(Ovs.CreateOvsdbDevice.class.getName())
|
||||
.chain(Ovs.UpdateOvsVersion.class.getName())
|
||||
.chain(Ovs.UpdateOverlayBridgeId.class.getName())
|
||||
.chain(Ovs.CreateOverlayBridge.class.getName())
|
||||
.chain(Ovs.UpdateUnderlayBridgeId.class.getName())
|
||||
.chain(Ovs.CreateUnderlayBridge.class.getName())
|
||||
.chain(Ovs.CreateOverlayBridgeVxlanPort.class.getName())
|
||||
.chain(Ovs.AddPhysicalPortsOnUnderlayBridge.class.getName())
|
||||
.chain(Ovs.ConfigureUnderlayBridgeLocalIp.class.getName())
|
||||
.build();
|
||||
workflowStore.register(workflow);
|
||||
// registering new workflow definition
|
||||
URI uri = URI.create("of-overlay.workflow-nova");
|
||||
Workflow workflow = ImmutableListWorkflow.builder()
|
||||
.id(uri)
|
||||
//.attribute(WorkflowAttribute.REMOVE_AFTER_COMPLETE)
|
||||
.chain(Ovs.CreateOvsdbDevice.class.getName())
|
||||
.chain(Ovs.UpdateOvsVersion.class.getName())
|
||||
.chain(Ovs.UpdateOverlayBridgeId.class.getName())
|
||||
.chain(DefaultWorkletDescription.builder().name(Ovs.CreateBridge.class.getName())
|
||||
.staticDataModel(BRIDGE_NAME, "br-int")
|
||||
.build())
|
||||
.chain(Ovs.UpdateUnderlayBridgeId.class.getName())
|
||||
.chain(DefaultWorkletDescription.builder().name(Ovs.CreateBridge.class.getName())
|
||||
.staticDataModel(BRIDGE_NAME, "br-phy")
|
||||
.build())
|
||||
.chain(Ovs.CreateOverlayBridgeVxlanPort.class.getName())
|
||||
.chain(Ovs.AddPhysicalPortsOnUnderlayBridge.class.getName())
|
||||
.chain(Ovs.ConfigureUnderlayBridgeLocalIp.class.getName())
|
||||
.build();
|
||||
|
||||
// registering new workflow definition based on multi-event handling
|
||||
uri = URI.create("of-overlay.workflow-nova-multiEvent-test");
|
||||
workflow = ImmutableListWorkflow.builder()
|
||||
.id(uri)
|
||||
//.attribute(WorkflowAttribute.REMOVE_AFTER_COMPLETE)
|
||||
.chain(Ovs.CreateOvsdbDevice.class.getName())
|
||||
.chain(Ovs.UpdateOvsVersion.class.getName())
|
||||
.chain(Ovs.UpdateOverlayBridgeId.class.getName())
|
||||
.chain(Ovs.CreateOverlayBridgeMultiEvent.class.getName())
|
||||
.chain(Ovs.UpdateUnderlayBridgeId.class.getName())
|
||||
.chain(Ovs.CreateUnderlayBridge.class.getName())
|
||||
.chain(Ovs.CreateOverlayBridgeVxlanPort.class.getName())
|
||||
.chain(Ovs.AddPhysicalPortsOnUnderlayBridge.class.getName())
|
||||
.chain(Ovs.ConfigureUnderlayBridgeLocalIp.class.getName())
|
||||
.build();
|
||||
workflowStore.register(workflow);
|
||||
workflowStore.register(workflow);
|
||||
|
||||
uri = URI.create("of-overlay.clean-workflow-nova");
|
||||
workflow = ImmutableListWorkflow.builder()
|
||||
.id(uri)
|
||||
//.attribute(WorkflowAttribute.REMOVE_AFTER_COMPLETE)
|
||||
.chain(Ovs.DeleteOverlayBridgeConfig.class.getName())
|
||||
.chain(Ovs.RemoveOverlayBridgeOfDevice.class.getName())
|
||||
.chain(Ovs.DeleteUnderlayBridgeConfig.class.getName())
|
||||
.chain(Ovs.RemoveUnderlayBridgeOfDevice.class.getName())
|
||||
.chain(Ovs.RemoveOvsdbDevice.class.getName())
|
||||
.build();
|
||||
workflowStore.register(workflow);
|
||||
// registering new workflow definition based on multi-event handling
|
||||
uri = URI.create("of-overlay.workflow-nova-multiEvent-test");
|
||||
workflow = ImmutableListWorkflow.builder()
|
||||
.id(uri)
|
||||
//.attribute(WorkflowAttribute.REMOVE_AFTER_COMPLETE)
|
||||
.chain(Ovs.CreateOvsdbDevice.class.getName())
|
||||
.chain(Ovs.UpdateOvsVersion.class.getName())
|
||||
.chain(Ovs.UpdateOverlayBridgeId.class.getName())
|
||||
.chain(Ovs.CreateOverlayBridgeMultiEvent.class.getName())
|
||||
.chain(Ovs.UpdateUnderlayBridgeId.class.getName())
|
||||
.chain(Ovs.CreateUnderlayBridge.class.getName())
|
||||
.chain(Ovs.CreateOverlayBridgeVxlanPort.class.getName())
|
||||
.chain(Ovs.AddPhysicalPortsOnUnderlayBridge.class.getName())
|
||||
.chain(Ovs.ConfigureUnderlayBridgeLocalIp.class.getName())
|
||||
.build();
|
||||
workflowStore.register(workflow);
|
||||
|
||||
uri = URI.create("of-overlay.clean-workflow-nova-waitAll-Bridge-Del");
|
||||
workflow = ImmutableListWorkflow.builder()
|
||||
.id(uri)
|
||||
//.attribute(WorkflowAttribute.REMOVE_AFTER_COMPLETE)
|
||||
.chain(Ovs.DeleteOverlayBridgeConfig.class.getName())
|
||||
.chain(Ovs.DeleteUnderlayBridgeConfig.class.getName())
|
||||
.chain(Ovs.RemoveBridgeOfDevice.class.getName())
|
||||
.chain(Ovs.RemoveOvsdbDevice.class.getName())
|
||||
.build();
|
||||
workflowStore.register(workflow);
|
||||
uri = URI.create("of-overlay.clean-workflow-nova");
|
||||
workflow = ImmutableListWorkflow.builder()
|
||||
.id(uri)
|
||||
//.attribute(WorkflowAttribute.REMOVE_AFTER_COMPLETE)
|
||||
.chain(Ovs.DeleteOverlayBridgeConfig.class.getName())
|
||||
.chain(Ovs.RemoveOverlayBridgeOfDevice.class.getName())
|
||||
.chain(Ovs.DeleteUnderlayBridgeConfig.class.getName())
|
||||
.chain(Ovs.RemoveUnderlayBridgeOfDevice.class.getName())
|
||||
.chain(Ovs.RemoveOvsdbDevice.class.getName())
|
||||
.build();
|
||||
workflowStore.register(workflow);
|
||||
|
||||
uri = URI.create("of-overlay.workflow-ovs-leaf");
|
||||
workflow = ImmutableListWorkflow.builder()
|
||||
.id(uri)
|
||||
.chain(Ovs.CreateOvsdbDevice.class.getName())
|
||||
.chain(Ovs.UpdateOvsVersion.class.getName())
|
||||
.chain(Ovs.UpdateUnderlayBridgeId.class.getName())
|
||||
.chain(Ovs.CreateUnderlayBridge.class.getName())
|
||||
.chain(Ovs.AddPhysicalPortsOnUnderlayBridge.class.getName())
|
||||
.build();
|
||||
workflowStore.register(workflow);
|
||||
uri = URI.create("of-overlay.clean-workflow-nova-waitAll-Bridge-Del");
|
||||
workflow = ImmutableListWorkflow.builder()
|
||||
.id(uri)
|
||||
//.attribute(WorkflowAttribute.REMOVE_AFTER_COMPLETE)
|
||||
.chain(Ovs.DeleteOverlayBridgeConfig.class.getName())
|
||||
.chain(Ovs.DeleteUnderlayBridgeConfig.class.getName())
|
||||
.chain(Ovs.RemoveBridgeOfDevice.class.getName())
|
||||
.chain(Ovs.RemoveOvsdbDevice.class.getName())
|
||||
.build();
|
||||
workflowStore.register(workflow);
|
||||
|
||||
uri = URI.create("of-overlay.workflow-ovs-spine");
|
||||
workflow = ImmutableListWorkflow.builder()
|
||||
.id(uri)
|
||||
.chain(Ovs.CreateOvsdbDevice.class.getName())
|
||||
.chain(Ovs.UpdateOvsVersion.class.getName())
|
||||
.chain(Ovs.UpdateUnderlayBridgeId.class.getName())
|
||||
.chain(Ovs.CreateUnderlayBridge.class.getName())
|
||||
.chain(Ovs.AddPhysicalPortsOnUnderlayBridge.class.getName())
|
||||
.build();
|
||||
workflowStore.register(workflow);
|
||||
uri = URI.create("of-overlay.workflow-ovs-leaf");
|
||||
workflow = ImmutableListWorkflow.builder()
|
||||
.id(uri)
|
||||
.chain(Ovs.CreateOvsdbDevice.class.getName())
|
||||
.chain(Ovs.UpdateOvsVersion.class.getName())
|
||||
.chain(Ovs.UpdateUnderlayBridgeId.class.getName())
|
||||
.chain(Ovs.CreateUnderlayBridge.class.getName())
|
||||
.chain(Ovs.AddPhysicalPortsOnUnderlayBridge.class.getName())
|
||||
.build();
|
||||
workflowStore.register(workflow);
|
||||
|
||||
deviceService.addListener(
|
||||
event -> {
|
||||
// trigger EventTask for DeviceEvent
|
||||
eventMapTriggerExecutor.submit(
|
||||
() -> workflowExecutionService.eventMapTrigger(
|
||||
event,
|
||||
// event hint supplier
|
||||
(ev) -> {
|
||||
if (ev == null || ev.subject() == null) {
|
||||
return null;
|
||||
uri = URI.create("of-overlay.workflow-ovs-spine");
|
||||
workflow = ImmutableListWorkflow.builder()
|
||||
.id(uri)
|
||||
.chain(Ovs.CreateOvsdbDevice.class.getName())
|
||||
.chain(Ovs.UpdateOvsVersion.class.getName())
|
||||
.chain(Ovs.UpdateUnderlayBridgeId.class.getName())
|
||||
.chain(Ovs.CreateUnderlayBridge.class.getName())
|
||||
.chain(Ovs.AddPhysicalPortsOnUnderlayBridge.class.getName())
|
||||
.build();
|
||||
workflowStore.register(workflow);
|
||||
|
||||
deviceService.addListener(
|
||||
event -> {
|
||||
// trigger EventTask for DeviceEvent
|
||||
eventMapTriggerExecutor.submit(
|
||||
() -> workflowExecutionService.eventMapTrigger(
|
||||
event,
|
||||
// event hint supplier
|
||||
(ev) -> {
|
||||
if (ev == null || ev.subject() == null) {
|
||||
return null;
|
||||
}
|
||||
String hint = event.subject().id().toString();
|
||||
log.debug("hint: {}", hint);
|
||||
return hint;
|
||||
}
|
||||
String hint = event.subject().id().toString();
|
||||
log.debug("hint: {}", hint);
|
||||
return hint;
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
);
|
||||
)
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
} catch (WorkflowException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -59,6 +59,7 @@ import org.onosproject.workflow.api.AbstractWorklet;
|
||||
import org.onosproject.workflow.api.JsonDataModel;
|
||||
import org.onosproject.workflow.api.WorkflowContext;
|
||||
import org.onosproject.workflow.api.WorkflowException;
|
||||
import org.onosproject.workflow.api.StaticDataModel;
|
||||
import org.onosproject.workflow.model.accessinfo.SshAccessInfo;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@ -83,6 +84,7 @@ public final class Ovs {
|
||||
private static final Logger log = LoggerFactory.getLogger(Ovs.class);
|
||||
|
||||
private static final String MODEL_MGMT_IP = "/mgmtIp";
|
||||
private static final String BRIDGE_NAME = "/bridgeName";
|
||||
private static final String MODEL_OVSDB_PORT = "/ovsdbPort";
|
||||
private static final String MODEL_OVS_VERSION = "/ovsVersion";
|
||||
private static final String MODEL_OVS_DATAPATH_TYPE = "/ovsDatapathType";
|
||||
@ -535,6 +537,108 @@ public final class Ovs {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class CreateBridge extends AbstractWorklet {
|
||||
|
||||
@StaticDataModel(path = BRIDGE_NAME)
|
||||
String bridgeName;
|
||||
|
||||
@JsonDataModel(path = MODEL_MGMT_IP)
|
||||
String strMgmtIp;
|
||||
|
||||
@JsonDataModel(path = MODEL_OVSDB_PORT)
|
||||
Integer intOvsdbPort;
|
||||
|
||||
@JsonDataModel(path = MODEL_OVS_DATAPATH_TYPE)
|
||||
String strOvsDatapath;
|
||||
|
||||
@JsonDataModel(path = MODEL_OF_DEVID_OVERLAY_BRIDGE, optional = true)
|
||||
String strOfDevId;
|
||||
|
||||
@Override
|
||||
public boolean isNext(WorkflowContext context) throws WorkflowException {
|
||||
|
||||
check(strOfDevId != null, "invalid strOfDevIdUnderlay");
|
||||
return !OvsUtil.isAvailableBridge(context, DeviceId.deviceId(strOfDevId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void process(WorkflowContext context) throws WorkflowException {
|
||||
|
||||
check(strOfDevId != null, "invalid strOfDevIdOverlay");
|
||||
BridgeConfig bridgeConfig = OvsUtil.getOvsdbBehaviour(context, strMgmtIp, BridgeConfig.class);
|
||||
List<ControllerInfo> ofControllers = OvsUtil.getOpenflowControllerInfoList(context);
|
||||
DeviceId ofDeviceId = DeviceId.deviceId(strOfDevId);
|
||||
|
||||
if (ofControllers == null || ofControllers.size() == 0) {
|
||||
throw new WorkflowException("Invalid of controllers");
|
||||
}
|
||||
|
||||
Optional<BridgeDescription> optBd = OvsUtil.getBridgeDescription(bridgeConfig, bridgeName);
|
||||
if (!optBd.isPresent()) {
|
||||
|
||||
// If bridge does not exist, just creates a new bridge.
|
||||
context.waitCompletion(DeviceEvent.class, ofDeviceId.toString(),
|
||||
() -> OvsUtil.createBridge(bridgeConfig,
|
||||
bridgeName,
|
||||
OvsUtil.bridgeDatapathId(ofDeviceId),
|
||||
ofControllers,
|
||||
OvsUtil.buildOvsDatapathType(strOvsDatapath)),
|
||||
TIMEOUT_DEVICE_CREATION_MS
|
||||
);
|
||||
return;
|
||||
|
||||
} else {
|
||||
BridgeDescription bd = optBd.get();
|
||||
if (OvsUtil.isEqual(ofControllers, bd.controllers())) {
|
||||
log.error("{} has valid controller setting({})", bridgeName, bd.controllers());
|
||||
context.completed();
|
||||
return;
|
||||
}
|
||||
|
||||
OvsdbClientService ovsdbClient = OvsUtil.getOvsdbClient(context, strMgmtIp, intOvsdbPort);
|
||||
if (ovsdbClient == null || !ovsdbClient.isConnected()) {
|
||||
throw new WorkflowException("Invalid ovsdb client for " + strMgmtIp);
|
||||
}
|
||||
|
||||
// If controller settings are not matched, set controller with valid controller information.
|
||||
context.waitCompletion(DeviceEvent.class, ofDeviceId.toString(),
|
||||
() -> ovsdbClient.setControllersWithDeviceId(bd.deviceId().get(), ofControllers),
|
||||
TIMEOUT_DEVICE_CREATION_MS
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCompleted(WorkflowContext context, Event event)throws WorkflowException {
|
||||
if (!(event instanceof DeviceEvent)) {
|
||||
return false;
|
||||
}
|
||||
DeviceEvent deviceEvent = (DeviceEvent) event;
|
||||
Device device = deviceEvent.subject();
|
||||
switch (deviceEvent.type()) {
|
||||
case DEVICE_ADDED:
|
||||
case DEVICE_AVAILABILITY_CHANGED:
|
||||
case DEVICE_UPDATED:
|
||||
return context.getService(DeviceService.class).isAvailable(device.id());
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void timeout(WorkflowContext context) throws WorkflowException {
|
||||
if (!isNext(context)) {
|
||||
context.completed(); //Complete the job of worklet by timeout
|
||||
} else {
|
||||
super.timeout(context);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Work-let class for creating overlay openflow bridge.
|
||||
*/
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user