Thomas Vachuska

Introducing concept of a physical or logical region to facilitate

support of geographically distributed cluster and to lay ground
for multiple/filtered topology layouts.

Added implementation of manager and store; unit-tests included.

Change-Id: Ia01673a0b711b8785c0ea68768552c2f61d7ea6d
Showing 22 changed files with 1678 additions and 83 deletions
...@@ -15,14 +15,19 @@ ...@@ -15,14 +15,19 @@
15 */ 15 */
16 package org.onosproject.cluster; 16 package org.onosproject.cluster;
17 17
18 -import java.util.Objects; 18 +import org.onlab.util.Identifier;
19 19
20 /** 20 /**
21 * Controller cluster identity. 21 * Controller cluster identity.
22 */ 22 */
23 -public class NodeId implements Comparable<NodeId> { 23 +public final class NodeId extends Identifier<String> implements Comparable<NodeId> {
24 24
25 - private final String id; 25 + /**
26 + * Constructor for serialization.
27 + */
28 + private NodeId() {
29 + super("");
30 + }
26 31
27 /** 32 /**
28 * Creates a new cluster node identifier from the specified string. 33 * Creates a new cluster node identifier from the specified string.
...@@ -30,34 +35,22 @@ public class NodeId implements Comparable<NodeId> { ...@@ -30,34 +35,22 @@ public class NodeId implements Comparable<NodeId> {
30 * @param id string identifier 35 * @param id string identifier
31 */ 36 */
32 public NodeId(String id) { 37 public NodeId(String id) {
33 - this.id = id; 38 + super(id);
34 } 39 }
35 40
36 - @Override 41 + /**
37 - public int hashCode() { 42 + * Creates a new cluster node identifier from the specified string.
38 - return id.hashCode(); 43 + *
39 - } 44 + * @param id string identifier
40 - 45 + * @return node id
41 - @Override 46 + */
42 - public boolean equals(Object obj) { 47 + public static NodeId nodeId(String id) {
43 - if (this == obj) { 48 + return new NodeId(id);
44 - return true;
45 - }
46 - if (obj instanceof NodeId) {
47 - final NodeId other = (NodeId) obj;
48 - return Objects.equals(this.id, other.id);
49 - }
50 - return false;
51 - }
52 -
53 - @Override
54 - public String toString() {
55 - return id;
56 } 49 }
57 50
58 @Override 51 @Override
59 public int compareTo(NodeId that) { 52 public int compareTo(NodeId that) {
60 - return this.id.compareTo(that.id); 53 + return identifier.compareTo(that.identifier);
61 } 54 }
62 55
63 } 56 }
......
...@@ -16,21 +16,18 @@ ...@@ -16,21 +16,18 @@
16 16
17 package org.onosproject.net.key; 17 package org.onosproject.net.key;
18 18
19 -import java.util.Objects; 19 +import org.onlab.util.Identifier;
20 -
21 -import static com.google.common.base.Preconditions.checkNotNull;
22 20
23 /** 21 /**
24 - * Device key Id definition. 22 + * Device key identifier backed by a string value.
25 */ 23 */
26 -public final class DeviceKeyId { 24 +public final class DeviceKeyId extends Identifier<String> {
27 - private final String identifier;
28 25
29 /** 26 /**
30 * Constructor for serialization. 27 * Constructor for serialization.
31 */ 28 */
32 private DeviceKeyId() { 29 private DeviceKeyId() {
33 - this.identifier = null; 30 + super();
34 } 31 }
35 32
36 /** 33 /**
...@@ -39,63 +36,17 @@ public final class DeviceKeyId { ...@@ -39,63 +36,17 @@ public final class DeviceKeyId {
39 * @param value the underlying value of this ID 36 * @param value the underlying value of this ID
40 */ 37 */
41 private DeviceKeyId(String value) { 38 private DeviceKeyId(String value) {
42 - this.identifier = checkNotNull(value, "Device Key Id cannot be null."); 39 + super(value);
43 } 40 }
44 41
45 /** 42 /**
46 - * Static method to construct a device key identifier. 43 + * Creates a new device key identifier.
47 * 44 *
48 - * @param id for the device key identifier 45 + * @param id backing identifier value
49 * @return device key identifier 46 * @return device key identifier
50 */ 47 */
51 - public static final DeviceKeyId deviceKeyId(String id) { 48 + public static DeviceKeyId deviceKeyId(String id) {
52 return new DeviceKeyId(id); 49 return new DeviceKeyId(id);
53 } 50 }
54 51
55 - /**
56 - * Returns the identifier of the device key identifier.
57 - *
58 - * @return identifier
59 - */
60 - public String id() {
61 - return identifier;
62 - }
63 -
64 - /**
65 - * Returns the hashcode of the identifier.
66 - *
67 - * @return hashcode
68 - */
69 - @Override
70 - public int hashCode() {
71 - return identifier.hashCode();
72 - }
73 -
74 - /**
75 - * Compares two device key identifiers for equality.
76 - *
77 - * @param obj to compare against
78 - * @return true if the objects are equal, false otherwise.
79 - */
80 - @Override
81 - public boolean equals(Object obj) {
82 - if (this == obj) {
83 - return true;
84 - }
85 - if (obj instanceof DeviceKeyId) {
86 - final DeviceKeyId that = (DeviceKeyId) obj;
87 - return this.getClass() == that.getClass() &&
88 - Objects.equals(this.identifier, that.identifier);
89 - }
90 - return false;
91 - }
92 -
93 - /**
94 - * Returns a string representation of a DeviceKeyId.
95 - *
96 - * @return string
97 - */
98 - public String toString() {
99 - return identifier;
100 - }
101 } 52 }
......
1 +/*
2 + * Copyright 2016 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 +
17 +package org.onosproject.net.region;
18 +
19 +import com.google.common.base.MoreObjects;
20 +import com.google.common.collect.ImmutableList;
21 +import org.onosproject.cluster.NodeId;
22 +
23 +import java.util.List;
24 +import java.util.Objects;
25 +import java.util.Set;
26 +
27 +/**
28 + * Default implementation of a region.
29 + */
30 +public final class DefaultRegion implements Region {
31 +
32 + private final RegionId id;
33 + private final String name;
34 + private final Type type;
35 + private final List<Set<NodeId>> masters;
36 +
37 + /**
38 + * Creates a region using the supplied information.
39 + *
40 + * @param id region identifier
41 + * @param name friendly name
42 + * @param type region type
43 + * @param masters list of sets of cluster node identifiers; in order of mastership
44 + */
45 + public DefaultRegion(RegionId id, String name, Type type, List<Set<NodeId>> masters) {
46 + this.id = id;
47 + this.name = name;
48 + this.type = type;
49 + this.masters = masters != null ? ImmutableList.copyOf(masters) : ImmutableList.of();
50 + }
51 +
52 + @Override
53 + public RegionId id() {
54 + return id;
55 + }
56 +
57 + @Override
58 + public String name() {
59 + return name;
60 + }
61 +
62 + @Override
63 + public Type type() {
64 + return type;
65 + }
66 +
67 + @Override
68 + public List<Set<NodeId>> masters() {
69 + return masters;
70 + }
71 +
72 + @Override
73 + public int hashCode() {
74 + return Objects.hash(id, name, type, masters);
75 + }
76 +
77 + @Override
78 + public boolean equals(Object obj) {
79 + if (this == obj) {
80 + return true;
81 + }
82 + if (obj instanceof DefaultRegion) {
83 + final DefaultRegion that = (DefaultRegion) obj;
84 + return Objects.equals(this.id, that.id)
85 + && Objects.equals(this.name, that.name)
86 + && Objects.equals(this.type, that.type)
87 + && Objects.equals(this.masters, that.masters);
88 + }
89 + return false;
90 + }
91 +
92 + @Override
93 + public String toString() {
94 + return MoreObjects.toStringHelper(this)
95 + .add("id", id)
96 + .add("name", name)
97 + .add("type", type)
98 + .add("masters", masters)
99 + .toString();
100 + }
101 +
102 +}
1 +/*
2 + * Copyright 2016 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 +
17 +package org.onosproject.net.region;
18 +
19 +import org.onosproject.cluster.NodeId;
20 +
21 +import java.util.List;
22 +import java.util.Set;
23 +
24 +/**
25 + * Representation of a group of devices located in a common physical or
26 + * logical region. Optionally, devices in the region can share the same
27 + * cluster nodes mastership affinities.
28 + */
29 +public interface Region {
30 +
31 + /**
32 + * Coarse representation of the type of the region.
33 + */
34 + enum Type {
35 + /**
36 + * Region represents an entire continent.
37 + */
38 + CONTINENT,
39 +
40 + /**
41 + * Region represents an entire country.
42 + */
43 + COUNTRY,
44 +
45 + /**
46 + * Region represents a metropolitan area.
47 + */
48 + METRO,
49 +
50 + /**
51 + * Region represents a campus.
52 + */
53 + CAMPUS,
54 +
55 + /**
56 + * Region represents a building.
57 + */
58 + BUILDING,
59 +
60 + /**
61 + * Region represents a building floor.
62 + */
63 + FLOOR,
64 +
65 + /**
66 + * Region represents a room.
67 + */
68 + ROOM,
69 +
70 + /**
71 + * Region represents a rack.
72 + */
73 + RACK,
74 +
75 + /**
76 + * Region represents a logical grouping.
77 + */
78 + LOGICAL_GROUP
79 + }
80 +
81 + /**
82 + * Returns the unique identifier of the region.
83 + *
84 + * @return region identifier
85 + */
86 + RegionId id();
87 +
88 + /**
89 + * Returns the friendly region name that can be used for display purposes.
90 + *
91 + * @return friendly name of the region
92 + */
93 + String name();
94 +
95 + /**
96 + * Returns the region type.
97 + *
98 + * @return region type
99 + */
100 + Type type();
101 +
102 + /**
103 + * Returns the list of master node sets. The sets of cluster node identifiers
104 + * should be listed in the order of preferred mastership. Nodes specified
105 + * in each sets should be considered with equally priority and devices in
106 + * the region can be balanced between them based on other criteria, e.g. load.
107 + *
108 + * @return list of preferred master node sets
109 + */
110 + List<Set<NodeId>> masters();
111 +
112 +}
1 +/*
2 + * Copyright 2016 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 +
17 +package org.onosproject.net.region;
18 +
19 +import org.onosproject.cluster.NodeId;
20 +import org.onosproject.net.DeviceId;
21 +
22 +import java.util.Collection;
23 +import java.util.List;
24 +import java.util.Set;
25 +
26 +/**
27 + * Service for interacting with inventory of network control regions.
28 + */
29 +public interface RegionAdminService extends RegionService {
30 +
31 + /**
32 + * Creates a new region using the supplied data.
33 + *
34 + * @param regionId region identifier
35 + * @param name friendly name
36 + * @param type region type
37 + * @param masterNodeIds list of sets of master nodes; null implies empty list
38 + * @return new region descriptor
39 + * @throws IllegalArgumentException if region already exists
40 + */
41 + Region createRegion(RegionId regionId, String name, Region.Type type,
42 + List<Set<NodeId>> masterNodeIds);
43 +
44 + /**
45 + * Update the specified region using the new set of data.
46 + *
47 + * @param regionId region identifier
48 + * @param name friendly name
49 + * @param type region type
50 + * @param masterNodeIds list of sets of master nodes; null implies empty list
51 + * @return new region descriptor
52 + */
53 + Region updateRegion(RegionId regionId, String name, Region.Type type,
54 + List<Set<NodeId>> masterNodeIds);
55 +
56 + /**
57 + * Removes the specified region using the new set of data.
58 + *
59 + * @param regionId region identifier
60 + */
61 + void removeRegion(RegionId regionId);
62 +
63 + /**
64 + * Adds the specified collection of devices to the region.
65 + *
66 + * @param regionId region identifier
67 + * @param deviceIds list of device identifiers
68 + */
69 + void addDevices(RegionId regionId, Collection<DeviceId> deviceIds);
70 +
71 + /**
72 + * Removes the specified collection of devices from the region.
73 + *
74 + * @param regionId region identifier
75 + * @param deviceIds list of device identifiers
76 + */
77 + void removeDevices(RegionId regionId, Collection<DeviceId> deviceIds);
78 +
79 +}
1 +/*
2 + * Copyright 2016 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 +
17 +package org.onosproject.net.region;
18 +
19 +import com.google.common.collect.ImmutableSet;
20 +import org.onosproject.event.AbstractEvent;
21 +import org.onosproject.net.DeviceId;
22 +
23 +import java.util.Set;
24 +
25 +/**
26 + * Describes region event.
27 + */
28 +public class RegionEvent extends AbstractEvent<RegionEvent.Type, Region> {
29 +
30 + private final Set<DeviceId> deviceIds;
31 +
32 + public enum Type {
33 + /**
34 + * Signifies that a new region was created.
35 + */
36 + REGION_ADDED,
37 +
38 + /**
39 + * Signifies that a region was updated.
40 + */
41 + REGION_REMOVED,
42 +
43 + /**
44 + * Signifies that a region was removed.
45 + */
46 + REGION_UPDATED,
47 +
48 + /**
49 + * Signifies that a region device membership has changed.
50 + */
51 + REGION_MEMBERSHIP_CHANGED
52 + }
53 +
54 + /**
55 + * Creates an event of a given type and for the specified region and the
56 + * current time.
57 + *
58 + * @param type device event type
59 + * @param region event region subject
60 + */
61 + public RegionEvent(Type type, Region region) {
62 + this(type, region, null);
63 + }
64 +
65 + /**
66 + * Creates an event of a given type and for the specified region, device
67 + * id list and the current time.
68 + *
69 + * @param type device event type
70 + * @param region event region subject
71 + * @param deviceIds optional set of device ids
72 + */
73 + public RegionEvent(Type type, Region region, Set<DeviceId> deviceIds) {
74 + super(type, region);
75 + this.deviceIds = deviceIds != null ? ImmutableSet.copyOf(deviceIds) : ImmutableSet.of();
76 + }
77 +
78 + /**
79 + * Creates an event of a given type and for the specified device and time.
80 + *
81 + * @param type device event type
82 + * @param region event region subject
83 + * @param deviceIds optional set of device ids
84 + * @param time occurrence time
85 + */
86 + public RegionEvent(Type type, Region region, Set<DeviceId> deviceIds, long time) {
87 + super(type, region, time);
88 + this.deviceIds = deviceIds != null ? ImmutableSet.copyOf(deviceIds) : ImmutableSet.of();
89 + }
90 +
91 +}
1 +/*
2 + * Copyright 2016 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 +
17 +package org.onosproject.net.region;
18 +
19 +import org.onlab.util.Identifier;
20 +
21 +/**
22 + * Region identifier backed by a string value.
23 + */
24 +public final class RegionId extends Identifier<String> {
25 +
26 + /**
27 + * Constructor for serialization.
28 + */
29 + private RegionId() {
30 + super();
31 + }
32 +
33 + /**
34 + * Constructs the ID corresponding to a given string value.
35 + *
36 + * @param value the underlying value of this ID
37 + */
38 + private RegionId(String value) {
39 + super(value);
40 + }
41 +
42 + /**
43 + * Creates a new region identifier.
44 + *
45 + * @param id backing identifier value
46 + * @return region identifier
47 + */
48 + public static RegionId regionId(String id) {
49 + return new RegionId(id);
50 + }
51 +
52 +}
1 +/*
2 + * Copyright 2016 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.onosproject.net.region;
17 +
18 +import org.onosproject.event.EventListener;
19 +
20 +/**
21 + * Entity capable of receiving region related events.
22 + */
23 +public interface RegionListener extends EventListener<RegionEvent> {
24 +}
1 +/*
2 + * Copyright 2016 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 +
17 +package org.onosproject.net.region;
18 +
19 +import org.onosproject.net.DeviceId;
20 +
21 +import java.util.Set;
22 +
23 +/**
24 + * Service for interacting with inventory of network control regions.
25 + */
26 +public interface RegionService {
27 +
28 + /**
29 + * Returns set of all regions.
30 + *
31 + * @return set of regions
32 + */
33 + Set<Region> getRegions();
34 +
35 + /**
36 + * Returns the region with the specified identifier.
37 + *
38 + * @param regionId region identifier
39 + * @return region
40 + * @throws org.onlab.util.ItemNotFoundException if region with given
41 + * id does not exist
42 + */
43 + Region getRegion(RegionId regionId);
44 +
45 + /**
46 + * Returns the region to which the specified device belongs.
47 + *
48 + * @param deviceId device identifier
49 + * @return region or null if device does not belong to any region
50 + */
51 + Region getRegionForDevice(DeviceId deviceId);
52 +
53 + /**
54 + * Returns the set of devices that belong to the specified region.
55 + *
56 + * @param regionId region identifier
57 + * @return set of identifiers for devices in the given region
58 + */
59 + Set<DeviceId> getRegionDevices(RegionId regionId);
60 +
61 +}
1 +/*
2 + * Copyright 2016 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.onosproject.net.region;
17 +
18 +import org.onosproject.cluster.NodeId;
19 +import org.onosproject.net.DeviceId;
20 +import org.onosproject.store.Store;
21 +
22 +import java.util.Collection;
23 +import java.util.List;
24 +import java.util.Set;
25 +
26 +/**
27 + * Manages inventory of regions of devices; not intended for direct use.
28 + */
29 +public interface RegionStore extends Store<RegionEvent, RegionStoreDelegate> {
30 +
31 + /**
32 + * Returns set of all regions.
33 + *
34 + * @return set of regions
35 + */
36 + Set<Region> getRegions();
37 +
38 + /**
39 + * Returns the region with the specified identifier.
40 + *
41 + * @param regionId region identifier
42 + * @return region
43 + * @throws org.onlab.util.ItemNotFoundException if region with given
44 + * id does not exist
45 + */
46 + Region getRegion(RegionId regionId);
47 +
48 + /**
49 + * Returns the region to which the specified device belongs.
50 + *
51 + * @param deviceId device identifier
52 + * @return region or null if device does not belong to any region
53 + */
54 + Region getRegionForDevice(DeviceId deviceId);
55 +
56 + /**
57 + * Returns the set of devices that belong to the specified region.
58 + *
59 + * @param regionId region identifier
60 + * @return set of identifiers for devices in the given region
61 + */
62 + Set<DeviceId> getRegionDevices(RegionId regionId);
63 +
64 + /**
65 + * Creates a new region using the supplied data.
66 + *
67 + * @param regionId region identifier
68 + * @param name friendly name
69 + * @param type region type
70 + * @param masterNodeIds list of master nodes; null implies empty list
71 + * @return new region descriptor
72 + * @throws IllegalArgumentException if item already exists
73 + */
74 + Region createRegion(RegionId regionId, String name, Region.Type type,
75 + List<Set<NodeId>> masterNodeIds);
76 +
77 + /**
78 + * Updates the specified new region using the supplied data.
79 + *
80 + * @param regionId region identifier
81 + * @param name friendly name
82 + * @param type region type
83 + * @param masterNodeIds list of master nodes; null implies empty list
84 + * @return new region descriptor
85 + * @throws IllegalArgumentException if item already exists
86 + */
87 + Region updateRegion(RegionId regionId, String name, Region.Type type,
88 + List<Set<NodeId>> masterNodeIds);
89 +
90 + /**
91 + * Removes the specified region using the new set of data.
92 + *
93 + * @param regionId region identifier
94 + */
95 + void removeRegion(RegionId regionId);
96 +
97 + /**
98 + * Adds the specified collection of devices to the region.
99 + *
100 + * @param regionId region identifier
101 + * @param deviceIds list of device identifiers
102 + */
103 + void addDevices(RegionId regionId, Collection<DeviceId> deviceIds);
104 +
105 + /**
106 + * Removes the specified collection of devices from the region.
107 + *
108 + * @param regionId region identifier
109 + * @param deviceIds list of device identifiers
110 + */
111 + void removeDevices(RegionId regionId, Collection<DeviceId> deviceIds);
112 +
113 +}
1 +/*
2 + * Copyright 2016 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.onosproject.net.region;
17 +
18 +import org.onosproject.store.StoreDelegate;
19 +
20 +/**
21 + * Region store delegate abstraction.
22 + */
23 +public interface RegionStoreDelegate extends StoreDelegate<RegionEvent> {
24 +}
1 +/*
2 + * Copyright 2016 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 +
17 +/**
18 + * Subsystem for tracking inventory of network control regions.
19 + */
20 +package org.onosproject.net.region;
...\ No newline at end of file ...\ No newline at end of file
1 +/*
2 + * Copyright 2014-2016 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 +
17 +package org.onosproject.net.region;
18 +
19 +import com.google.common.collect.ImmutableList;
20 +import com.google.common.collect.ImmutableSet;
21 +import com.google.common.testing.EqualsTester;
22 +import org.junit.Test;
23 +import org.onosproject.cluster.NodeId;
24 +
25 +import java.util.Set;
26 +
27 +import static org.junit.Assert.assertEquals;
28 +import static org.onosproject.cluster.NodeId.nodeId;
29 +import static org.onosproject.net.region.Region.Type.METRO;
30 +
31 +/**
32 + * Suite of tests of the default region implementation.
33 + */
34 +public class DefaultRegionTest {
35 +
36 + private static final RegionId ID1 = RegionId.regionId("r1");
37 +
38 + @Test
39 + public void basics() {
40 + ImmutableList<Set<NodeId>> masters = ImmutableList
41 + .of(ImmutableSet.of(nodeId("n1"), nodeId("n2")),
42 + ImmutableSet.of(nodeId("n3"), nodeId("n4")));
43 + Region r = new DefaultRegion(ID1, "R1", METRO, masters);
44 + assertEquals("incorrect id", ID1, r.id());
45 + assertEquals("incorrect name", "R1", r.name());
46 + assertEquals("incorrect type", METRO, r.type());
47 + assertEquals("incorrect masters", masters, r.masters());
48 + }
49 +
50 + @Test
51 + public void equality() {
52 + Region a = new DefaultRegion(ID1, "R1", METRO, null);
53 + Region b = new DefaultRegion(ID1, "R1", METRO, null);
54 + Region c = new DefaultRegion(ID1, "R2", METRO, null);
55 +
56 + new EqualsTester().addEqualityGroup(a, b).addEqualityGroup(c).testEquals();
57 + }
58 +
59 +}
...\ No newline at end of file ...\ No newline at end of file
1 +/*
2 + * Copyright 2016 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 +
17 +package org.onosproject.net.region.impl;
18 +
19 +import org.apache.felix.scr.annotations.Activate;
20 +import org.apache.felix.scr.annotations.Deactivate;
21 +import org.apache.felix.scr.annotations.Reference;
22 +import org.apache.felix.scr.annotations.ReferenceCardinality;
23 +import org.onosproject.cluster.NodeId;
24 +import org.onosproject.event.AbstractListenerManager;
25 +import org.onosproject.net.DeviceId;
26 +import org.onosproject.net.region.Region;
27 +import org.onosproject.net.region.RegionAdminService;
28 +import org.onosproject.net.region.RegionEvent;
29 +import org.onosproject.net.region.RegionId;
30 +import org.onosproject.net.region.RegionListener;
31 +import org.onosproject.net.region.RegionService;
32 +import org.onosproject.net.region.RegionStore;
33 +import org.onosproject.net.region.RegionStoreDelegate;
34 +import org.slf4j.Logger;
35 +
36 +import java.util.Collection;
37 +import java.util.List;
38 +import java.util.Set;
39 +
40 +import static com.google.common.base.Preconditions.checkNotNull;
41 +import static com.google.common.base.Preconditions.checkState;
42 +import static com.google.common.collect.ImmutableList.of;
43 +import static org.slf4j.LoggerFactory.getLogger;
44 +
45 +/**
46 + * Provides implementation of the region service APIs.
47 + */
48 +public class RegionManager extends AbstractListenerManager<RegionEvent, RegionListener>
49 + implements RegionAdminService, RegionService {
50 +
51 + private static final String REGION_ID_NULL = "Region ID cannot be null";
52 + private static final String REGION_TYPE_NULL = "Region type cannot be null";
53 + private static final String DEVICE_ID_NULL = "Device ID cannot be null";
54 + private static final String DEVICE_IDS_NULL = "Device IDs cannot be null";
55 + private static final String DEVICE_IDS_EMPTY = "Device IDs cannot be empty";
56 + private static final String NAME_NULL = "Name cannot be null";
57 +
58 + private final Logger log = getLogger(getClass());
59 +
60 + private RegionStoreDelegate delegate = this::post;
61 +
62 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
63 + protected RegionStore store;
64 +
65 + @Activate
66 + public void activate() {
67 + store.setDelegate(delegate);
68 + eventDispatcher.addSink(RegionEvent.class, listenerRegistry);
69 + log.info("Started");
70 + }
71 +
72 + @Deactivate
73 + public void deactivate() {
74 + store.unsetDelegate(delegate);
75 + eventDispatcher.removeSink(RegionEvent.class);
76 + log.info("Stopped");
77 + }
78 +
79 + @Override
80 + public Region createRegion(RegionId regionId, String name, Region.Type type,
81 + List<Set<NodeId>> masterNodeIds) {
82 + checkNotNull(regionId, REGION_ID_NULL);
83 + checkNotNull(name, NAME_NULL);
84 + checkNotNull(name, REGION_TYPE_NULL);
85 + return store.createRegion(regionId, name, type, masterNodeIds == null ? of() : masterNodeIds);
86 + }
87 +
88 + @Override
89 + public Region updateRegion(RegionId regionId, String name, Region.Type type,
90 + List<Set<NodeId>> masterNodeIds) {
91 + checkNotNull(regionId, REGION_ID_NULL);
92 + checkNotNull(name, NAME_NULL);
93 + checkNotNull(name, REGION_TYPE_NULL);
94 + return store.updateRegion(regionId, name, type, masterNodeIds == null ? of() : masterNodeIds);
95 + }
96 +
97 + @Override
98 + public void removeRegion(RegionId regionId) {
99 + checkNotNull(regionId, REGION_ID_NULL);
100 + store.removeRegion(regionId);
101 + }
102 +
103 + @Override
104 + public void addDevices(RegionId regionId, Collection<DeviceId> deviceIds) {
105 + checkNotNull(regionId, REGION_ID_NULL);
106 + checkNotNull(deviceIds, DEVICE_IDS_NULL);
107 + checkState(!deviceIds.isEmpty(), DEVICE_IDS_EMPTY);
108 + store.addDevices(regionId, deviceIds);
109 + }
110 +
111 + @Override
112 + public void removeDevices(RegionId regionId, Collection<DeviceId> deviceIds) {
113 + checkNotNull(regionId, REGION_ID_NULL);
114 + checkNotNull(deviceIds, DEVICE_IDS_NULL);
115 + checkState(!deviceIds.isEmpty(), DEVICE_IDS_EMPTY);
116 + store.removeDevices(regionId, deviceIds);
117 + }
118 +
119 + @Override
120 + public Set<Region> getRegions() {
121 + return store.getRegions();
122 + }
123 +
124 + @Override
125 + public Region getRegion(RegionId regionId) {
126 + checkNotNull(regionId, REGION_ID_NULL);
127 + return store.getRegion(regionId);
128 + }
129 +
130 + @Override
131 + public Region getRegionForDevice(DeviceId deviceId) {
132 + checkNotNull(deviceId, DEVICE_ID_NULL);
133 + return store.getRegionForDevice(deviceId);
134 + }
135 +
136 + @Override
137 + public Set<DeviceId> getRegionDevices(RegionId regionId) {
138 + checkNotNull(regionId, REGION_ID_NULL);
139 + return store.getRegionDevices(regionId);
140 + }
141 +
142 +}
1 +/*
2 + * Copyright 2016 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 +
17 +/**
18 + * Core subsystem for managing region definitions.
19 + */
20 +package org.onosproject.net.region.impl;
...\ No newline at end of file ...\ No newline at end of file
1 +/*
2 + * Copyright 2016 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 +
17 +package org.onosproject.net.region.impl;
18 +
19 +import com.google.common.collect.ImmutableList;
20 +import com.google.common.collect.ImmutableSet;
21 +import org.junit.After;
22 +import org.junit.Before;
23 +import org.junit.Test;
24 +import org.onlab.junit.TestUtils;
25 +import org.onlab.util.ItemNotFoundException;
26 +import org.onosproject.cluster.NodeId;
27 +import org.onosproject.common.event.impl.TestEventDispatcher;
28 +import org.onosproject.net.DeviceId;
29 +import org.onosproject.net.NetTestTools;
30 +import org.onosproject.net.region.Region;
31 +import org.onosproject.net.region.RegionAdminService;
32 +import org.onosproject.net.region.RegionEvent;
33 +import org.onosproject.net.region.RegionId;
34 +import org.onosproject.net.region.RegionListener;
35 +import org.onosproject.store.region.impl.DistributedRegionStore;
36 +import org.onosproject.store.service.TestStorageService;
37 +
38 +import java.util.List;
39 +import java.util.Set;
40 +
41 +import static org.junit.Assert.*;
42 +import static org.onosproject.net.region.Region.Type.*;
43 +import static org.onosproject.net.region.RegionEvent.Type.*;
44 +
45 +/**
46 + * Tests of the region service implementation.
47 + */
48 +public class RegionManagerTest {
49 +
50 + private static final RegionId RID1 = RegionId.regionId("r1");
51 + private static final RegionId RID2 = RegionId.regionId("r2");
52 +
53 + private static final DeviceId DID1 = DeviceId.deviceId("foo:d1");
54 + private static final DeviceId DID2 = DeviceId.deviceId("foo:d2");
55 + private static final DeviceId DID3 = DeviceId.deviceId("foo:d3");
56 +
57 + private static final NodeId NID1 = NodeId.nodeId("n1");
58 +
59 + private static final List<Set<NodeId>> MASTERS = ImmutableList.of(ImmutableSet.of(NID1));
60 +
61 + private TestManager manager = new TestManager();
62 + private RegionAdminService service;
63 + private TestStore store = new TestStore();
64 + private TestListener listener = new TestListener();
65 +
66 + @Before
67 + public void setUp() throws Exception {
68 + TestUtils.setField(store, "storageService", new TestStorageService());
69 + store.activate();
70 +
71 + manager.store = store;
72 + manager.addListener(listener);
73 + NetTestTools.injectEventDispatcher(manager, new TestEventDispatcher());
74 + manager.activate();
75 + service = manager;
76 + }
77 +
78 + @After
79 + public void tearDown() {
80 + store.deactivate();
81 + manager.removeListener(listener);
82 + manager.deactivate();
83 + NetTestTools.injectEventDispatcher(manager, null);
84 + }
85 +
86 + @Test
87 + public void basics() {
88 + Region r1 = service.createRegion(RID1, "R1", METRO, MASTERS);
89 + assertEquals("incorrect id", RID1, r1.id());
90 + assertEquals("incorrect event", REGION_ADDED, listener.event.type());
91 +
92 + Region r2 = service.createRegion(RID2, "R2", CAMPUS, MASTERS);
93 + assertEquals("incorrect id", RID2, r2.id());
94 + assertEquals("incorrect type", CAMPUS, r2.type());
95 + assertEquals("incorrect event", REGION_ADDED, listener.event.type());
96 +
97 + r2 = service.updateRegion(RID2, "R2", COUNTRY, MASTERS);
98 + assertEquals("incorrect type", COUNTRY, r2.type());
99 + assertEquals("incorrect event", REGION_UPDATED, listener.event.type());
100 +
101 + Set<Region> regions = service.getRegions();
102 + assertEquals("incorrect size", 2, regions.size());
103 + assertTrue("missing r1", regions.contains(r1));
104 + assertTrue("missing r2", regions.contains(r2));
105 +
106 + r1 = service.getRegion(RID1);
107 + assertEquals("incorrect id", RID1, r1.id());
108 +
109 + service.removeRegion(RID1);
110 + regions = service.getRegions();
111 + assertEquals("incorrect size", 1, regions.size());
112 + assertTrue("missing r2", regions.contains(r2));
113 + assertEquals("incorrect event", REGION_REMOVED, listener.event.type());
114 + }
115 +
116 + @Test(expected = IllegalArgumentException.class)
117 + public void duplicateCreate() {
118 + service.createRegion(RID1, "R1", METRO, MASTERS);
119 + service.createRegion(RID1, "R2", CAMPUS, MASTERS);
120 + }
121 +
122 + @Test(expected = ItemNotFoundException.class)
123 + public void missingUpdate() {
124 + service.updateRegion(RID1, "R1", METRO, MASTERS);
125 + }
126 +
127 + @Test
128 + public void membership() {
129 + Region r = service.createRegion(RID1, "R1", METRO, MASTERS);
130 + assertTrue("no devices expected", service.getRegionDevices(RID1).isEmpty());
131 + assertNull("no region expected", service.getRegionForDevice(DID1));
132 +
133 + service.addDevices(RID1, ImmutableSet.of(DID1, DID2));
134 + Set<DeviceId> deviceIds = service.getRegionDevices(RID1);
135 + assertEquals("incorrect device count", 2, deviceIds.size());
136 + assertTrue("missing d1", deviceIds.contains(DID1));
137 + assertTrue("missing d2", deviceIds.contains(DID2));
138 + assertEquals("wrong region", r, service.getRegionForDevice(DID1));
139 + assertEquals("incorrect event", REGION_MEMBERSHIP_CHANGED, listener.event.type());
140 +
141 + service.addDevices(RID1, ImmutableSet.of(DID3));
142 + deviceIds = service.getRegionDevices(RID1);
143 + assertEquals("incorrect device count", 3, deviceIds.size());
144 + assertTrue("missing d3", deviceIds.contains(DID3));
145 + assertEquals("incorrect event", REGION_MEMBERSHIP_CHANGED, listener.event.type());
146 +
147 + service.addDevices(RID1, ImmutableSet.of(DID3, DID1));
148 + deviceIds = service.getRegionDevices(RID1);
149 + assertEquals("incorrect device count", 3, deviceIds.size());
150 +
151 + service.removeDevices(RID1, ImmutableSet.of(DID2, DID3));
152 + deviceIds = service.getRegionDevices(RID1);
153 + assertEquals("incorrect device count", 1, deviceIds.size());
154 + assertTrue("missing d1", deviceIds.contains(DID1));
155 +
156 + service.removeDevices(RID1, ImmutableSet.of(DID1, DID3));
157 + assertTrue("no devices expected", service.getRegionDevices(RID1).isEmpty());
158 +
159 + service.removeDevices(RID1, ImmutableSet.of(DID2));
160 + assertTrue("no devices expected", service.getRegionDevices(RID1).isEmpty());
161 + }
162 +
163 + private class TestStore extends DistributedRegionStore {
164 + @Override
165 + protected void activate() {
166 + super.activate();
167 + }
168 +
169 + @Override
170 + protected void deactivate() {
171 + super.deactivate();
172 + }
173 + }
174 +
175 + private class TestManager extends RegionManager {
176 + TestManager() {
177 + eventDispatcher = new TestEventDispatcher();
178 + }
179 + }
180 +
181 + private class TestListener implements RegionListener {
182 + RegionEvent event;
183 +
184 + @Override
185 + public void event(RegionEvent event) {
186 + this.event = event;
187 + }
188 + }
189 +}
...\ No newline at end of file ...\ No newline at end of file
1 +/*
2 + * Copyright 2016 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 +
17 +package org.onosproject.store.region.impl;
18 +
19 +import com.google.common.collect.ImmutableSet;
20 +import com.google.common.collect.Sets;
21 +import org.apache.felix.scr.annotations.Activate;
22 +import org.apache.felix.scr.annotations.Component;
23 +import org.apache.felix.scr.annotations.Deactivate;
24 +import org.apache.felix.scr.annotations.Reference;
25 +import org.apache.felix.scr.annotations.ReferenceCardinality;
26 +import org.apache.felix.scr.annotations.Service;
27 +import org.onlab.util.Identifier;
28 +import org.onosproject.cluster.NodeId;
29 +import org.onosproject.net.DeviceId;
30 +import org.onosproject.net.region.DefaultRegion;
31 +import org.onosproject.net.region.Region;
32 +import org.onosproject.net.region.RegionEvent;
33 +import org.onosproject.net.region.RegionId;
34 +import org.onosproject.net.region.RegionStore;
35 +import org.onosproject.net.region.RegionStoreDelegate;
36 +import org.onosproject.store.AbstractStore;
37 +import org.onosproject.store.serializers.KryoNamespaces;
38 +import org.onosproject.store.service.ConsistentMap;
39 +import org.onosproject.store.service.MapEvent;
40 +import org.onosproject.store.service.MapEventListener;
41 +import org.onosproject.store.service.Serializer;
42 +import org.onosproject.store.service.StorageService;
43 +import org.slf4j.Logger;
44 +
45 +import java.util.Arrays;
46 +import java.util.Collection;
47 +import java.util.HashMap;
48 +import java.util.List;
49 +import java.util.Map;
50 +import java.util.Set;
51 +
52 +import static com.google.common.base.Preconditions.checkArgument;
53 +import static com.google.common.base.Preconditions.checkNotNull;
54 +import static org.onlab.util.Tools.nullIsNotFound;
55 +import static org.onosproject.net.region.RegionEvent.Type.REGION_MEMBERSHIP_CHANGED;
56 +import static org.slf4j.LoggerFactory.getLogger;
57 +
58 +/**
59 + * Consistent store implementation for tracking region definitions and device
60 + * region affiliation.
61 + */
62 +@Component(immediate = true)
63 +@Service
64 +public class DistributedRegionStore
65 + extends AbstractStore<RegionEvent, RegionStoreDelegate>
66 + implements RegionStore {
67 +
68 + private static final String NO_REGION = "Region does not exist";
69 + private static final String DUPLICATE_REGION = "Region already exists";
70 +
71 + private final Logger log = getLogger(getClass());
72 +
73 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
74 + protected StorageService storageService;
75 +
76 + private ConsistentMap<RegionId, Region> regionsRepo;
77 + private Map<RegionId, Region> regionsById;
78 +
79 + private ConsistentMap<RegionId, Set<DeviceId>> membershipRepo;
80 + private Map<RegionId, Set<DeviceId>> regionDevices;
81 +
82 + private Map<DeviceId, Region> regionsByDevice = new HashMap<>();
83 +
84 + private final MapEventListener<RegionId, Region> listener =
85 + new InternalRegionListener();
86 + private final MapEventListener<RegionId, Set<DeviceId>> membershipListener =
87 + new InternalMembershipListener();
88 +
89 + @Activate
90 + protected void activate() {
91 + Serializer serializer =
92 + Serializer.using(Arrays.asList(KryoNamespaces.API),
93 + Identifier.class,
94 + RegionId.class,
95 + Region.class,
96 + DefaultRegion.class,
97 + Region.Type.class);
98 +
99 + regionsRepo = storageService.<RegionId, Region>consistentMapBuilder()
100 + .withSerializer(serializer)
101 + .withName("onos-regions")
102 + .withRelaxedReadConsistency()
103 + .build();
104 + regionsRepo.addListener(listener);
105 + regionsById = regionsRepo.asJavaMap();
106 +
107 + membershipRepo = storageService.<RegionId, Set<DeviceId>>consistentMapBuilder()
108 + .withSerializer(serializer)
109 + .withName("onos-region-devices")
110 + .withRelaxedReadConsistency()
111 + .build();
112 + membershipRepo.addListener(membershipListener);
113 + regionDevices = membershipRepo.asJavaMap();
114 + log.info("Started");
115 + }
116 +
117 + @Deactivate
118 + protected void deactivate() {
119 + regionsRepo.removeListener(listener);
120 + membershipRepo.removeListener(membershipListener);
121 + regionsByDevice.clear();
122 + log.info("Stopped");
123 + }
124 +
125 + @Override
126 + public Set<Region> getRegions() {
127 + return ImmutableSet.copyOf(regionsById.values());
128 + }
129 +
130 + @Override
131 + public Region getRegion(RegionId regionId) {
132 + return nullIsNotFound(regionsById.get(regionId), NO_REGION);
133 + }
134 +
135 + @Override
136 + public Region getRegionForDevice(DeviceId deviceId) {
137 + return regionsByDevice.get(deviceId);
138 + }
139 +
140 + @Override
141 + public Set<DeviceId> getRegionDevices(RegionId regionId) {
142 + Set<DeviceId> deviceIds = regionDevices.get(regionId);
143 + return deviceIds != null ? ImmutableSet.copyOf(deviceIds) : ImmutableSet.of();
144 + }
145 +
146 + @Override
147 + public Region createRegion(RegionId regionId, String name, Region.Type type,
148 + List<Set<NodeId>> masterNodeIds) {
149 + return regionsRepo.compute(regionId, (id, region) -> {
150 + checkArgument(region == null, DUPLICATE_REGION);
151 + return new DefaultRegion(regionId, name, type, masterNodeIds);
152 + }).value();
153 + }
154 +
155 + @Override
156 + public Region updateRegion(RegionId regionId, String name, Region.Type type,
157 + List<Set<NodeId>> masterNodeIds) {
158 + return regionsRepo.compute(regionId, (id, region) -> {
159 + nullIsNotFound(region, NO_REGION);
160 + return new DefaultRegion(regionId, name, type, masterNodeIds);
161 + }).value();
162 + }
163 +
164 + @Override
165 + public void removeRegion(RegionId regionId) {
166 + membershipRepo.remove(regionId);
167 + regionsRepo.remove(regionId);
168 + }
169 +
170 + @Override
171 + public void addDevices(RegionId regionId, Collection<DeviceId> deviceIds) {
172 + membershipRepo.compute(regionId, (id, existingDevices) -> {
173 + if (existingDevices == null) {
174 + return ImmutableSet.copyOf(deviceIds);
175 + } else if (!existingDevices.containsAll(deviceIds)) {
176 + return ImmutableSet.<DeviceId>builder()
177 + .addAll(existingDevices)
178 + .addAll(deviceIds)
179 + .build();
180 + } else {
181 + return existingDevices;
182 + }
183 + });
184 +
185 + Region region = regionsById.get(regionId);
186 + deviceIds.forEach(deviceId -> regionsByDevice.put(deviceId, region));
187 + }
188 +
189 + @Override
190 + public void removeDevices(RegionId regionId, Collection<DeviceId> deviceIds) {
191 + membershipRepo.compute(regionId, (id, existingDevices) -> {
192 + if (existingDevices == null || existingDevices.isEmpty()) {
193 + return ImmutableSet.of();
194 + } else {
195 + return ImmutableSet.<DeviceId>builder()
196 + .addAll(Sets.difference(existingDevices,
197 + ImmutableSet.copyOf(deviceIds)))
198 + .build();
199 + }
200 + });
201 +
202 + deviceIds.forEach(deviceId -> regionsByDevice.remove(deviceId));
203 + }
204 +
205 + /**
206 + * Listener class to map listener events to the region inventory events.
207 + */
208 + private class InternalRegionListener implements MapEventListener<RegionId, Region> {
209 + @Override
210 + public void event(MapEvent<RegionId, Region> event) {
211 + Region region = null;
212 + RegionEvent.Type type = null;
213 + switch (event.type()) {
214 + case INSERT:
215 + type = RegionEvent.Type.REGION_ADDED;
216 + region = checkNotNull(event.newValue().value());
217 + break;
218 + case UPDATE:
219 + type = RegionEvent.Type.REGION_UPDATED;
220 + region = checkNotNull(event.newValue().value());
221 + break;
222 + case REMOVE:
223 + type = RegionEvent.Type.REGION_REMOVED;
224 + region = checkNotNull(event.oldValue().value());
225 + break;
226 + default:
227 + log.error("Unsupported event type: " + event.type());
228 + }
229 + notifyDelegate(new RegionEvent(type, region));
230 + }
231 + }
232 +
233 + /**
234 + * Listener class to map listener events to the region membership events.
235 + */
236 + private class InternalMembershipListener implements MapEventListener<RegionId, Set<DeviceId>> {
237 + @Override
238 + public void event(MapEvent<RegionId, Set<DeviceId>> event) {
239 + if (event.type() != MapEvent.Type.REMOVE) {
240 + notifyDelegate(new RegionEvent(REGION_MEMBERSHIP_CHANGED,
241 + regionsById.get(event.key()),
242 + event.newValue().value()));
243 + }
244 + }
245 + }
246 +}
1 +/*
2 + * Copyright 2016 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 +
17 +/**
18 + * A distributed store implementation for tracking region definitions
19 + * consistently across the cluster.
20 + */
21 +package org.onosproject.store.region.impl;
...\ No newline at end of file ...\ No newline at end of file
1 +/*
2 + * Copyright 2016 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 +
17 +package org.onosproject.store.region.impl;
18 +
19 +import com.google.common.collect.ImmutableList;
20 +import com.google.common.collect.ImmutableSet;
21 +import org.junit.After;
22 +import org.junit.Before;
23 +import org.junit.Test;
24 +import org.onlab.util.ItemNotFoundException;
25 +import org.onosproject.cluster.NodeId;
26 +import org.onosproject.net.DeviceId;
27 +import org.onosproject.net.region.Region;
28 +import org.onosproject.net.region.RegionEvent;
29 +import org.onosproject.net.region.RegionId;
30 +import org.onosproject.store.service.TestStorageService;
31 +
32 +import java.util.List;
33 +import java.util.Set;
34 +
35 +import static org.junit.Assert.*;
36 +import static org.onosproject.net.region.Region.Type.*;
37 +import static org.onosproject.net.region.RegionEvent.Type.*;
38 +
39 +/**
40 + * Test of the distributed region store implementation.
41 + */
42 +public class DistributedRegionStoreTest {
43 +
44 + private static final RegionId RID1 = RegionId.regionId("r1");
45 + private static final RegionId RID2 = RegionId.regionId("r2");
46 +
47 + private static final DeviceId DID1 = DeviceId.deviceId("foo:d1");
48 + private static final DeviceId DID2 = DeviceId.deviceId("foo:d2");
49 + private static final DeviceId DID3 = DeviceId.deviceId("foo:d3");
50 +
51 + private static final NodeId NID1 = NodeId.nodeId("n1");
52 +
53 + private static final List<Set<NodeId>> MASTERS = ImmutableList.of(ImmutableSet.of(NID1));
54 +
55 + private TestStore store;
56 + private RegionEvent event;
57 +
58 + /**
59 + * Sets up the device key store and the storage service test harness.
60 + */
61 + @Before
62 + public void setUp() {
63 + store = new TestStore();
64 + store.storageService = new TestStorageService();
65 + store.setDelegate(e -> this.event = e);
66 + store.activate();
67 + }
68 +
69 + /**
70 + * Tears down the device key store.
71 + */
72 + @After
73 + public void tearDown() {
74 + store.deactivate();
75 + }
76 +
77 + @Test
78 + public void basics() {
79 + Region r1 = store.createRegion(RID1, "R1", METRO, MASTERS);
80 + assertEquals("incorrect id", RID1, r1.id());
81 + assertEquals("incorrect event", REGION_ADDED, event.type());
82 +
83 + Region r2 = store.createRegion(RID2, "R2", CAMPUS, MASTERS);
84 + assertEquals("incorrect id", RID2, r2.id());
85 + assertEquals("incorrect type", CAMPUS, r2.type());
86 + assertEquals("incorrect event", REGION_ADDED, event.type());
87 +
88 + r2 = store.updateRegion(RID2, "R2", COUNTRY, MASTERS);
89 + assertEquals("incorrect type", COUNTRY, r2.type());
90 + assertEquals("incorrect event", REGION_UPDATED, event.type());
91 +
92 + Set<Region> regions = store.getRegions();
93 + assertEquals("incorrect size", 2, regions.size());
94 + assertTrue("missing r1", regions.contains(r1));
95 + assertTrue("missing r2", regions.contains(r2));
96 +
97 + r1 = store.getRegion(RID1);
98 + assertEquals("incorrect id", RID1, r1.id());
99 +
100 + store.removeRegion(RID1);
101 + regions = store.getRegions();
102 + assertEquals("incorrect size", 1, regions.size());
103 + assertTrue("missing r2", regions.contains(r2));
104 + assertEquals("incorrect event", REGION_REMOVED, event.type());
105 + }
106 +
107 + @Test(expected = IllegalArgumentException.class)
108 + public void duplicateCreate() {
109 + store.createRegion(RID1, "R1", METRO, MASTERS);
110 + store.createRegion(RID1, "R2", CAMPUS, MASTERS);
111 + }
112 +
113 + @Test(expected = ItemNotFoundException.class)
114 + public void missingUpdate() {
115 + store.updateRegion(RID1, "R1", METRO, MASTERS);
116 + }
117 +
118 + @Test
119 + public void membership() {
120 + Region r = store.createRegion(RID1, "R1", METRO, MASTERS);
121 + assertTrue("no devices expected", store.getRegionDevices(RID1).isEmpty());
122 + assertNull("no region expected", store.getRegionForDevice(DID1));
123 +
124 + store.addDevices(RID1, ImmutableSet.of(DID1, DID2));
125 + Set<DeviceId> deviceIds = store.getRegionDevices(RID1);
126 + assertEquals("incorrect device count", 2, deviceIds.size());
127 + assertTrue("missing d1", deviceIds.contains(DID1));
128 + assertTrue("missing d2", deviceIds.contains(DID2));
129 + assertEquals("wrong region", r, store.getRegionForDevice(DID1));
130 +
131 + store.addDevices(RID1, ImmutableSet.of(DID3));
132 + deviceIds = store.getRegionDevices(RID1);
133 + assertEquals("incorrect device count", 3, deviceIds.size());
134 + assertTrue("missing d3", deviceIds.contains(DID3));
135 +
136 + store.addDevices(RID1, ImmutableSet.of(DID3, DID1));
137 + deviceIds = store.getRegionDevices(RID1);
138 + assertEquals("incorrect device count", 3, deviceIds.size());
139 +
140 + store.removeDevices(RID1, ImmutableSet.of(DID2, DID3));
141 + deviceIds = store.getRegionDevices(RID1);
142 + assertEquals("incorrect device count", 1, deviceIds.size());
143 + assertTrue("missing d1", deviceIds.contains(DID1));
144 +
145 + store.removeDevices(RID1, ImmutableSet.of(DID1, DID3));
146 + assertTrue("no devices expected", store.getRegionDevices(RID1).isEmpty());
147 +
148 + store.removeDevices(RID1, ImmutableSet.of(DID2));
149 + assertTrue("no devices expected", store.getRegionDevices(RID1).isEmpty());
150 + }
151 +
152 + class TestStore extends DistributedRegionStore {
153 + }
154 +}
...\ No newline at end of file ...\ No newline at end of file
1 -Copyright 2014-$today.year Open Networking Laboratory 1 +Copyright $today.year Open Networking Laboratory
2 2
3 Licensed under the Apache License, Version 2.0 (the "License"); 3 Licensed under the Apache License, Version 2.0 (the "License");
4 you may not use this file except in compliance with the License. 4 you may not use this file except in compliance with the License.
......
1 +/*
2 + * Copyright 2014-2016 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 +
17 +package org.onlab.util;
18 +
19 +import java.util.Objects;
20 +
21 +import static com.google.common.base.Preconditions.checkNotNull;
22 +
23 +/**
24 + * Abstract identifier backed by another value, e.g. string, int.
25 + */
26 +public class Identifier<T> {
27 +
28 + protected final T identifier; // backing identifier value
29 +
30 + /**
31 + * Constructor for serialization.
32 + */
33 + protected Identifier() {
34 + this.identifier = null;
35 + }
36 +
37 + /**
38 + * Constructs an identifier backed by the specified value.
39 + *
40 + * @param value the backing value
41 + */
42 + protected Identifier(T value) {
43 + this.identifier = checkNotNull(value, "Identifier cannot be null.");
44 + }
45 +
46 + /**
47 + * Returns the backing identifier value.
48 + *
49 + * @return identifier
50 + */
51 + public T id() {
52 + return identifier;
53 + }
54 +
55 + /**
56 + * Returns the hashcode of the identifier.
57 + *
58 + * @return hashcode
59 + */
60 + @Override
61 + public int hashCode() {
62 + return identifier.hashCode();
63 + }
64 +
65 + /**
66 + * Compares two device key identifiers for equality.
67 + *
68 + * @param obj to compare against
69 + * @return true if the objects are equal, false otherwise.
70 + */
71 + @Override
72 + public boolean equals(Object obj) {
73 + if (this == obj) {
74 + return true;
75 + }
76 + if (obj instanceof Identifier) {
77 + Identifier that = (Identifier) obj;
78 + return this.getClass() == that.getClass() &&
79 + Objects.equals(this.identifier, that.identifier);
80 + }
81 + return false;
82 + }
83 +
84 + /**
85 + * Returns a string representation of a DeviceKeyId.
86 + *
87 + * @return string
88 + */
89 + public String toString() {
90 + return identifier.toString();
91 + }
92 +
93 +}
1 +/*
2 + * Copyright 2014-2016 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 +
17 +package org.onlab.util;
18 +
19 +import com.google.common.testing.EqualsTester;
20 +import org.junit.Test;
21 +
22 +import static org.junit.Assert.*;
23 +
24 +/**
25 + * Test of the base identifier.
26 + */
27 +public class IdentifierTest {
28 +
29 + @Test
30 + public void basics() {
31 + FooId id = new FooId(123);
32 + assertEquals("incorrect value", 123, (int) id.id());
33 + }
34 +
35 + @Test
36 + public void equality() {
37 + FooId a = new FooId(1);
38 + FooId b = new FooId(1);
39 + FooId c = new FooId(2);
40 + new EqualsTester().addEqualityGroup(a, b).addEqualityGroup(c).testEquals();
41 + }
42 +
43 + static class FooId extends Identifier<Integer> {
44 + FooId(int id) {
45 + super(id);
46 + }
47 + }
48 +
49 +}
...\ No newline at end of file ...\ No newline at end of file