bug 6745: Using UUID instead of integers - for Async Jobs

This commit is contained in:
Kelven Yang 2011-10-28 16:20:46 -07:00
parent 6f14bdc361
commit 8d8775b533
19 changed files with 2981 additions and 2840 deletions

View File

@ -56,7 +56,8 @@ public abstract class BaseAsyncCmd extends BaseCmd {
public ResponseObject getResponse(long jobId) {
AsyncJobResponse response = new AsyncJobResponse();
response.setId(jobId);
response.setId(_identityService.getIdentityUuid("async_job", String.valueOf(jobId)));
response.setResponseName(getCommandName());
return response;
}
@ -129,6 +130,4 @@ public abstract class BaseAsyncCmd extends BaseCmd {
}
return _mgr.saveCompletedEvent((userId == null) ? User.UID_SYSTEM : userId, getEntityOwnerId(), level, eventType, description, startEvent);
}
}

View File

@ -124,7 +124,8 @@ public abstract class BaseCmd {
public static FirewallService _firewallService;
public static DomainService _domainService;
public static ResourceLimitService _resourceLimitService;
public static IdentityService _identityService;
static void setComponents(ResponseGenerator generator) {
ComponentLocator locator = ComponentLocator.getLocator(ManagementService.Name);
_mgr = (ManagementService)ComponentLocator.getComponent(ManagementService.Name);
@ -149,6 +150,7 @@ public abstract class BaseCmd {
_firewallService = locator.getManager(FirewallService.class);
_domainService = locator.getManager(DomainService.class);
_resourceLimitService = locator.getManager(ResourceLimitService.class);
_identityService = locator.getManager(IdentityService.class);
}
public abstract void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException;

View File

@ -1,5 +1,5 @@
/**
* Copyright (C) 2011 Citrix Systems, Inc. All rights reserved.
* Copyright (C) 2010 Cloud.com, Inc. All rights reserved.
*
* This software is licensed under the GNU General Public License v3 or later.
*
@ -15,13 +15,33 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.cloud.Identity.dao;
package com.cloud.api;
import javax.persistence.Entity;
public class IdentityProxy {
private String _tableName;
private Long _value;
/**
* This is a dummy class to fit for CloudStack Dao framework
*/
@Entity
public class IdentityVO {
public IdentityProxy() {
}
public IdentityProxy(String tableName) {
_tableName = tableName;
}
public String getTableName() {
return _tableName;
}
public void setTableName(String tableName) {
_tableName = tableName;
}
public Long getValue() {
return _value;
}
public void setValue(Long value) {
_value = value;
}
}

View File

@ -1,5 +1,5 @@
/**
* Copyright (C) 2011 Citrix Systems, Inc. All rights reserved.
* Copyright (C) 2010 Cloud.com, Inc. All rights reserved.
*
* This software is licensed under the GNU General Public License v3 or later.
*
@ -15,12 +15,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.cloud.api;
package com.cloud.Identity.dao;
import com.cloud.api.IdentityMapper;
import com.cloud.utils.db.GenericDao;
public interface IdentityDao extends GenericDao<IdentityVO, Long> {
public interface IdentityService {
Long getIdentityId(IdentityMapper mapper, String identityString);
String getIdentityUuid(String tableName, String identityString);
}

View File

@ -22,6 +22,7 @@ import org.apache.log4j.Logger;
import com.cloud.api.ApiConstants;
import com.cloud.api.BaseCmd;
import com.cloud.api.IdentityMapper;
import com.cloud.api.Implementation;
import com.cloud.api.Parameter;
import com.cloud.api.response.AsyncJobResponse;
@ -37,6 +38,7 @@ public class QueryAsyncJobResultCmd extends BaseCmd {
//////////////// API parameters /////////////////////
/////////////////////////////////////////////////////
@IdentityMapper(entityTableName="async_job")
@Parameter(name=ApiConstants.JOB_ID, type=CommandType.LONG, required=true, description="the ID of the asychronous job")
private Long id;

View File

@ -20,13 +20,14 @@ package com.cloud.api.response;
import java.util.Date;
import com.cloud.api.ApiConstants;
import com.cloud.api.IdentityProxy;
import com.cloud.api.ResponseObject;
import com.cloud.serializer.Param;
import com.google.gson.annotations.SerializedName;
public class AsyncJobResponse extends BaseResponse {
@SerializedName(ApiConstants.JOB_ID) @Param(description="async job ID")
private Long id;
private String id;
@SerializedName("accountid") @Param(description="the account that executed the async command")
private Long accountId;
@ -56,16 +57,17 @@ public class AsyncJobResponse extends BaseResponse {
private String jobInstanceType;
@SerializedName("jobinstanceid") @Param(description="the unique ID of the instance/entity object related to the job")
private Long jobInstanceId;
// private Long jobInstanceId;
IdentityProxy jobInstanceIdProxy = new IdentityProxy();
@SerializedName(ApiConstants.CREATED) @Param(description=" the created date of the job")
private Date created;
public Long getId() {
public String getId() {
return id;
}
public void setId(Long id) {
public void setId(String id) {
this.id = id;
}
@ -139,14 +141,26 @@ public class AsyncJobResponse extends BaseResponse {
public void setJobInstanceType(String jobInstanceType) {
this.jobInstanceType = jobInstanceType;
if(jobInstanceType != null) {
if(jobInstanceType.equalsIgnoreCase("volume")) {
this.jobInstanceIdProxy.setTableName("volumes");
} else if(jobInstanceType.equalsIgnoreCase("template")) {
this.jobInstanceIdProxy.setTableName("vm_template");
} else if(jobInstanceType.equalsIgnoreCase("iso")) {
this.jobInstanceIdProxy.setTableName("vm_template");
} else {
// TODO : when we hit here, we need to add instanceType -> UUID entity table mapping
assert(false);
}
}
}
public Long getJobInstanceId() {
return jobInstanceId;
return jobInstanceIdProxy.getValue();
}
public void setJobInstanceId(Long jobInstanceId) {
this.jobInstanceId = jobInstanceId;
this.jobInstanceIdProxy.setValue(jobInstanceId);
}
public Date getCreated() {

View File

@ -19,7 +19,9 @@ package com.cloud.async;
import java.util.Date;
public interface AsyncJob {
import com.cloud.api.Identity;
public interface AsyncJob extends Identity{
public enum Type {
None,
VirtualMachine,

View File

@ -19,6 +19,7 @@
package com.cloud.async;
import java.util.Date;
import java.util.UUID;
import javax.persistence.Column;
import javax.persistence.Entity;
@ -109,7 +110,10 @@ public class AsyncJobVO implements AsyncJob {
private Date lastPolled;
@Column(name=GenericDao.REMOVED_COLUMN)
private Date removed;
private Date removed;
@Column(name="uuid")
private String uuid;
@Transient
private SyncQueueItemVO syncSource = null;
@ -118,6 +122,7 @@ public class AsyncJobVO implements AsyncJob {
private boolean fromPreviousSession = false;
public AsyncJobVO() {
this.uuid = UUID.randomUUID().toString();
}
public AsyncJobVO(long userId, long accountId, String cmd, String cmdInfo) {
@ -125,7 +130,8 @@ public class AsyncJobVO implements AsyncJob {
this.accountId = accountId;
this.cmd = cmd;
this.cmdInfo = cmdInfo;
callbackType = CALLBACK_POLLING;
this.callbackType = CALLBACK_POLLING;
this.uuid = UUID.randomUUID().toString();
}
public AsyncJobVO(long userId, long accountId, String cmd, String cmdInfo,
@ -134,6 +140,7 @@ public class AsyncJobVO implements AsyncJob {
this(userId, accountId, cmd, cmdInfo);
this.callbackType = callbackType;
this.callbackAddress = callbackAddress;
this.uuid = UUID.randomUUID().toString();
}
@Override
@ -352,6 +359,15 @@ public class AsyncJobVO implements AsyncJob {
this.fromPreviousSession = fromPreviousSession;
}
@Override
public String getUuid() {
return this.uuid;
}
public void setUuid(String uuid) {
this.uuid = uuid;
}
@Override
public String toString() {
StringBuffer sb = new StringBuffer();

View File

@ -1,66 +0,0 @@
/**
* Copyright (C) 2010 Cloud.com, Inc. All rights reserved.
*
* This software is licensed under the GNU General Public License v3 or later.
*
* It is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.cloud.Identity.dao;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import javax.ejb.Local;
import org.apache.log4j.Logger;
import com.cloud.api.IdentityMapper;
import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.db.Transaction;
@Local(value={IdentityDao.class})
public class IdentityDaoImpl extends GenericDaoBase<IdentityVO, Long> implements IdentityDao {
private static final Logger s_logger = Logger.getLogger(IdentityDaoImpl.class);
public Long getIdentityId(IdentityMapper mapper, String identityString) {
assert(mapper.entityTableName() != null);
assert(identityString != null);
PreparedStatement pstmt = null;
Transaction txn = Transaction.currentTxn();;
try {
pstmt = txn.prepareAutoCloseStatement(
String.format("SELECT id FROM %s WHERE id=? OR uuid=?", mapper.entityTableName()));
long id = 0;
try {
id = Long.parseLong(identityString);
} catch(NumberFormatException e) {
// this could happen when it is a uuid string, so catch and ignore it
}
pstmt.setLong(1, id);
pstmt.setString(2, identityString);
ResultSet rs = pstmt.executeQuery();
if(rs.next()) {
return rs.getLong(1);
}
} catch (SQLException e) {
s_logger.error("Unexpected exception ", e);
}
return null;
}
}

View File

@ -30,8 +30,6 @@ import java.util.regex.Matcher;
import org.apache.log4j.Logger;
import com.cloud.Identity.dao.IdentityDao;
import com.cloud.Identity.dao.IdentityDaoImpl;
import com.cloud.api.BaseCmd.CommandType;
import com.cloud.api.commands.ListEventsCmd;
import com.cloud.async.AsyncCommandQueued;
@ -42,6 +40,8 @@ import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.PermissionDeniedException;
import com.cloud.exception.ResourceAllocationException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.identity.dao.IdentityDao;
import com.cloud.identity.dao.IdentityDaoImpl;
import com.cloud.server.ManagementServer;
import com.cloud.user.Account;
import com.cloud.user.UserContext;

View File

@ -25,7 +25,8 @@ public class ApiGsonHelper {
static {
s_gBuilder = new GsonBuilder().setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
s_gBuilder.setVersion(1.3);
s_gBuilder.registerTypeAdapter(ResponseObject.class, new ResponseObjectTypeAdapter());
s_gBuilder.registerTypeAdapter(ResponseObject.class, new ResponseObjectTypeAdapter());
s_gBuilder.registerTypeAdapter(IdentityProxy.class, new IdentityTypeAdapter());
}
public static GsonBuilder getBuilder() {

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,57 @@
/**
* Copyright (C) 2010 Cloud.com, Inc. All rights reserved.
*
* This software is licensed under the GNU General Public License v3 or later.
*
* It is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.cloud.api;
import java.lang.reflect.Type;
import com.cloud.identity.dao.IdentityDao;
import com.cloud.identity.dao.IdentityDaoImpl;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
public class IdentityTypeAdapter implements JsonSerializer<IdentityProxy>, JsonDeserializer<IdentityProxy> {
@Override
public JsonElement serialize(IdentityProxy src, Type srcType, JsonSerializationContext context) {
assert(src != null);
assert(src.getTableName() != null);
if(src.getValue() == null)
return null;
IdentityDao identityDao = new IdentityDaoImpl();
if(src.getValue() == null)
return context.serialize(null);
return new JsonPrimitive(identityDao.getIdentityUuid(src.getTableName(), String.valueOf(src.getValue())));
}
@Override
public IdentityProxy deserialize(JsonElement json, Type type,
JsonDeserializationContext context) throws JsonParseException {
// this is a place holder implementation to guard our assumption - IdentityProxy is only used
// on one-direction
assert(false);
return null;
}
}

View File

@ -330,7 +330,8 @@ public class AsyncJobManagerImpl implements AsyncJobManager, ClusterManagerListe
jobResult.setJobStatus(job.getStatus());
jobResult.setProcessStatus(job.getProcessStatus());
jobResult.setResult(job.getResult());
jobResult.setResultCode(job.getResultCode());
jobResult.setResultCode(job.getResultCode());
jobResult.setUuid(job.getUuid());
if(job.getStatus() == AsyncJobResult.STATUS_SUCCEEDED ||
job.getStatus() == AsyncJobResult.STATUS_FAILED) {

View File

@ -30,7 +30,8 @@ public class AsyncJobResult {
private int jobStatus;
private int processStatus;
private int resultCode;
private String result;
private String result;
private String uuid;
public AsyncJobResult(long jobId) {
this.jobId = jobId;
@ -54,6 +55,14 @@ public class AsyncJobResult {
public void setJobId(long jobId) {
this.jobId = jobId;
}
public String getUuid() {
return this.uuid;
}
public void setUuid(String uuid) {
this.uuid = uuid;
}
public int getJobStatus() {

View File

@ -22,7 +22,6 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.cloud.Identity.dao.IdentityDaoImpl;
import com.cloud.agent.manager.ClusteredAgentManagerImpl;
import com.cloud.alert.AlertManagerImpl;
import com.cloud.alert.dao.AlertDaoImpl;
@ -66,6 +65,8 @@ import com.cloud.host.dao.HostDetailsDaoImpl;
import com.cloud.host.dao.HostTagsDaoImpl;
import com.cloud.hypervisor.HypervisorGuruManagerImpl;
import com.cloud.hypervisor.dao.HypervisorCapabilitiesDaoImpl;
import com.cloud.identity.IdentityServiceImpl;
import com.cloud.identity.dao.IdentityDaoImpl;
import com.cloud.keystore.KeystoreDaoImpl;
import com.cloud.keystore.KeystoreManagerImpl;
import com.cloud.maint.UpgradeManagerImpl;
@ -332,6 +333,7 @@ public class DefaultComponentLibrary extends ComponentLibraryBase implements Com
addManager("HypervisorGuruManager", HypervisorGuruManagerImpl.class);
addManager("ClusterFenceManager", ClusterFenceManagerImpl.class);
addManager("ResourceManager", ResourceManagerImpl.class);
addManager("IdentityManager", IdentityServiceImpl.class);
addManager("OCFS2Manager", OCFS2ManagerImpl.class);
addManager("FirewallManager", FirewallManagerImpl.class);

View File

@ -0,0 +1,67 @@
/**
* Copyright (C) 2010 Cloud.com, Inc. All rights reserved.
*
* This software is licensed under the GNU General Public License v3 or later.
*
* It is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.cloud.identity;
import java.util.Map;
import javax.ejb.Local;
import javax.naming.ConfigurationException;
import com.cloud.api.IdentityMapper;
import com.cloud.api.IdentityService;
import com.cloud.identity.dao.IdentityDao;
import com.cloud.utils.component.Inject;
import com.cloud.utils.component.Manager;
@Local(value = { IdentityService.class })
public class IdentityServiceImpl implements Manager, IdentityService {
private String _name;
@Inject private IdentityDao _identityDao;
public Long getIdentityId(IdentityMapper mapper, String identityString) {
return _identityDao.getIdentityId(mapper, identityString);
}
public String getIdentityUuid(String tableName, String identityString) {
return _identityDao.getIdentityUuid(tableName, identityString);
}
@Override
public boolean configure(String name, Map<String, Object> params)
throws ConfigurationException {
_name = name;
return true;
}
@Override
public String getName() {
return _name;
}
@Override
public boolean start() {
return true;
}
@Override
public boolean stop() {
return true;
}
}

View File

@ -1161,6 +1161,7 @@ CREATE TABLE `cloud`.`async_job` (
`last_updated` datetime COMMENT 'date created',
`last_polled` datetime COMMENT 'date polled',
`removed` datetime COMMENT 'date removed',
`uuid` varchar(255),
PRIMARY KEY (`id`),
INDEX `i_async_job__removed`(`removed`),
INDEX `i_async__user_id`(`user_id`),
@ -1169,7 +1170,8 @@ CREATE TABLE `cloud`.`async_job` (
INDEX `i_async__job_cmd`(`job_cmd`),
INDEX `i_async__created`(`created`),
INDEX `i_async__last_updated`(`last_updated`),
INDEX `i_async__last_poll`(`last_polled`)
INDEX `i_async__last_poll`(`last_polled`),
CONSTRAINT `uc_async__uuid` UNIQUE (`uuid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `cloud`.`sync_queue` (

View File

@ -119,3 +119,6 @@ ALTER TABLE `cloud`.`user_statistics` ADD COLUMN `agg_bytes_received` bigint uns
ALTER TABLE `cloud`.`user_statistics` ADD COLUMN `agg_bytes_sent` bigint unsigned NOT NULL default '0';
ALTER TABLE `cloud`.`vm_instance` ADD COLUMN `uuid` varchar(255);
ALTER TABLE `cloud`.`vm_instance` ADD CONSTRAINT `uc_vm_instance_uuid` UNIQUE (`uuid`);
ALTER TABLE `cloud`.`async_job` ADD COLUMN `uuid` varchar(255);
ALTER TABLE `cloud`.`async_job` ADD CONSTRAINT `uc_async__uuid` UNIQUE (`uuid`);