adds a state machine and state listener to Network objects

This commit is contained in:
Murali Reddy 2012-09-16 21:03:59 +05:30
parent bfd6c67a48
commit b89f7c61b3
6 changed files with 111 additions and 51 deletions

View File

@ -25,13 +25,13 @@ import com.cloud.acl.ControlledEntity;
import com.cloud.network.Networks.BroadcastDomainType;
import com.cloud.network.Networks.Mode;
import com.cloud.network.Networks.TrafficType;
import com.cloud.utils.fsm.FiniteState;
import com.cloud.utils.fsm.StateMachine;
import com.cloud.utils.fsm.StateMachine2;
import com.cloud.utils.fsm.StateObject;
/**
* owned by an account.
*/
public interface Network extends ControlledEntity {
public interface Network extends ControlledEntity, StateObject<Network.State> {
public enum GuestType {
Shared,
@ -197,7 +197,7 @@ public interface Network extends ControlledEntity {
OperationFailed;
}
enum State implements FiniteState<State, Event> {
public enum State {
Allocated("Indicates the network configuration is in allocated but not setup"),
Setup("Indicates the network configuration is setup"),
Implementing("Indicates the network configuration is being implemented"),
@ -205,39 +205,7 @@ public interface Network extends ControlledEntity {
Shutdown("Indicates the network configuration is being destroyed"),
Destroy("Indicates that the network is destroyed");
@Override
public StateMachine<State, Event> getStateMachine() {
return s_fsm;
}
@Override
public State getNextState(Event event) {
return s_fsm.getNextState(this, event);
}
@Override
public List<State> getFromStates(Event event) {
return s_fsm.getFromStates(this, event);
}
@Override
public Set<Event> getPossibleEvents() {
return s_fsm.getPossibleEvents(this);
}
String _description;
@Override
public String getDescription() {
return _description;
}
private State(String description) {
_description = description;
}
private static StateMachine<State, Event> s_fsm = new StateMachine<State, Event>();
protected static final StateMachine2<State, Network.Event, Network> s_fsm = new StateMachine2<State, Network.Event, Network>();
static {
s_fsm.addTransition(State.Allocated, Event.ImplementNetwork, State.Implementing);
s_fsm.addTransition(State.Implementing, Event.OperationSucceeded, State.Implemented);
@ -246,6 +214,15 @@ public interface Network extends ControlledEntity {
s_fsm.addTransition(State.Shutdown, Event.OperationSucceeded, State.Allocated);
s_fsm.addTransition(State.Shutdown, Event.OperationFailed, State.Implemented);
}
public static StateMachine2<State, Network.Event, Network> getStateMachine() {
return s_fsm;
}
String _description;
private State(String description) {
_description = description;
}
}
/**

View File

@ -142,6 +142,7 @@ import com.cloud.network.element.StaticNatServiceProvider;
import com.cloud.network.element.UserDataServiceProvider;
import com.cloud.network.element.VirtualRouterElement;
import com.cloud.network.element.VpcVirtualRouterElement;
import com.cloud.network.Network.Event;
import com.cloud.network.guru.NetworkGuru;
import com.cloud.network.lb.LoadBalancingRule;
import com.cloud.network.lb.LoadBalancingRule.LbDestination;
@ -200,6 +201,8 @@ import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.SearchCriteria.Op;
import com.cloud.utils.db.Transaction;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.fsm.NoTransitionException;
import com.cloud.utils.fsm.StateMachine2;
import com.cloud.utils.net.Ip;
import com.cloud.utils.net.NetUtils;
import com.cloud.vm.Nic;
@ -322,6 +325,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
@Inject
ResourceTagDao _resourceTagDao;
protected StateMachine2<Network.State, Network.Event, Network> _stateMachine;
private final HashMap<String, NetworkOfferingVO> _systemNetworks = new HashMap<String, NetworkOfferingVO>(5);
private static Long _privateOfferingId = null;
@ -1503,6 +1507,8 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
_agentMgr.registerForHostEvents(this, true, false, true);
Network.State.getStateMachine().registerListener(new NetworkStateListener(_usageEventDao, _networksDao));
s_logger.info("Network Manager is configured.");
return true;
@ -1553,6 +1559,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
}
protected NetworkManagerImpl() {
setStateMachine();
}
@Override
@ -1949,9 +1956,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
NetworkOfferingVO offering = _networkOfferingDao.findById(network.getNetworkOfferingId());
network.setReservationId(context.getReservationId());
network.setState(Network.State.Implementing);
_networksDao.update(networkId, network);
stateTransitTo(network, Event.ImplementNetwork);
Network result = guru.implement(network, offering, dest, context);
network.setCidr(result.getCidr());
@ -1964,16 +1969,23 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
// implement network elements and re-apply all the network rules
implementNetworkElementsAndResources(dest, context, network, offering);
network.setState(Network.State.Implemented);
stateTransitTo(network,Event.OperationSucceeded);
network.setRestartRequired(false);
_networksDao.update(network.getId(), network);
implemented.set(guru, network);
return implemented;
} catch (NoTransitionException e) {
s_logger.error(e.getMessage());
return null;
} finally {
if (implemented.first() == null) {
s_logger.debug("Cleaning up because we're unable to implement the network " + network);
network.setState(Network.State.Shutdown);
_networksDao.update(networkId, network);
try {
stateTransitTo(network,Event.OperationFailed);
} catch (NoTransitionException e) {
s_logger.error(e.getMessage());
}
shutdownNetwork(networkId, context, false);
}
@ -3401,8 +3413,11 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
return false;
}
network.setState(Network.State.Shutdown);
_networksDao.update(network.getId(), network);
try {
stateTransitTo(network, Event.DestroyNetwork);
} catch (NoTransitionException e) {
s_logger.debug(e.getMessage());
}
boolean success = shutdownNetworkElementsAndResources(context, cleanupElements, network);
@ -3418,14 +3433,22 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
applyProfileToNetwork(network, profile);
network.setState(Network.State.Allocated);
try {
stateTransitTo(network, Event.OperationSucceeded);
} catch (NoTransitionException e) {
s_logger.debug(e.getMessage());
}
network.setRestartRequired(false);
_networksDao.update(network.getId(), network);
_networksDao.clearCheckForGc(networkId);
result = true;
} else {
network.setState(Network.State.Implemented);
_networksDao.update(network.getId(), network);
try {
stateTransitTo(network, Event.OperationFailed);
} catch (NoTransitionException e) {
s_logger.debug(e.getMessage());
}
result = false;
}
txn.commit();
@ -3584,8 +3607,11 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
s_logger.warn("Failed to delete network " + network + "; was unable to cleanup corresponding ip ranges");
} else {
// commit transaction only when ips and vlans for the network are released successfully
network.setState(Network.State.Destroy);
_networksDao.update(network.getId(), network);
try {
stateTransitTo(network, Event.DestroyNetwork);
} catch (NoTransitionException e) {
s_logger.debug(e.getMessage());
}
_networksDao.remove(network.getId());
txn.commit();
}
@ -7331,4 +7357,11 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
return _networkLockTimeout;
}
protected boolean stateTransitTo(NetworkVO network, Network.Event e) throws NoTransitionException {
return _stateMachine.transitTo(network, e, null, _networksDao);
}
private void setStateMachine() {
_stateMachine = Network.State.getStateMachine();
}
}

View File

@ -0,0 +1,31 @@
package com.cloud.network;
import com.cloud.event.dao.UsageEventDao;
import com.cloud.network.Network.Event;
import com.cloud.network.Network.State;
import com.cloud.network.dao.NetworkDao;
import com.cloud.utils.fsm.StateListener;
public class NetworkStateListener implements StateListener<State, Event, Network> {
protected UsageEventDao _usageEventDao;
protected NetworkDao _networkDao;
public NetworkStateListener(UsageEventDao usageEventDao, NetworkDao networkDao) {
this._usageEventDao = usageEventDao;
this._networkDao = networkDao;
}
@Override
public boolean preStateTransitionEvent(State oldState, Event event, State newState, Network vo, boolean status, Object opaque) {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean postStateTransitionEvent(State oldState, Event event, State newState, Network vo, boolean status, Object opaque) {
// TODO Auto-generated method stub
return false;
}
}

View File

@ -247,6 +247,7 @@ public class NetworkVO implements Network, Identity {
return state;
}
// don't use this directly when possible, use Network state machine instead
public void setState(State state) {
this.state = state;
}

View File

@ -24,10 +24,12 @@ import com.cloud.network.Network.GuestType;
import com.cloud.network.NetworkAccountVO;
import com.cloud.network.NetworkVO;
import com.cloud.network.Networks.TrafficType;
import com.cloud.network.Network.State;
import com.cloud.utils.db.GenericDao;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.fsm.StateDao;
public interface NetworkDao extends GenericDao<NetworkVO, Long> {
public interface NetworkDao extends GenericDao<NetworkVO, Long> , StateDao<State, Network.Event, Network> {
List<NetworkVO> listByOwner(long ownerId);

View File

@ -25,9 +25,11 @@ import javax.persistence.TableGenerator;
import com.cloud.acl.ControlledEntity.ACLType;
import com.cloud.network.Network;
import com.cloud.network.Network.Event;
import com.cloud.network.Network.GuestType;
import com.cloud.network.Network.Provider;
import com.cloud.network.Network.Service;
import com.cloud.network.Network.State;
import com.cloud.network.NetworkAccountDaoImpl;
import com.cloud.network.NetworkAccountVO;
import com.cloud.network.NetworkDomainVO;
@ -551,4 +553,18 @@ public class NetworkDaoImpl extends GenericDaoBase<NetworkVO, Long> implements N
sc.setParameters("vpcId", vpcId);
return customSearch(sc, null).get(0);
}
@Override
public boolean updateState(State currentState, Event event, State nextState, Network vo, Object data) {
// TODO: ensure this update is correct
Transaction txn = Transaction.currentTxn();
txn.start();
NetworkVO networkVo = (NetworkVO) vo;
networkVo.setState(nextState);
super.update(networkVo.getId(), networkVo);
txn.commit();
return true;
}
}