bug 8270: Synchronize on 1) ipAddress object when create/delete ipForwarding/portForwardingRule and vpn service 2) on networkId when assignTo/removeFrom/deleteLoadBalancer

status 8270: resolved fixed
This commit is contained in:
alena 2011-02-03 18:18:42 -08:00
parent 4c7fb08b33
commit 6f55c4dd7e
29 changed files with 184 additions and 37 deletions

View File

@ -29,10 +29,15 @@ import com.cloud.user.UserContext;
* queryAsyncJobResult API command.
*/
public abstract class BaseAsyncCmd extends BaseCmd {
private Object _job = null;
public static final String ipAddressSyncObject = "ipaddress";
public static final String networkSyncObject = "network";
private AsyncJob job;
@Parameter(name="starteventid", type=CommandType.LONG)
private Long startEventId;
/**
* For async commands the API framework needs to know the owner of the object being acted upon. This method is
@ -64,12 +69,8 @@ public abstract class BaseAsyncCmd extends BaseCmd {
return response;
}
public void synchronizeCommand(String syncObjType, long syncObjId) {
_responseGenerator.synchronizeCommand(_job, syncObjType, syncObjId);
}
public void setJob(Object job) {
_job = job;
public void setJob(AsyncJob job) {
this.job = job;
}
public Long getStartEventId() {
@ -85,7 +86,7 @@ public abstract class BaseAsyncCmd extends BaseCmd {
* provide implementations of the two following methods, getInstanceId() and getInstanceType()
*
* getObjectId() should return the id of the object the async command is executing on
* getObjectType() should return a type from the AsyncJobVO.Type enumeration
* getObjectType() should return a type from the AsyncJob.Type enumeration
*/
public Long getInstanceId() {
return null;
@ -95,6 +96,18 @@ public abstract class BaseAsyncCmd extends BaseCmd {
return AsyncJob.Type.None;
}
public String getSyncObjType() {
return null;
}
public Long getSyncObjId() {
return null;
}
public AsyncJob getJob() {
return job;
}
protected long saveStartedEvent(){
return saveStartedEvent(getEventType(), "Executing job for "+getEventDescription(), getStartEventId());
}
@ -124,4 +137,6 @@ public abstract class BaseAsyncCmd extends BaseCmd {
}
return _mgr.saveCompletedEvent((userId == null) ? User.UID_SYSTEM : userId, getEntityOwnerId(), level, eventType, description, startEvent);
}
}

View File

@ -145,8 +145,6 @@ public interface ResponseGenerator {
IpForwardingRuleResponse createIpForwardingRuleResponse(PortForwardingRule fwRule);
void synchronizeCommand(Object job, String syncObjType, Long syncObjId);
User findUserById(Long userId);
UserVm findUserVmById(Long vmId);

View File

@ -99,4 +99,12 @@ public class AssignToLoadBalancerRuleCmd extends BaseAsyncCmd {
throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to assign load balancer rule");
}
}
public String getSyncObjType() {
return this.networkSyncObject;
}
public Long getSyncObjId() {
return _lbService.findById(id).getNetworkId();
}
}

View File

@ -171,5 +171,14 @@ public class AssociateIPAddrCmd extends BaseAsyncCreateCmd {
s_logger.trace(ex);
throw new ServerApiException(BaseCmd.INSUFFICIENT_CAPACITY_ERROR, ex.getMessage());
}
}
public String getSyncObjType() {
return this.networkSyncObject;
}
public Long getSyncObjId() {
return getNetworkId();
}
}

View File

@ -237,5 +237,15 @@ public class CreateIpForwardingRuleCmd extends BaseAsyncCreateCmd implements Por
throw new InvalidParameterValueException("Ip address id=" + ipAddressId + " doesn't have 1-1 Nat feature enabled");
}
}
@Override
public String getSyncObjType() {
return this.ipAddressSyncObject;
}
@Override
public Long getSyncObjId() {
return ipAddressId;
}
}

View File

@ -228,5 +228,15 @@ public class CreatePortForwardingRuleCmd extends BaseAsyncCreateCmd implements
public boolean isOneToOneNat() {
return false;
}
@Override
public String getSyncObjType() {
return this.ipAddressSyncObject;
}
@Override
public Long getSyncObjId() {
return ipAddressId;
}
}

View File

@ -150,5 +150,16 @@ public class CreateRemoteAccessVpnCmd extends BaseAsyncCreateCmd {
s_logger.warn("Exception: ", ex);
throw new ServerApiException(BaseCmd.RESOURCE_UNAVAILABLE_ERROR, ex.getMessage());
}
}
@Override
public String getSyncObjType() {
return this.ipAddressSyncObject;
}
@Override
public Long getSyncObjId() {
return publicIpId;
}
}

View File

@ -99,5 +99,15 @@ public class DeleteIpForwardingRuleCmd extends BaseAsyncCmd {
public String getEventDescription() {
return ("Deleting an ipforwarding 1:1 NAT rule id:"+id);
}
@Override
public String getSyncObjType() {
return this.ipAddressSyncObject;
}
@Override
public Long getSyncObjId() {
return _rulesService.getPortForwardigRule(id).getSourceIpAddressId();
}
}

View File

@ -89,4 +89,14 @@ public class DeleteLoadBalancerRuleCmd extends BaseAsyncCmd {
throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to delete load balancer");
}
}
@Override
public String getSyncObjType() {
return this.networkSyncObject;
}
@Override
public Long getSyncObjId() {
return _lbService.findById(id).getNetworkId();
}
}

View File

@ -90,4 +90,15 @@ public class DeletePortForwardingRuleCmd extends BaseAsyncCmd {
throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to delete port forwarding rule");
}
}
@Override
public String getSyncObjType() {
return this.ipAddressSyncObject;
}
@Override
public Long getSyncObjId() {
return _rulesService.getPortForwardigRule(id).getSourceIpAddressId();
}
}

View File

@ -77,7 +77,17 @@ public class DeleteRemoteAccessVpnCmd extends BaseAsyncCmd {
@Override
public void execute() throws ResourceUnavailableException {
_ravService.destroyRemoteAccessVpn(publicIpId, getStartEventId());
_ravService.destroyRemoteAccessVpn(publicIpId);
}
@Override
public String getSyncObjType() {
return this.ipAddressSyncObject;
}
@Override
public Long getSyncObjId() {
return publicIpId;
}
}

View File

@ -84,4 +84,15 @@ public class DisableStaticNat extends BaseAsyncCmd {
throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to disable static nat");
}
}
@Override
public String getSyncObjType() {
return this.ipAddressSyncObject;
}
@Override
public Long getSyncObjId() {
return ipAddressId;
}
}

View File

@ -99,4 +99,14 @@ public class RemoveFromLoadBalancerRuleCmd extends BaseAsyncCmd {
throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to remove instance from load balancer rule");
}
}
@Override
public String getSyncObjType() {
return this.networkSyncObject;
}
@Override
public Long getSyncObjId() {
return _lbService.findById(id).getNetworkId();
}
}

View File

@ -57,4 +57,5 @@ public interface AsyncJob {
String getSessionKey();
String getCmdOriginator();
boolean isFromPreviousSession();
SyncQueueItem getSyncSource();
}

View File

@ -0,0 +1,8 @@
package com.cloud.async;
public interface SyncQueueItem {
String getContentType();
Long getContentId();
}

View File

@ -63,5 +63,7 @@ public interface LoadBalancingRulesService {
List<? extends LoadBalancer> searchForLoadBalancers(ListLoadBalancerRulesCmd cmd);
List<LoadBalancingRule> listByNetworkId(long networkId);
LoadBalancer findById(long LoadBalancer);
}

View File

@ -61,4 +61,6 @@ public interface RulesService {
List<PortForwardingRuleTO> buildPortForwardingTOrules(List<? extends PortForwardingRule> pfRules);
PortForwardingRule getPortForwardigRule(long ruleId);
}

View File

@ -30,7 +30,7 @@ import com.cloud.network.VpnUser;
public interface RemoteAccessVpnService {
RemoteAccessVpn createRemoteAccessVpn(long vpnServerAddressId, String ipRange) throws NetworkRuleConflictException;
void destroyRemoteAccessVpn(long vpnServerAddressId, long startEventId) throws ResourceUnavailableException;
void destroyRemoteAccessVpn(long vpnServerAddressId) throws ResourceUnavailableException;
RemoteAccessVpn startRemoteAccessVpn(long vpnServerAddressId) throws ResourceUnavailableException;
VpnUser addVpnUser(long vpnOwnerId, String userName, String password);

View File

@ -333,7 +333,8 @@ public class AsyncJobVO implements AsyncJob {
public void setCmdOriginator(String cmdOriginator) {
this.cmdOriginator = cmdOriginator;
}
@Override
public SyncQueueItemVO getSyncSource() {
return syncSource;
}

View File

@ -29,7 +29,7 @@ import javax.persistence.Table;
@Entity
@Table(name="sync_queue_item")
public class SyncQueueItemVO {
public class SyncQueueItemVO implements SyncQueueItem{
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@ -69,7 +69,8 @@ public class SyncQueueItemVO {
public void setQueueId(Long queueId) {
this.queueId = queueId;
}
@Override
public String getContentType() {
return contentType;
}
@ -77,7 +78,8 @@ public class SyncQueueItemVO {
public void setContentType(String contentType) {
this.contentType = contentType;
}
@Override
public Long getContentId() {
return contentId;
}

View File

@ -30,7 +30,6 @@ import com.cloud.host.dao.HostDao;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.network.IPAddressVO;
import com.cloud.network.LoadBalancerVO;
import com.cloud.network.Network;
import com.cloud.network.Network.Capability;
import com.cloud.network.Network.Service;
import com.cloud.network.NetworkManager;
@ -88,10 +87,8 @@ import com.cloud.user.dao.UserStatisticsDao;
import com.cloud.uservm.UserVm;
import com.cloud.utils.DateUtil;
import com.cloud.utils.component.ComponentLocator;
import com.cloud.utils.net.Ip;
import com.cloud.vm.DomainRouterVO;
import com.cloud.vm.InstanceGroupVO;
import com.cloud.vm.Nic;
import com.cloud.vm.NicProfile;
import com.cloud.vm.UserVmManager;
import com.cloud.vm.UserVmVO;
@ -502,10 +499,6 @@ public class ApiDBUtils {
return _networkMgr.getNetworkProfile(networkId);
}
public static void synchronizeCommand(Object job, String syncObjType, long syncObjId) {
_asyncMgr.syncAsyncJobExecution((AsyncJobVO)job, syncObjType, syncObjId);
}
public static NetworkOfferingVO findNetworkOfferingById(long networkOfferingId) {
return _networkOfferingDao.findByIdIncludingRemoved(networkOfferingId);
}

View File

@ -29,7 +29,7 @@ import org.apache.log4j.Logger;
import com.cloud.api.BaseCmd.CommandType;
import com.cloud.async.AsyncCommandQueued;
import com.cloud.event.EventVO;
import com.cloud.async.AsyncJobManager;
import com.cloud.exception.AccountLimitException;
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.InvalidParameterValueException;
@ -49,7 +49,8 @@ import com.cloud.utils.exception.CloudRuntimeException;
public class ApiDispatcher {
private static final Logger s_logger = Logger.getLogger(ApiDispatcher.class.getName());
ComponentLocator _locator = null;
ComponentLocator _locator;
AsyncJobManager _asyncMgr;
// singleton class
private static ApiDispatcher s_instance = new ApiDispatcher();
@ -60,6 +61,7 @@ public class ApiDispatcher {
private ApiDispatcher() {
_locator = ComponentLocator.getLocator(ManagementServer.Name);
_asyncMgr = _locator.getManager(AsyncJobManager.class);
}
public void dispatchCreateCmd(BaseAsyncCreateCmd cmd, Map<String, String> params) {
@ -128,8 +130,15 @@ public class ApiDispatcher {
ctx.setAccountId(asyncCmd.getEntityOwnerId());
String startEventId = params.get("ctxStartEventId");
ctx.setStartEventId(Long.valueOf(startEventId));
//Synchronise job on the object if needed
if (asyncCmd.getJob() != null && asyncCmd.getSyncObjId() != null && asyncCmd.getSyncObjType() != null) {
_asyncMgr.syncAsyncJobExecution(asyncCmd.getJob(), asyncCmd.getSyncObjType(), asyncCmd.getSyncObjId().longValue());
}
}
cmd.execute();
} catch (Throwable t) {
if (t instanceof InvalidParameterValueException || t instanceof IllegalArgumentException) {
s_logger.info(t.getMessage());

View File

@ -1261,11 +1261,6 @@ public class ApiResponseHelper implements ResponseGenerator {
return vmResponse;
}
@Override
public void synchronizeCommand(Object job, String syncObjType, Long syncObjId) {
ApiDBUtils.synchronizeCommand(job, syncObjType, syncObjId);
}
@Override
public User findUserById(Long userId) {
return ApiDBUtils.findUserById(userId);

View File

@ -416,7 +416,7 @@ public class ApiServer implements HttpRequestHandler {
}
job.setCmd(cmdObj.getClass().getName());
job.setCmdInfo(ApiGsonHelper.getBuilder().create().toJson(params));
long jobId = _asyncMgr.submitAsyncJob(job);
if (jobId == 0L) {

View File

@ -25,7 +25,8 @@ import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.PermissionDeniedException;
import com.cloud.utils.component.Manager;
public interface AsyncJobManager extends Manager {
public interface AsyncJobManager extends Manager {
public AsyncJobExecutorContext getExecutorContext();
public AsyncJobVO getAsyncJob(long jobId);
@ -39,10 +40,11 @@ public interface AsyncJobManager extends Manager {
public void completeAsyncJob(long jobId, int jobStatus, int resultCode, Object resultObject);
public void updateAsyncJobStatus(long jobId, int processStatus, Object resultObject);
public void updateAsyncJobAttachment(long jobId, String instanceType, Long instanceId);
public void syncAsyncJobExecution(AsyncJobVO job, String syncObjType, long syncObjId);
public void releaseSyncSource(AsyncJobExecutor executor);
public void syncAsyncJobExecution(AsyncJob job, String syncObjType, long syncObjId);
/**
* Queries for the status or final result of an async job.
* @param cmd the command that specifies the job id

View File

@ -233,7 +233,7 @@ public class AsyncJobManagerImpl implements AsyncJobManager, ClusterManagerListe
}
@Override
public void syncAsyncJobExecution(AsyncJobVO job, String syncObjType, long syncObjId) {
public void syncAsyncJobExecution(AsyncJob job, String syncObjType, long syncObjId) {
// This method is re-entrant. If an API developer wants to synchronized on an object, e.g. the router,
// when executing business logic, they will call this method (actually a method in BaseAsyncCmd that calls this).
// This method will get called every time their business logic executes. The first time it exectues for a job

View File

@ -1378,5 +1378,10 @@ public class LoadBalancingRulesManagerImpl implements LoadBalancingRulesManager,
}
return lbRules;
}
@Override
public LoadBalancerVO findById(long lbId) {
return _lbDao.findById(lbId);
}
}

View File

@ -700,5 +700,9 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager {
return null;
}
}
@Override
public PortForwardingRule getPortForwardigRule(long ruleId) {
return _forwardingDao.findById(ruleId);
}
}

View File

@ -192,7 +192,7 @@ public class RemoteAccessVpnManagerImpl implements RemoteAccessVpnService, Manag
}
@Override @DB
public void destroyRemoteAccessVpn(long ipId, long startEventId) throws ResourceUnavailableException {
public void destroyRemoteAccessVpn(long ipId) throws ResourceUnavailableException {
Account caller = UserContext.current().getCaller();
RemoteAccessVpnVO vpn = _remoteAccessVpnDao.findById(ipId);