Toggle navigation
Toggle navigation
This project
Loading...
Sign in
홍길동
/
onos
Go to a project
Toggle navigation
Toggle navigation pinning
Projects
Groups
Snippets
Help
Project
Activity
Repository
Pipelines
Graphs
Issues
0
Merge Requests
0
Wiki
Snippets
Network
Create a new issue
Builds
Commits
Issue Boards
Authored by
Ayaka Koshibe
2014-10-07 14:43:52 -0700
Browse Files
Options
Browse Files
Download
Email Patches
Plain Diff
Commit
c4047709262cde23eb91b62fccdf7b35049f3748
c4047709
1 parent
25fd23a6
role reassignment tweaks
Change-Id: Ie6d412787330e67a13e605a34f0824cf70882f85
Show whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
265 additions
and
210 deletions
core/api/src/main/java/org/onlab/onos/cluster/MastershipService.java
core/api/src/main/java/org/onlab/onos/cluster/MastershipStore.java
core/net/src/main/java/org/onlab/onos/cluster/impl/MastershipManager.java
core/net/src/main/java/org/onlab/onos/net/device/impl/DeviceManager.java
core/net/src/test/java/org/onlab/onos/net/device/impl/DeviceManagerTest.java
core/store/hz/cluster/src/main/java/org/onlab/onos/store/cluster/impl/DistributedMastershipStore.java
core/store/hz/cluster/src/test/java/org/onlab/onos/store/cluster/impl/DistributedMastershipStoreTest.java
core/store/trivial/src/main/java/org/onlab/onos/store/trivial/impl/SimpleMastershipStore.java
core/store/trivial/src/test/java/org/onlab/onos/store/trivial/impl/SimpleMastershipStoreTest.java
openflow/ctl/src/main/java/org/onlab/onos/openflow/controller/impl/OFChannelHandler.java
openflow/ctl/src/main/java/org/onlab/onos/openflow/controller/impl/OpenFlowControllerImpl.java
core/api/src/main/java/org/onlab/onos/cluster/MastershipService.java
View file @
c404770
...
...
@@ -33,7 +33,7 @@ public interface MastershipService {
/**
* Abandons mastership of the specified device on the local node thus
* forcing selection of a new master. If the local node is not a master
* for this device, no
action will be taken
.
* for this device, no
master selection will occur
.
*
* @param deviceId the identifier of the device
*/
...
...
core/api/src/main/java/org/onlab/onos/cluster/MastershipStore.java
View file @
c404770
...
...
@@ -66,12 +66,25 @@ public interface MastershipStore extends Store<MastershipEvent, MastershipStoreD
MastershipTerm
getTermFor
(
DeviceId
deviceId
);
/**
* Revokes a controller instance's mastership over a device and hands
* over mastership to another controller instance.
* Sets a controller instance's mastership role to STANDBY for a device.
* If the role is MASTER, another controller instance will be selected
* as a candidate master.
*
* @param nodeId the controller instance identifier
* @param deviceId device to revoke mastership for
* @param deviceId device to revoke mastership
role
for
* @return a mastership event
*/
MastershipEvent
unsetMaster
(
NodeId
nodeId
,
DeviceId
deviceId
);
MastershipEvent
setStandby
(
NodeId
nodeId
,
DeviceId
deviceId
);
/**
* Allows a controller instance to give up its current role for a device.
* If the role is MASTER, another controller instance will be selected
* as a candidate master.
*
* @param nodeId the controller instance identifier
* @param deviceId device to revoke mastership role for
* @return a mastership event
*/
MastershipEvent
relinquishRole
(
NodeId
nodeId
,
DeviceId
deviceId
);
}
...
...
core/net/src/main/java/org/onlab/onos/cluster/impl/MastershipManager.java
View file @
c404770
...
...
@@ -82,7 +82,7 @@ implements MastershipService, MastershipAdminService {
if
(
role
.
equals
(
MastershipRole
.
MASTER
))
{
event
=
store
.
setMaster
(
nodeId
,
deviceId
);
}
else
{
event
=
store
.
unsetMaster
(
nodeId
,
deviceId
);
event
=
store
.
setStandby
(
nodeId
,
deviceId
);
}
if
(
event
!=
null
)
{
...
...
@@ -98,13 +98,10 @@ implements MastershipService, MastershipAdminService {
@Override
public
void
relinquishMastership
(
DeviceId
deviceId
)
{
MastershipRole
role
=
getLocalRole
(
deviceId
);
if
(!
role
.
equals
(
MastershipRole
.
MASTER
))
{
return
;
}
MastershipEvent
event
=
store
.
unsetMaster
(
MastershipEvent
event
=
null
;
event
=
store
.
relinquishRole
(
clusterService
.
getLocalNode
().
id
(),
deviceId
);
if
(
event
!=
null
)
{
post
(
event
);
}
...
...
core/net/src/main/java/org/onlab/onos/net/device/impl/DeviceManager.java
View file @
c404770
...
...
@@ -142,7 +142,7 @@ public class DeviceManager
// Applies the specified role to the device; ignores NONE
private
void
applyRole
(
DeviceId
deviceId
,
MastershipRole
newRole
)
{
if
(
newRole
!=
MastershipRole
.
NONE
)
{
if
(
newRole
.
equals
(
MastershipRole
.
NONE
)
)
{
Device
device
=
store
.
getDevice
(
deviceId
);
DeviceProvider
provider
=
getProvider
(
device
.
providerId
());
if
(
provider
!=
null
)
{
...
...
@@ -196,11 +196,8 @@ public class DeviceManager
DeviceEvent
event
=
store
.
createOrUpdateDevice
(
provider
().
id
(),
deviceId
,
deviceDescription
);
// If there was a change of any kind, trigger role selection
// process.
if
(
event
!=
null
)
{
log
.
info
(
"Device {} connected"
,
deviceId
);
//mastershipService.requestRoleFor(deviceId);
provider
().
roleChanged
(
event
.
subject
(),
mastershipService
.
requestRoleFor
(
deviceId
));
post
(
event
);
...
...
@@ -212,11 +209,11 @@ public class DeviceManager
checkNotNull
(
deviceId
,
DEVICE_ID_NULL
);
checkValidity
();
DeviceEvent
event
=
store
.
markOffline
(
deviceId
);
//we're no longer capable of being master or a candidate.
mastershipService
.
relinquishMastership
(
deviceId
);
//we're no longer capable of mastership.
if
(
event
!=
null
)
{
log
.
info
(
"Device {} disconnected"
,
deviceId
);
mastershipService
.
relinquishMastership
(
deviceId
);
post
(
event
);
}
}
...
...
@@ -267,17 +264,23 @@ public class DeviceManager
}
// Intercepts mastership events
private
class
InternalMastershipListener
implements
MastershipListener
{
private
class
InternalMastershipListener
implements
MastershipListener
{
@Override
public
void
event
(
MastershipEvent
event
)
{
DeviceId
did
=
event
.
subject
();
if
(
isAvailable
(
did
))
{
if
(
event
.
master
().
equals
(
clusterService
.
getLocalNode
().
id
()))
{
MastershipTerm
term
=
mastershipService
.
requestTermService
()
.
getMastershipTerm
(
event
.
subject
());
clockService
.
setMastershipTerm
(
event
.
subject
(),
term
);
applyRole
(
event
.
subject
(),
MastershipRole
.
MASTER
);
MastershipTerm
term
=
termService
.
getMastershipTerm
(
did
);
clockService
.
setMastershipTerm
(
did
,
term
);
applyRole
(
did
,
MastershipRole
.
MASTER
);
}
else
{
applyRole
(
did
,
MastershipRole
.
STANDBY
);
}
}
else
{
applyRole
(
event
.
subject
(),
MastershipRole
.
STANDBY
);
//device dead to node, give up
mastershipService
.
relinquishMastership
(
did
);
applyRole
(
did
,
MastershipRole
.
STANDBY
);
}
}
}
...
...
core/net/src/test/java/org/onlab/onos/net/device/impl/DeviceManagerTest.java
View file @
c404770
package
org
.
onlab
.
onos
.
net
.
device
.
impl
;
import
com.google.common.collect.Sets
;
import
org.junit.After
;
import
org.junit.Before
;
import
org.junit.Ignore
;
...
...
@@ -258,7 +259,8 @@ public class DeviceManagerTest {
}
}
private
static
class
TestMastershipService
extends
MastershipServiceAdapter
{
private
static
class
TestMastershipService
extends
MastershipServiceAdapter
{
@Override
public
MastershipRole
getLocalRole
(
DeviceId
deviceId
)
{
return
MastershipRole
.
MASTER
;
...
...
core/store/hz/cluster/src/main/java/org/onlab/onos/store/cluster/impl/DistributedMastershipStore.java
View file @
c404770
...
...
@@ -10,7 +10,6 @@ import org.apache.felix.scr.annotations.Component;
import
org.apache.felix.scr.annotations.Deactivate
;
import
org.apache.felix.scr.annotations.Reference
;
import
org.apache.felix.scr.annotations.ReferenceCardinality
;
import
org.apache.felix.scr.annotations.ReferencePolicy
;
import
org.apache.felix.scr.annotations.Service
;
import
org.onlab.onos.cluster.ClusterService
;
import
org.onlab.onos.cluster.MastershipEvent
;
...
...
@@ -20,15 +19,16 @@ import org.onlab.onos.cluster.MastershipTerm;
import
org.onlab.onos.cluster.NodeId
;
import
org.onlab.onos.net.DeviceId
;
import
org.onlab.onos.net.MastershipRole
;
import
org.onlab.onos.net.device.DeviceService
;
import
org.onlab.onos.store.common.AbstractHazelcastStore
;
import
com.google.common.collect.ImmutableSet
;
import
com.hazelcast.core.ILock
;
import
com.hazelcast.core.IMap
;
import
com.hazelcast.core.MultiMap
;
/**
* Distributed implementation of the cluster nodes store.
* Distributed implementation of the mastership store. The store is
* responsible for the master selection process.
*/
@Component
(
immediate
=
true
)
@Service
...
...
@@ -38,35 +38,34 @@ implements MastershipStore {
//arbitrary lock name
private
static
final
String
LOCK
=
"lock"
;
//initial term value
//initial term
/TTL
value
private
static
final
Integer
INIT
=
0
;
//placeholder non-null value
private
static
final
Byte
NIL
=
0x0
;
//devices to masters
protected
IMap
<
byte
[],
byte
[]>
rawM
asters
;
protected
IMap
<
byte
[],
byte
[]>
m
asters
;
//devices to terms
protected
IMap
<
byte
[],
Integer
>
rawTerms
;
//collection of nodes. values are ignored, as it's used as a makeshift 'set'
protected
IMap
<
byte
[],
Byte
>
backups
;
protected
IMap
<
byte
[],
Integer
>
terms
;
//re-election related, disjoint-set structures:
//device-nodes multiset of available nodes
protected
MultiMap
<
byte
[],
byte
[]>
standbys
;
//device-nodes multiset for nodes that have given up on device
protected
MultiMap
<
byte
[],
byte
[]>
unusable
;
@Reference
(
cardinality
=
ReferenceCardinality
.
MANDATORY_UNARY
)
protected
ClusterService
clusterService
;
//FIXME: need to guarantee that this will be met, sans circular dependencies
@Reference
(
policy
=
ReferencePolicy
.
DYNAMIC
)
protected
DeviceService
deviceService
;
@Override
@Activate
public
void
activate
()
{
super
.
activate
();
rawMasters
=
theInstance
.
getMap
(
"masters"
);
rawTerms
=
theInstance
.
getMap
(
"terms"
);
backups
=
theInstance
.
getMap
(
"backups"
);
masters
=
theInstance
.
getMap
(
"masters"
);
terms
=
theInstance
.
getMap
(
"terms"
);
standbys
=
theInstance
.
getMultiMap
(
"backups"
);
unusable
=
theInstance
.
getMultiMap
(
"unusable"
);
rawM
asters
.
addEntryListener
(
new
RemoteMasterShipEventHandler
(),
true
);
m
asters
.
addEntryListener
(
new
RemoteMasterShipEventHandler
(),
true
);
log
.
info
(
"Started"
);
}
...
...
@@ -77,6 +76,30 @@ implements MastershipStore {
}
@Override
public
MastershipRole
getRole
(
NodeId
nodeId
,
DeviceId
deviceId
)
{
byte
[]
did
=
serialize
(
deviceId
);
byte
[]
nid
=
serialize
(
nodeId
);
NodeId
current
=
deserialize
(
masters
.
get
(
did
));
if
(
current
==
null
)
{
if
(
standbys
.
containsEntry
(
did
,
nid
))
{
//was previously standby, or set to standby from master
return
MastershipRole
.
STANDBY
;
}
else
{
return
MastershipRole
.
NONE
;
}
}
else
{
if
(
current
.
equals
(
nodeId
))
{
//*should* be in unusable, not always
return
MastershipRole
.
MASTER
;
}
else
{
//may be in backups or unusable from earlier retirement
return
MastershipRole
.
STANDBY
;
}
}
}
@Override
public
MastershipEvent
setMaster
(
NodeId
nodeId
,
DeviceId
deviceId
)
{
byte
[]
did
=
serialize
(
deviceId
);
byte
[]
nid
=
serialize
(
nodeId
);
...
...
@@ -85,30 +108,31 @@ implements MastershipStore {
lock
.
lock
();
try
{
MastershipRole
role
=
getRole
(
nodeId
,
deviceId
);
Integer
term
=
rawTerms
.
get
(
did
);
switch
(
role
)
{
case
MASTER:
//reinforce mastership
evict
(
nid
,
did
);
return
null
;
case
STANDBY:
rawMasters
.
put
(
did
,
nid
);
rawTerms
.
put
(
did
,
++
term
);
backups
.
putIfAbsent
(
nid
,
NIL
);
break
;
case
NONE:
rawMasters
.
put
(
did
,
nid
);
//new switch OR state transition after being orphaned
if
(
term
==
null
)
{
rawTerms
.
put
(
did
,
INIT
);
}
else
{
rawTerms
.
put
(
did
,
++
term
);
//make current master standby
byte
[]
current
=
masters
.
get
(
did
);
if
(
current
!=
null
)
{
backup
(
current
,
did
);
}
backups
.
put
(
nid
,
NIL
);
break
;
//assign specified node as new master
masters
.
put
(
did
,
nid
);
evict
(
nid
,
did
);
updateTerm
(
did
);
return
new
MastershipEvent
(
MASTER_CHANGED
,
deviceId
,
nodeId
);
case
NONE:
masters
.
put
(
did
,
nid
);
evict
(
nid
,
did
);
updateTerm
(
did
);
return
new
MastershipEvent
(
MASTER_CHANGED
,
deviceId
,
nodeId
);
default
:
log
.
warn
(
"unknown Mastership Role {}"
,
role
);
return
null
;
}
return
new
MastershipEvent
(
MASTER_CHANGED
,
deviceId
,
nodeId
);
}
finally
{
lock
.
unlock
();
}
...
...
@@ -116,14 +140,14 @@ implements MastershipStore {
@Override
public
NodeId
getMaster
(
DeviceId
deviceId
)
{
return
deserialize
(
rawM
asters
.
get
(
serialize
(
deviceId
)));
return
deserialize
(
m
asters
.
get
(
serialize
(
deviceId
)));
}
@Override
public
Set
<
DeviceId
>
getDevices
(
NodeId
nodeId
)
{
ImmutableSet
.
Builder
<
DeviceId
>
builder
=
ImmutableSet
.
builder
();
for
(
Map
.
Entry
<
byte
[],
byte
[]>
entry
:
rawM
asters
.
entrySet
())
{
for
(
Map
.
Entry
<
byte
[],
byte
[]>
entry
:
m
asters
.
entrySet
())
{
if
(
nodeId
.
equals
(
deserialize
(
entry
.
getValue
())))
{
builder
.
add
((
DeviceId
)
deserialize
(
entry
.
getKey
()));
}
...
...
@@ -134,11 +158,8 @@ implements MastershipStore {
@Override
public
MastershipRole
requestRole
(
DeviceId
deviceId
)
{
// first to empty slot for device in master map is MASTER
// depending on how backups are organized, might need to trigger election
// so only controller doesn't set itself to backup for another device
byte
[]
did
=
serialize
(
deviceId
);
NodeId
local
=
clusterService
.
getLocalNode
().
id
();
byte
[]
did
=
serialize
(
deviceId
);
byte
[]
lnid
=
serialize
(
local
);
ILock
lock
=
theInstance
.
getLock
(
LOCK
);
...
...
@@ -147,15 +168,17 @@ implements MastershipStore {
MastershipRole
role
=
getRole
(
local
,
deviceId
);
switch
(
role
)
{
case
MASTER:
evict
(
lnid
,
did
);
break
;
case
STANDBY:
backup
s
.
put
(
lnid
,
NIL
);
rawT
erms
.
putIfAbsent
(
did
,
INIT
);
backup
(
lnid
,
did
);
t
erms
.
putIfAbsent
(
did
,
INIT
);
break
;
case
NONE:
rawMasters
.
put
(
did
,
lnid
);
rawTerms
.
putIfAbsent
(
did
,
INIT
);
backups
.
put
(
lnid
,
NIL
);
//claim mastership
masters
.
put
(
did
,
lnid
);
evict
(
lnid
,
did
);
updateTerm
(
did
);
role
=
MastershipRole
.
MASTER
;
break
;
default
:
...
...
@@ -168,41 +191,50 @@ implements MastershipStore {
}
@Override
public
Mastership
Role
getRole
(
NodeId
nodeId
,
DeviceId
deviceId
)
{
public
Mastership
Term
getTermFor
(
DeviceId
deviceId
)
{
byte
[]
did
=
serialize
(
deviceId
);
NodeId
current
=
deserialize
(
rawMasters
.
get
(
did
));
MastershipRole
role
=
null
;
if
(
current
==
null
)
{
//IFF no controllers have claimed mastership over it
role
=
MastershipRole
.
NONE
;
}
else
{
if
(
current
.
equals
(
nodeId
))
{
role
=
MastershipRole
.
MASTER
;
}
else
{
role
=
MastershipRole
.
STANDBY
;
}
if
((
masters
.
get
(
did
)
==
null
)
||
(
terms
.
get
(
did
)
==
null
))
{
return
null
;
}
return
role
;
return
MastershipTerm
.
of
(
(
NodeId
)
deserialize
(
masters
.
get
(
did
)),
terms
.
get
(
did
))
;
}
@Override
public
MastershipTerm
getTermFor
(
DeviceId
deviceId
)
{
byte
[]
did
=
serialize
(
deviceId
);
public
MastershipEvent
setStandby
(
NodeId
nodeId
,
DeviceId
deviceId
)
{
byte
[]
did
=
serialize
(
deviceId
);
byte
[]
nid
=
serialize
(
nodeId
);
MastershipEvent
event
=
null
;
if
((
rawMasters
.
get
(
did
)
==
null
)
||
(
rawTerms
.
get
(
did
)
==
null
))
{
return
null
;
ILock
lock
=
theInstance
.
getLock
(
LOCK
);
lock
.
lock
();
try
{
MastershipRole
role
=
getRole
(
nodeId
,
deviceId
);
switch
(
role
)
{
case
MASTER:
event
=
reelect
(
nodeId
,
deviceId
);
backup
(
nid
,
did
);
break
;
case
STANDBY:
//fall through to reinforce role
case
NONE:
backup
(
nid
,
did
);
break
;
default
:
log
.
warn
(
"unknown Mastership Role {}"
,
role
);
}
return
event
;
}
finally
{
lock
.
unlock
();
}
return
MastershipTerm
.
of
(
(
NodeId
)
deserialize
(
rawMasters
.
get
(
did
)),
rawTerms
.
get
(
did
));
}
@Override
public
MastershipEvent
unsetMaster
(
NodeId
nodeId
,
DeviceId
deviceId
)
{
public
MastershipEvent
relinquishRole
(
NodeId
nodeId
,
DeviceId
deviceId
)
{
byte
[]
did
=
serialize
(
deviceId
);
byte
[]
nid
=
serialize
(
nodeId
);
MastershipEvent
event
=
null
;
ILock
lock
=
theInstance
.
getLock
(
LOCK
);
lock
.
lock
();
...
...
@@ -210,54 +242,84 @@ implements MastershipStore {
MastershipRole
role
=
getRole
(
nodeId
,
deviceId
);
switch
(
role
)
{
case
MASTER:
//hand off device to another
NodeId
backup
=
reelect
(
nodeId
,
deviceId
);
if
(
backup
==
null
)
{
//goes back to NONE
rawMasters
.
remove
(
did
);
}
else
{
//goes to STANDBY for local, MASTER for someone else
Integer
term
=
rawTerms
.
get
(
did
);
rawMasters
.
put
(
did
,
serialize
(
backup
));
rawTerms
.
put
(
did
,
++
term
);
return
new
MastershipEvent
(
MASTER_CHANGED
,
deviceId
,
backup
);
}
event
=
reelect
(
nodeId
,
deviceId
);
evict
(
nid
,
did
);
break
;
case
STANDBY:
//fall through to reinforce relinquishment
case
NONE:
evict
(
nid
,
did
);
break
;
default
:
log
.
warn
(
"unknown Mastership Role {}"
,
role
);
}
return
null
;
return
event
;
}
finally
{
lock
.
unlock
();
}
}
//helper for "re-electing" a new master for a given device
private
NodeId
reelect
(
NodeId
current
,
DeviceId
deviceId
)
{
//helper to fetch a new master candidate for a given device.
private
MastershipEvent
reelect
(
NodeId
current
,
DeviceId
deviceId
)
{
byte
[]
did
=
serialize
(
deviceId
);
byte
[]
nid
=
serialize
(
current
);
for
(
byte
[]
node
:
backups
.
keySet
())
{
NodeId
nid
=
deserialize
(
node
);
//if a device dies we shouldn't pick another master for it.
if
(!
current
.
equals
(
nid
)
&&
(
deviceService
.
isAvailable
(
deviceId
)))
{
return
nid
;
//if this is an queue it'd be neater.
byte
[]
backup
=
null
;
for
(
byte
[]
n
:
standbys
.
get
(
serialize
(
deviceId
)))
{
if
(!
current
.
equals
(
deserialize
(
n
)))
{
backup
=
n
;
break
;
}
}
if
(
backup
==
null
)
{
masters
.
remove
(
did
,
nid
);
return
null
;
}
else
{
masters
.
put
(
did
,
backup
);
evict
(
backup
,
did
);
Integer
term
=
terms
.
get
(
did
);
terms
.
put
(
did
,
++
term
);
return
new
MastershipEvent
(
MASTER_CHANGED
,
deviceId
,
(
NodeId
)
deserialize
(
backup
));
}
}
//adds node to pool(s) of backup
private
void
backup
(
NodeId
nodeId
,
DeviceId
deviceId
)
{
//TODO might be useful to isolate out this function and reelect() if we
//get more backup/election schemes
//adds node to pool(s) of backups and moves them from unusable.
private
void
backup
(
byte
[]
nodeId
,
byte
[]
deviceId
)
{
if
(!
standbys
.
containsEntry
(
deviceId
,
nodeId
))
{
standbys
.
put
(
deviceId
,
nodeId
);
}
if
(
unusable
.
containsEntry
(
deviceId
,
nodeId
))
{
unusable
.
remove
(
deviceId
,
nodeId
);
}
}
//adds node to unusable and evicts it from backup pool.
private
void
evict
(
byte
[]
nodeId
,
byte
[]
deviceId
)
{
if
(!
unusable
.
containsEntry
(
deviceId
,
nodeId
))
{
unusable
.
put
(
deviceId
,
nodeId
);
}
if
(
standbys
.
containsEntry
(
deviceId
,
nodeId
))
{
standbys
.
remove
(
deviceId
,
nodeId
);
}
}
//adds or updates term information.
private
void
updateTerm
(
byte
[]
deviceId
)
{
Integer
term
=
terms
.
get
(
deviceId
);
if
(
term
==
null
)
{
terms
.
put
(
deviceId
,
INIT
);
}
else
{
terms
.
put
(
deviceId
,
++
term
);
}
}
private
class
RemoteMasterShipEventHandler
extends
RemoteEventHandler
<
DeviceId
,
NodeId
>
{
@Override
protected
void
onAdd
(
DeviceId
deviceId
,
NodeId
nodeId
)
{
//only addition indicates a change in mastership
notifyDelegate
(
new
MastershipEvent
(
MASTER_CHANGED
,
deviceId
,
nodeId
));
}
...
...
@@ -268,6 +330,7 @@ implements MastershipStore {
@Override
protected
void
onUpdate
(
DeviceId
deviceId
,
NodeId
oldNodeId
,
NodeId
nodeId
)
{
//only addition indicates a change in mastership
//notifyDelegate(new MastershipEvent(MASTER_CHANGED, deviceId, nodeId));
}
}
...
...
core/store/hz/cluster/src/test/java/org/onlab/onos/store/cluster/impl/DistributedMastershipStoreTest.java
View file @
c404770
...
...
@@ -5,7 +5,7 @@ import static org.junit.Assert.assertNull;
import
static
org
.
junit
.
Assert
.
assertTrue
;
import
static
org
.
onlab
.
onos
.
net
.
MastershipRole
.*;
import
java.util.
List
;
import
java.util.
Map
;
import
java.util.Set
;
import
java.util.concurrent.CountDownLatch
;
import
java.util.concurrent.TimeUnit
;
...
...
@@ -26,13 +26,7 @@ import org.onlab.onos.cluster.MastershipEvent.Type;
import
org.onlab.onos.cluster.MastershipStoreDelegate
;
import
org.onlab.onos.cluster.MastershipTerm
;
import
org.onlab.onos.cluster.NodeId
;
import
org.onlab.onos.net.Device
;
import
org.onlab.onos.net.DeviceId
;
import
org.onlab.onos.net.MastershipRole
;
import
org.onlab.onos.net.Port
;
import
org.onlab.onos.net.PortNumber
;
import
org.onlab.onos.net.device.DeviceListener
;
import
org.onlab.onos.net.device.DeviceService
;
import
org.onlab.onos.store.common.StoreManager
;
import
org.onlab.onos.store.common.StoreService
;
import
org.onlab.onos.store.common.TestStoreManager
;
...
...
@@ -87,7 +81,6 @@ public class DistributedMastershipStoreTest {
dms
=
new
TestDistributedMastershipStore
(
storeMgr
,
serializationMgr
);
dms
.
clusterService
=
new
TestClusterService
();
dms
.
deviceService
=
new
TestDeviceService
();
dms
.
activate
();
testStore
=
(
TestDistributedMastershipStore
)
dms
;
...
...
@@ -105,14 +98,14 @@ public class DistributedMastershipStoreTest {
@Test
public
void
getRole
()
{
assertEquals
(
"wrong role:"
,
NONE
,
dms
.
getRole
(
N1
,
DID1
));
testStore
.
put
(
DID1
,
N1
,
true
,
tru
e
,
true
);
testStore
.
put
(
DID1
,
N1
,
true
,
fals
e
,
true
);
assertEquals
(
"wrong role:"
,
MASTER
,
dms
.
getRole
(
N1
,
DID1
));
assertEquals
(
"wrong role:"
,
STANDBY
,
dms
.
getRole
(
N2
,
DID1
));
}
@Test
public
void
getMaster
()
{
assertTrue
(
"wrong store state:"
,
dms
.
rawM
asters
.
isEmpty
());
assertTrue
(
"wrong store state:"
,
dms
.
m
asters
.
isEmpty
());
testStore
.
put
(
DID1
,
N1
,
true
,
false
,
false
);
assertEquals
(
"wrong master:"
,
N1
,
dms
.
getMaster
(
DID1
));
...
...
@@ -121,7 +114,7 @@ public class DistributedMastershipStoreTest {
@Test
public
void
getDevices
()
{
assertTrue
(
"wrong store state:"
,
dms
.
rawM
asters
.
isEmpty
());
assertTrue
(
"wrong store state:"
,
dms
.
m
asters
.
isEmpty
());
testStore
.
put
(
DID1
,
N1
,
true
,
false
,
false
);
testStore
.
put
(
DID2
,
N1
,
true
,
false
,
false
);
...
...
@@ -139,20 +132,17 @@ public class DistributedMastershipStoreTest {
//if already MASTER, nothing should happen
testStore
.
put
(
DID2
,
N1
,
true
,
false
,
false
);
assertEquals
(
"wrong role for MASTER:"
,
MASTER
,
dms
.
requestRole
(
DID2
));
assertTrue
(
"wrong state for store:"
,
dms
.
backups
.
isEmpty
()
&
dms
.
rawTerms
.
isEmpty
());
//populate maps with DID1, N1 thru NONE case
assertEquals
(
"wrong role for NONE:"
,
MASTER
,
dms
.
requestRole
(
DID1
));
assertTrue
(
"wrong state for store:"
,
!
dms
.
backups
.
isEmpty
()
&
!
dms
.
rawTerms
.
isEmpty
());
assertTrue
(
"wrong state for store:"
,
!
dms
.
terms
.
isEmpty
());
assertEquals
(
"wrong term"
,
MastershipTerm
.
of
(
N1
,
0
),
dms
.
getTermFor
(
DID1
));
//CN2 now local. DID2 has N1 as MASTER so N2 is STANDBY
testStore
.
setCurrent
(
CN2
);
assertEquals
(
"wrong role for STANDBY:"
,
STANDBY
,
dms
.
requestRole
(
DID2
));
assertEquals
(
"wrong number of entries:"
,
2
,
dms
.
rawT
erms
.
size
());
assertEquals
(
"wrong number of entries:"
,
2
,
dms
.
t
erms
.
size
());
//change term and requestRole() again; should persist
testStore
.
increment
(
DID2
);
...
...
@@ -181,35 +171,42 @@ public class DistributedMastershipStoreTest {
}
@Test
public
void
unsetMaster
()
{
public
void
relinquishRole
()
{
//populate maps with DID1, N1 as MASTER thru NONE case
testStore
.
setCurrent
(
CN1
);
assertEquals
(
"wrong role for NONE:"
,
MASTER
,
dms
.
requestRole
(
DID1
));
//no backup, no new MASTER/event
assertNull
(
"wrong event:"
,
dms
.
unsetMaster
(
N1
,
DID1
));
assertNull
(
"wrong event:"
,
dms
.
relinquishRole
(
N1
,
DID1
));
dms
.
requestRole
(
DID1
);
((
TestDeviceService
)
dms
.
deviceService
).
active
.
add
(
DID1
);
//add backup CN2, get it elected MASTER by relinquishing
testStore
.
setCurrent
(
CN2
);
dms
.
requestRole
(
DID1
);
assertEquals
(
"wrong event:"
,
Type
.
MASTER_CHANGED
,
dms
.
unsetMaster
(
N1
,
DID1
).
type
());
assertEquals
(
"wrong role for NONE:"
,
STANDBY
,
dms
.
requestRole
(
DID1
)
);
assertEquals
(
"wrong event:"
,
Type
.
MASTER_CHANGED
,
dms
.
relinquishRole
(
N1
,
DID1
).
type
());
assertEquals
(
"wrong master"
,
N2
,
dms
.
getMaster
(
DID1
));
//STANDBY - nothing here, either
assertNull
(
"wrong event:"
,
dms
.
unsetMaster
(
N1
,
DID1
));
assertNull
(
"wrong event:"
,
dms
.
relinquishRole
(
N1
,
DID1
));
assertEquals
(
"wrong role for node:"
,
STANDBY
,
dms
.
getRole
(
N1
,
DID1
));
//all nodes "give up" on device, which goes back to NONE.
assertNull
(
"wrong event:"
,
dms
.
relinquishRole
(
N2
,
DID1
));
assertEquals
(
"wrong role for node:"
,
NONE
,
dms
.
getRole
(
N2
,
DID1
));
assertEquals
(
"wrong role for node:"
,
NONE
,
dms
.
getRole
(
N1
,
DID1
));
assertEquals
(
"wrong number of retired nodes"
,
2
,
dms
.
unusable
.
size
());
//bring nodes back
assertEquals
(
"wrong role for NONE:"
,
MASTER
,
dms
.
requestRole
(
DID1
));
testStore
.
setCurrent
(
CN1
);
assertEquals
(
"wrong role for NONE:"
,
STANDBY
,
dms
.
requestRole
(
DID1
));
assertEquals
(
"wrong number of backup nodes"
,
1
,
dms
.
standbys
.
size
());
//NONE - nothing happens
assertNull
(
"wrong event:"
,
dms
.
unsetMaster
(
N1
,
DID2
));
assertNull
(
"wrong event:"
,
dms
.
relinquishRole
(
N1
,
DID2
));
assertEquals
(
"wrong role for node:"
,
NONE
,
dms
.
getRole
(
N1
,
DID2
));
//for a device that turned off (not active) - status to NONE
((
TestDeviceService
)
dms
.
deviceService
).
active
.
clear
();
assertNull
(
"extraneous event:"
,
dms
.
unsetMaster
(
N2
,
DID1
));
assertEquals
(
"wrong role"
,
NONE
,
dms
.
getRole
(
N2
,
DID1
));
}
@Ignore
(
"Ignore until Delegate spec. is clear."
)
...
...
@@ -244,36 +241,55 @@ public class DistributedMastershipStoreTest {
//helper to populate master/backup structures
public
void
put
(
DeviceId
dev
,
NodeId
node
,
boolean
store
,
boolean
backup
,
boolean
term
)
{
if
(
store
)
{
dms
.
rawMasters
.
put
(
serialize
(
dev
),
serialize
(
node
));
boolean
master
,
boolean
backup
,
boolean
term
)
{
byte
[]
n
=
serialize
(
node
);
byte
[]
d
=
serialize
(
dev
);
if
(
master
)
{
dms
.
masters
.
put
(
d
,
n
);
dms
.
unusable
.
put
(
d
,
n
);
dms
.
standbys
.
remove
(
d
,
n
);
}
if
(
backup
)
{
dms
.
backups
.
put
(
serialize
(
node
),
(
byte
)
0
);
dms
.
standbys
.
put
(
d
,
n
);
dms
.
masters
.
remove
(
d
,
n
);
dms
.
unusable
.
remove
(
d
,
n
);
}
if
(
term
)
{
dms
.
rawTerms
.
put
(
serialize
(
dev
),
0
);
dms
.
terms
.
put
(
d
,
0
);
}
}
public
void
dump
()
{
System
.
out
.
println
(
"standbys"
);
for
(
Map
.
Entry
<
byte
[],
byte
[]>
e
:
standbys
.
entrySet
())
{
System
.
out
.
println
(
deserialize
(
e
.
getKey
())
+
":"
+
deserialize
(
e
.
getValue
()));
}
System
.
out
.
println
(
"unusable"
);
for
(
Map
.
Entry
<
byte
[],
byte
[]>
e
:
unusable
.
entrySet
())
{
System
.
out
.
println
(
deserialize
(
e
.
getKey
())
+
":"
+
deserialize
(
e
.
getValue
()));
}
}
//clears structures
public
void
reset
(
boolean
store
,
boolean
backup
,
boolean
term
)
{
if
(
store
)
{
dms
.
rawMasters
.
clear
();
dms
.
masters
.
clear
();
dms
.
unusable
.
clear
();
}
if
(
backup
)
{
dms
.
backup
s
.
clear
();
dms
.
standby
s
.
clear
();
}
if
(
term
)
{
dms
.
rawT
erms
.
clear
();
dms
.
t
erms
.
clear
();
}
}
//increment term for a device
public
void
increment
(
DeviceId
dev
)
{
Integer
t
=
dms
.
rawT
erms
.
get
(
serialize
(
dev
));
Integer
t
=
dms
.
t
erms
.
get
(
serialize
(
dev
));
if
(
t
!=
null
)
{
dms
.
rawT
erms
.
put
(
serialize
(
dev
),
++
t
);
dms
.
t
erms
.
put
(
serialize
(
dev
),
++
t
);
}
}
...
...
@@ -317,52 +333,4 @@ public class DistributedMastershipStoreTest {
}
private
class
TestDeviceService
implements
DeviceService
{
Set
<
DeviceId
>
active
=
Sets
.
newHashSet
();
@Override
public
int
getDeviceCount
()
{
return
0
;
}
@Override
public
Iterable
<
Device
>
getDevices
()
{
return
null
;
}
@Override
public
Device
getDevice
(
DeviceId
deviceId
)
{
return
null
;
}
@Override
public
MastershipRole
getRole
(
DeviceId
deviceId
)
{
return
null
;
}
@Override
public
List
<
Port
>
getPorts
(
DeviceId
deviceId
)
{
return
null
;
}
@Override
public
Port
getPort
(
DeviceId
deviceId
,
PortNumber
portNumber
)
{
return
null
;
}
@Override
public
boolean
isAvailable
(
DeviceId
deviceId
)
{
return
active
.
contains
(
deviceId
);
}
@Override
public
void
addListener
(
DeviceListener
listener
)
{
}
@Override
public
void
removeListener
(
DeviceListener
listener
)
{
}
}
}
...
...
core/store/trivial/src/main/java/org/onlab/onos/store/trivial/impl/SimpleMastershipStore.java
View file @
c404770
...
...
@@ -174,7 +174,7 @@ public class SimpleMastershipStore
}
@Override
public
MastershipEvent
unsetMaster
(
NodeId
nodeId
,
DeviceId
deviceId
)
{
public
MastershipEvent
setStandby
(
NodeId
nodeId
,
DeviceId
deviceId
)
{
MastershipRole
role
=
getRole
(
nodeId
,
deviceId
);
synchronized
(
this
)
{
switch
(
role
)
{
...
...
@@ -214,4 +214,9 @@ public class SimpleMastershipStore
return
backup
;
}
@Override
public
MastershipEvent
relinquishRole
(
NodeId
nodeId
,
DeviceId
deviceId
)
{
return
setStandby
(
nodeId
,
deviceId
);
}
}
...
...
core/store/trivial/src/test/java/org/onlab/onos/store/trivial/impl/SimpleMastershipStoreTest.java
View file @
c404770
...
...
@@ -129,22 +129,22 @@ public class SimpleMastershipStoreTest {
public
void
unsetMaster
()
{
//NONE - record backup but take no other action
put
(
DID1
,
N1
,
false
,
false
);
sms
.
unsetMaster
(
N1
,
DID1
);
sms
.
setStandby
(
N1
,
DID1
);
assertTrue
(
"not backed up"
,
sms
.
backups
.
contains
(
N1
));
sms
.
termMap
.
clear
();
sms
.
unsetMaster
(
N1
,
DID1
);
sms
.
setStandby
(
N1
,
DID1
);
assertTrue
(
"term not set"
,
sms
.
termMap
.
containsKey
(
DID1
));
//no backup, MASTER
put
(
DID1
,
N1
,
true
,
true
);
assertNull
(
"wrong event"
,
sms
.
unsetMaster
(
N1
,
DID1
));
assertNull
(
"wrong event"
,
sms
.
setStandby
(
N1
,
DID1
));
assertNull
(
"wrong node"
,
sms
.
masterMap
.
get
(
DID1
));
//backup, switch
sms
.
masterMap
.
clear
();
put
(
DID1
,
N1
,
true
,
true
);
put
(
DID2
,
N2
,
true
,
true
);
assertEquals
(
"wrong event"
,
MASTER_CHANGED
,
sms
.
unsetMaster
(
N1
,
DID1
).
type
());
assertEquals
(
"wrong event"
,
MASTER_CHANGED
,
sms
.
setStandby
(
N1
,
DID1
).
type
());
}
//helper to populate master/backup structures
...
...
openflow/ctl/src/main/java/org/onlab/onos/openflow/controller/impl/OFChannelHandler.java
View file @
c404770
...
...
@@ -981,11 +981,13 @@ class OFChannelHandler extends IdleStateAwareChannelHandler {
// switch was a duplicate-dpid, calling the method below would clear
// all state for the original switch (with the same dpid),
// which we obviously don't want.
log
.
info
(
"{}:removal called"
);
sw
.
removeConnectedSwitch
();
}
else
{
// A duplicate was disconnected on this ChannelHandler,
// this is the same switch reconnecting, but the original state was
// not cleaned up - XXX check liveness of original ChannelHandler
log
.
info
(
"{}:duplicate found"
);
duplicateDpidFound
=
Boolean
.
FALSE
;
}
}
else
{
...
...
openflow/ctl/src/main/java/org/onlab/onos/openflow/controller/impl/OpenFlowControllerImpl.java
View file @
c404770
...
...
@@ -307,9 +307,11 @@ public class OpenFlowControllerImpl implements OpenFlowController {
connectedSwitches
.
remove
(
dpid
);
OpenFlowSwitch
sw
=
activeMasterSwitches
.
remove
(
dpid
);
if
(
sw
==
null
)
{
log
.
warn
(
"sw was null for {}"
,
dpid
);
sw
=
activeEqualSwitches
.
remove
(
dpid
);
}
for
(
OpenFlowSwitchListener
l
:
ofSwitchListener
)
{
log
.
warn
(
"removal for {}"
,
dpid
);
l
.
switchRemoved
(
dpid
);
}
}
...
...
Please
register
or
login
to post a comment