Sho SHIMIZU
Committed by Ray Milkey

Add constraint for link annotated value

Change-Id: Ia51e488de1ae885da02493f09156afbd52c53592
1 +/*
2 + * Copyright 2014 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 + */
16 +package org.onlab.onos.net.intent.constraint;
17 +
18 +import com.google.common.base.MoreObjects;
19 +import org.onlab.onos.net.Link;
20 +import org.onlab.onos.net.resource.LinkResourceService;
21 +
22 +import java.util.Objects;
23 +
24 +/**
25 + * Constraint that evaluates an arbitrary link annotated value is under the specified threshold.
26 + */
27 +public class AnnotationConstraint extends BooleanConstraint {
28 +
29 + private final String key;
30 + private final double threshold;
31 +
32 + /**
33 + * Creates a new constraint to keep the value for the specified key
34 + * of link annotation under the threshold.
35 + *
36 + * @param key key of link annotation
37 + * @param threshold threshold value of the specified link annotation
38 + */
39 + public AnnotationConstraint(String key, double threshold) {
40 + this.key = key;
41 + this.threshold = threshold;
42 + }
43 +
44 + /**
45 + * Returns the key of link annotation this constraint designates.
46 + * @return key of link annotation
47 + */
48 + public String key() {
49 + return key;
50 + }
51 +
52 + /**
53 + * Returns the threshold this constraint ensures as link annotated value.
54 + *
55 + * @return threshold as link annotated value
56 + */
57 + public double threshold() {
58 + return threshold;
59 + }
60 +
61 + @Override
62 + public boolean isValid(Link link, LinkResourceService resourceService) {
63 + double value = getAnnotatedValue(link, key);
64 +
65 + return value <= threshold;
66 + }
67 +
68 + /**
69 + * Returns the annotated value of the specified link. The annotated value
70 + * is expected to be String that can be parsed as double. If parsing fails,
71 + * the returned value will be 1.0.
72 + *
73 + * @param link link whose annotated value is obtained
74 + * @param key key of link annotation
75 + * @return double value of link annotation for the specified key
76 + */
77 + private double getAnnotatedValue(Link link, String key) {
78 + double value;
79 + try {
80 + value = Double.parseDouble(link.annotations().value(key));
81 + } catch (NumberFormatException e) {
82 + value = 1.0;
83 + }
84 + return value;
85 + }
86 +
87 + @Override
88 + public double cost(Link link, LinkResourceService resourceService) {
89 + if (isValid(link, resourceService)) {
90 + return getAnnotatedValue(link, key);
91 + } else {
92 + return -1;
93 + }
94 + }
95 +
96 + @Override
97 + public int hashCode() {
98 + return Objects.hash(key, threshold);
99 + }
100 +
101 + @Override
102 + public boolean equals(Object obj) {
103 + if (this == obj) {
104 + return true;
105 + }
106 +
107 + if (!(obj instanceof AnnotationConstraint)) {
108 + return false;
109 + }
110 +
111 + final AnnotationConstraint other = (AnnotationConstraint) obj;
112 + return Objects.equals(this.key, other.key) && Objects.equals(this.threshold, other.threshold);
113 + }
114 +
115 + @Override
116 + public String toString() {
117 + return MoreObjects.toStringHelper(this)
118 + .add("key", key)
119 + .add("threshold", threshold)
120 + .toString();
121 + }
122 +}
1 +/*
2 + * Copyright 2014 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 + */
16 +package org.onlab.onos.net.intent.constraint;
17 +
18 +import com.google.common.testing.EqualsTester;
19 +import org.junit.Before;
20 +import org.junit.Test;
21 +import org.onlab.onos.net.DefaultAnnotations;
22 +import org.onlab.onos.net.DefaultLink;
23 +import org.onlab.onos.net.DeviceId;
24 +import org.onlab.onos.net.Link;
25 +import org.onlab.onos.net.PortNumber;
26 +import org.onlab.onos.net.provider.ProviderId;
27 +import org.onlab.onos.net.resource.LinkResourceService;
28 +
29 +import static org.easymock.EasyMock.createMock;
30 +import static org.hamcrest.Matchers.closeTo;
31 +import static org.hamcrest.Matchers.is;
32 +import static org.hamcrest.Matchers.lessThan;
33 +import static org.junit.Assert.assertThat;
34 +import static org.onlab.onos.net.DefaultLinkTest.cp;
35 +import static org.onlab.onos.net.DeviceId.deviceId;
36 +import static org.onlab.onos.net.Link.Type.DIRECT;
37 +import static org.onlab.onos.net.PortNumber.portNumber;
38 +
39 +/**
40 + * Test for link annotated value threshold.
41 + */
42 +public class AnnotationConstraintTest {
43 +
44 + private static final ProviderId PID = new ProviderId("of", "foo");
45 + private static final DeviceId DID1 = deviceId("of:1");
46 + private static final DeviceId DID2 = deviceId("of:2");
47 + private static final PortNumber PID1 = portNumber(1);
48 + private static final PortNumber PID2 = portNumber(2);
49 + private static final String KEY = "distance";
50 + private static final double VALUE = 100;
51 +
52 + private AnnotationConstraint sut;
53 + private Link link;
54 + private LinkResourceService linkResourceService;
55 +
56 + @Before
57 + public void setUp() {
58 + linkResourceService = createMock(LinkResourceService.class);
59 +
60 + DefaultAnnotations annotations = DefaultAnnotations.builder().set(KEY, String.valueOf(VALUE)).build();
61 +
62 + link = new DefaultLink(PID, cp(DID1, PID1), cp(DID2, PID2), DIRECT, annotations);
63 + }
64 +
65 + /**
66 + * Tests the specified annotated value is less than the threshold.
67 + */
68 + @Test
69 + public void testLessThanThreshold() {
70 + double value = 120;
71 + sut = new AnnotationConstraint(KEY, value);
72 +
73 + assertThat(sut.isValid(link, linkResourceService), is(true));
74 + assertThat(sut.cost(link, linkResourceService), is(closeTo(VALUE, 1.0e-6)));
75 + }
76 +
77 + /**
78 + * Tests the specified annotated value is more than the threshold.
79 + */
80 + @Test
81 + public void testMoreThanThreshold() {
82 + double value = 80;
83 + sut = new AnnotationConstraint(KEY, value);
84 +
85 + assertThat(sut.isValid(link, linkResourceService), is(false));
86 + assertThat(sut.cost(link, linkResourceService), is(lessThan(0.0)));
87 + }
88 +
89 + @Test
90 + public void testEquality() {
91 + new EqualsTester()
92 + .addEqualityGroup(new AnnotationConstraint(KEY, 100), new AnnotationConstraint(KEY, 100))
93 + .addEqualityGroup(new AnnotationConstraint(KEY, 120))
94 + .addEqualityGroup(new AnnotationConstraint("latency", 100))
95 + .testEquals();
96 + }
97 +}