From b89f7c61b3fc67f3841d352d672dd4fb1823642f Mon Sep 17 00:00:00 2001 From: Murali Reddy Date: Sun, 16 Sep 2012 21:03:59 +0530 Subject: [PATCH] adds a state machine and state listener to Network objects --- api/src/com/cloud/network/Network.java | 51 +++++----------- .../com/cloud/network/NetworkManagerImpl.java | 59 +++++++++++++++---- .../cloud/network/NetworkStateListener.java | 31 ++++++++++ server/src/com/cloud/network/NetworkVO.java | 1 + .../src/com/cloud/network/dao/NetworkDao.java | 4 +- .../com/cloud/network/dao/NetworkDaoImpl.java | 16 +++++ 6 files changed, 111 insertions(+), 51 deletions(-) create mode 100644 server/src/com/cloud/network/NetworkStateListener.java diff --git a/api/src/com/cloud/network/Network.java b/api/src/com/cloud/network/Network.java index 75d94ee163f..d220032b802 100644 --- a/api/src/com/cloud/network/Network.java +++ b/api/src/com/cloud/network/Network.java @@ -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 { public enum GuestType { Shared, @@ -197,7 +197,7 @@ public interface Network extends ControlledEntity { OperationFailed; } - enum State implements FiniteState { + 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 getStateMachine() { - return s_fsm; - } - - @Override - public State getNextState(Event event) { - return s_fsm.getNextState(this, event); - } - - @Override - public List getFromStates(Event event) { - return s_fsm.getFromStates(this, event); - } - - @Override - public Set getPossibleEvents() { - return s_fsm.getPossibleEvents(this); - } - - String _description; - - @Override - public String getDescription() { - return _description; - } - - private State(String description) { - _description = description; - } - - private static StateMachine s_fsm = new StateMachine(); + protected static final StateMachine2 s_fsm = new StateMachine2(); 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 getStateMachine() { + return s_fsm; + } + + String _description; + private State(String description) { + _description = description; + } } /** diff --git a/server/src/com/cloud/network/NetworkManagerImpl.java b/server/src/com/cloud/network/NetworkManagerImpl.java index 292a25987ba..08b08934ff2 100755 --- a/server/src/com/cloud/network/NetworkManagerImpl.java +++ b/server/src/com/cloud/network/NetworkManagerImpl.java @@ -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 _stateMachine; private final HashMap _systemNetworks = new HashMap(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(); + } } diff --git a/server/src/com/cloud/network/NetworkStateListener.java b/server/src/com/cloud/network/NetworkStateListener.java new file mode 100644 index 00000000000..fdabeb0afcb --- /dev/null +++ b/server/src/com/cloud/network/NetworkStateListener.java @@ -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 { + + 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; + } + +} diff --git a/server/src/com/cloud/network/NetworkVO.java b/server/src/com/cloud/network/NetworkVO.java index 39dd66e77b0..7108701b87c 100644 --- a/server/src/com/cloud/network/NetworkVO.java +++ b/server/src/com/cloud/network/NetworkVO.java @@ -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; } diff --git a/server/src/com/cloud/network/dao/NetworkDao.java b/server/src/com/cloud/network/dao/NetworkDao.java index a2e37b7b33b..396650b1fff 100644 --- a/server/src/com/cloud/network/dao/NetworkDao.java +++ b/server/src/com/cloud/network/dao/NetworkDao.java @@ -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 { +public interface NetworkDao extends GenericDao , StateDao { List listByOwner(long ownerId); diff --git a/server/src/com/cloud/network/dao/NetworkDaoImpl.java b/server/src/com/cloud/network/dao/NetworkDaoImpl.java index cbfec895b32..b3d3f71151a 100644 --- a/server/src/com/cloud/network/dao/NetworkDaoImpl.java +++ b/server/src/com/cloud/network/dao/NetworkDaoImpl.java @@ -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 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; + } }