mirror of https://github.com/apache/cloudstack.git
wip
Signed-off-by: Abhishek Kumar <abhishek.mrt22@gmail.com>
This commit is contained in:
parent
fba7c634cb
commit
a89f872b4f
|
|
@ -21,8 +21,11 @@ import java.util.Map;
|
|||
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
import org.apache.cloudstack.context.CallContext;
|
||||
|
||||
import com.cloud.domain.Domain;
|
||||
import com.cloud.exception.CloudAuthenticationException;
|
||||
import com.cloud.user.Account;
|
||||
import com.cloud.user.UserAccount;
|
||||
|
||||
public interface ApiServerService {
|
||||
|
|
@ -52,4 +55,20 @@ public interface ApiServerService {
|
|||
String getDomainId(Map<String, Object[]> params);
|
||||
|
||||
boolean isPostRequestsAndTimestampsEnforced();
|
||||
|
||||
AsyncCmdResult processAsyncCmd(BaseAsyncCmd cmdObj, Map<String, String> params, CallContext ctx, Long callerUserId, Account caller) throws Exception;
|
||||
|
||||
class AsyncCmdResult {
|
||||
public final Long objectId;
|
||||
public final String objectUuid;
|
||||
public final BaseAsyncCmd asyncCmd;
|
||||
public final long jobId;
|
||||
|
||||
public AsyncCmdResult(Long objectId, String objectUuid, BaseAsyncCmd asyncCmd, long jobId) {
|
||||
this.objectId = objectId;
|
||||
this.objectUuid = objectUuid;
|
||||
this.asyncCmd = asyncCmd;
|
||||
this.jobId = jobId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ package org.apache.cloudstack.veeam.adapter;
|
|||
import java.util.Arrays;
|
||||
import java.util.Base64;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
|
@ -33,6 +34,7 @@ import org.apache.cloudstack.acl.RoleService;
|
|||
import org.apache.cloudstack.acl.RoleType;
|
||||
import org.apache.cloudstack.acl.Rule;
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.api.ApiServerService;
|
||||
import org.apache.cloudstack.api.BaseCmd;
|
||||
import org.apache.cloudstack.api.command.admin.vm.DeployVMCmdByAdmin;
|
||||
import org.apache.cloudstack.api.command.user.job.QueryAsyncJobResultCmd;
|
||||
|
|
@ -90,12 +92,14 @@ import org.apache.commons.collections.CollectionUtils;
|
|||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import com.cloud.api.query.dao.AsyncJobJoinDao;
|
||||
import com.cloud.api.query.dao.DataCenterJoinDao;
|
||||
import com.cloud.api.query.dao.HostJoinDao;
|
||||
import com.cloud.api.query.dao.ImageStoreJoinDao;
|
||||
import com.cloud.api.query.dao.StoragePoolJoinDao;
|
||||
import com.cloud.api.query.dao.UserVmJoinDao;
|
||||
import com.cloud.api.query.dao.VolumeJoinDao;
|
||||
import com.cloud.api.query.vo.AsyncJobJoinVO;
|
||||
import com.cloud.api.query.vo.DataCenterJoinVO;
|
||||
import com.cloud.api.query.vo.HostJoinVO;
|
||||
import com.cloud.api.query.vo.ImageStoreJoinVO;
|
||||
|
|
@ -108,7 +112,6 @@ import com.cloud.dc.dao.ClusterDao;
|
|||
import com.cloud.dc.dao.DataCenterDao;
|
||||
import com.cloud.exception.InsufficientCapacityException;
|
||||
import com.cloud.exception.InvalidParameterValueException;
|
||||
import com.cloud.exception.OperationTimedoutException;
|
||||
import com.cloud.exception.ResourceAllocationException;
|
||||
import com.cloud.exception.ResourceUnavailableException;
|
||||
import com.cloud.hypervisor.Hypervisor;
|
||||
|
|
@ -124,12 +127,12 @@ import com.cloud.storage.dao.VolumeDao;
|
|||
import com.cloud.storage.dao.VolumeDetailsDao;
|
||||
import com.cloud.user.Account;
|
||||
import com.cloud.user.AccountService;
|
||||
import com.cloud.user.AccountVO;
|
||||
import com.cloud.user.User;
|
||||
import com.cloud.user.UserAccount;
|
||||
import com.cloud.user.dao.AccountDao;
|
||||
import com.cloud.user.dao.UserAccountDao;
|
||||
import com.cloud.uservm.UserVm;
|
||||
import com.cloud.utils.EnumUtils;
|
||||
import com.cloud.utils.Pair;
|
||||
import com.cloud.utils.component.ComponentContext;
|
||||
import com.cloud.utils.component.ManagerBase;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
|
|
@ -167,7 +170,7 @@ public class ServerAdapter extends ManagerBase {
|
|||
AccountService accountService;
|
||||
|
||||
@Inject
|
||||
AccountDao accountDao;
|
||||
UserAccountDao userAccountDao;
|
||||
|
||||
@Inject
|
||||
DataCenterDao dataCenterDao;
|
||||
|
|
@ -229,6 +232,12 @@ public class ServerAdapter extends ManagerBase {
|
|||
@Inject
|
||||
NicDao nicDao;
|
||||
|
||||
@Inject
|
||||
ApiServerService apiServerService;
|
||||
|
||||
@Inject
|
||||
AsyncJobJoinDao asyncJobJoinDao;
|
||||
|
||||
private Map<String, Long> jobsMap = new ConcurrentHashMap<>();
|
||||
|
||||
protected Role createServiceAccountRole() {
|
||||
|
|
@ -255,7 +264,7 @@ public class ServerAdapter extends ManagerBase {
|
|||
return createServiceAccountRole();
|
||||
}
|
||||
|
||||
protected Account createServiceAccount() {
|
||||
protected UserAccount createServiceAccount() {
|
||||
CallContext.register(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM);
|
||||
try {
|
||||
Role role = getServiceAccountRole();
|
||||
|
|
@ -263,23 +272,22 @@ public class ServerAdapter extends ManagerBase {
|
|||
UUID.randomUUID().toString(), SERVICE_ACCOUNT_FIRST_NAME,
|
||||
SERVICE_ACCOUNT_LAST_NAME, null, null, SERVICE_ACCOUNT_NAME, Account.Type.NORMAL, role.getId(),
|
||||
1L, null, null, null, null, User.Source.NATIVE);
|
||||
Account account = accountService.getAccount(userAccount.getAccountId());
|
||||
logger.debug("Created Veeam service account: {}", account);
|
||||
return account;
|
||||
logger.debug("Created Veeam service account: {}", userAccount);
|
||||
return userAccount;
|
||||
} finally {
|
||||
CallContext.unregister();
|
||||
}
|
||||
}
|
||||
|
||||
protected Account createServiceAccountIfNeeded() {
|
||||
List<AccountVO> accounts = accountDao.findAccountsByName(SERVICE_ACCOUNT_NAME);
|
||||
for (AccountVO account : accounts) {
|
||||
if (Account.State.ENABLED.equals(account.getState())) {
|
||||
logger.debug("Veeam service account found: {}", account);
|
||||
return account;
|
||||
}
|
||||
protected Pair<User, Account> createServiceAccountIfNeeded() {
|
||||
UserAccount userAccount = accountService.getActiveUserAccount(SERVICE_ACCOUNT_NAME, 1L);
|
||||
if (userAccount == null) {
|
||||
userAccount = createServiceAccount();
|
||||
} else {
|
||||
logger.debug("Veeam service user account found: {}", userAccount);
|
||||
}
|
||||
return createServiceAccount();
|
||||
return new Pair<>(accountService.getActiveUser(userAccount.getId()),
|
||||
accountService.getActiveAccountById(userAccount.getAccountId()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -431,8 +439,8 @@ public class ServerAdapter extends ManagerBase {
|
|||
bootType = ApiConstants.BootType.UEFI;
|
||||
bootMode = ApiConstants.BootMode.SECURE;
|
||||
}
|
||||
Account serviceAccount = createServiceAccountIfNeeded();
|
||||
CallContext.register(serviceAccount.getId(), serviceAccount.getId());
|
||||
Pair<User, Account> serviceUserAccount = createServiceAccountIfNeeded();
|
||||
CallContext ctx = CallContext.register(serviceUserAccount.first(), serviceUserAccount.second());
|
||||
try {
|
||||
return createVm(zoneId, clusterId, name, cpu, memory, userdata, bootType, bootMode);
|
||||
} finally {
|
||||
|
|
@ -507,11 +515,22 @@ public class ServerAdapter extends ManagerBase {
|
|||
if (vo == null) {
|
||||
throw new InvalidParameterValueException("VM with ID " + uuid + " not found");
|
||||
}
|
||||
Pair<User, Account> serviceUserAccount = createServiceAccountIfNeeded();
|
||||
CallContext ctx = CallContext.register(serviceUserAccount.first(), serviceUserAccount.second());
|
||||
try {
|
||||
userVmService.startVirtualMachine(vo, null);
|
||||
return UserVmJoinVOToVmConverter.toVmAction(userVmJoinDao.findById(vo.getId()));
|
||||
} catch (ResourceUnavailableException | OperationTimedoutException | InsufficientCapacityException | CloudRuntimeException e) {
|
||||
StartVMCmd cmd = new StartVMCmd();
|
||||
ComponentContext.inject(cmd);
|
||||
Map<String, String> params = new HashMap<>();
|
||||
params.put(ApiConstants.ID, vo.getUuid());
|
||||
ApiServerService.AsyncCmdResult result =
|
||||
apiServerService.processAsyncCmd(cmd, params, ctx, serviceUserAccount.first().getId(),
|
||||
serviceUserAccount.second());
|
||||
AsyncJobJoinVO asyncJobJoinVO = asyncJobJoinDao.findById(result.jobId);
|
||||
return AsyncJobJoinVOToJobConverter.toVmAction(asyncJobJoinVO, userVmJoinDao.findById(vo.getId()));
|
||||
} catch (Exception e) {
|
||||
throw new CloudRuntimeException("Failed to start VM: " + e.getMessage(), e);
|
||||
} finally {
|
||||
CallContext.unregister();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -520,11 +539,23 @@ public class ServerAdapter extends ManagerBase {
|
|||
if (vo == null) {
|
||||
throw new InvalidParameterValueException("VM with ID " + uuid + " not found");
|
||||
}
|
||||
Pair<User, Account> serviceUserAccount = createServiceAccountIfNeeded();
|
||||
CallContext ctx = CallContext.register(serviceUserAccount.first(), serviceUserAccount.second());
|
||||
try {
|
||||
userVmService.stopVirtualMachine(vo.getId(), true);
|
||||
return UserVmJoinVOToVmConverter.toVmAction(userVmJoinDao.findById(vo.getId()));
|
||||
} catch (CloudRuntimeException e) {
|
||||
StopVMCmd cmd = new StopVMCmd();
|
||||
ComponentContext.inject(cmd);
|
||||
Map<String, String> params = new HashMap<>();
|
||||
params.put(ApiConstants.ID, vo.getUuid());
|
||||
params.put(ApiConstants.FORCED, Boolean.TRUE.toString());
|
||||
ApiServerService.AsyncCmdResult result =
|
||||
apiServerService.processAsyncCmd(cmd, params, ctx, serviceUserAccount.first().getId(),
|
||||
serviceUserAccount.second());
|
||||
AsyncJobJoinVO asyncJobJoinVO = asyncJobJoinDao.findById(result.jobId);
|
||||
return AsyncJobJoinVOToJobConverter.toVmAction(asyncJobJoinVO, userVmJoinDao.findById(vo.getId()));
|
||||
} catch (Exception e) {
|
||||
throw new CloudRuntimeException("Failed to stop VM: " + e.getMessage(), e);
|
||||
} finally {
|
||||
CallContext.unregister();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -533,11 +564,23 @@ public class ServerAdapter extends ManagerBase {
|
|||
if (vo == null) {
|
||||
throw new InvalidParameterValueException("VM with ID " + uuid + " not found");
|
||||
}
|
||||
Pair<User, Account> serviceUserAccount = createServiceAccountIfNeeded();
|
||||
CallContext ctx = CallContext.register(serviceUserAccount.first(), serviceUserAccount.second());
|
||||
try {
|
||||
userVmService.stopVirtualMachine(vo.getId(), false);
|
||||
return UserVmJoinVOToVmConverter.toVmAction(userVmJoinDao.findById(vo.getId()));
|
||||
} catch (CloudRuntimeException e) {
|
||||
StopVMCmd cmd = new StopVMCmd();
|
||||
ComponentContext.inject(cmd);
|
||||
Map<String, String> params = new HashMap<>();
|
||||
params.put(ApiConstants.ID, vo.getUuid());
|
||||
params.put(ApiConstants.FORCED, Boolean.FALSE.toString());
|
||||
ApiServerService.AsyncCmdResult result =
|
||||
apiServerService.processAsyncCmd(cmd, params, ctx, serviceUserAccount.first().getId(),
|
||||
serviceUserAccount.second());
|
||||
AsyncJobJoinVO asyncJobJoinVO = asyncJobJoinDao.findById(result.jobId);
|
||||
return AsyncJobJoinVOToJobConverter.toVmAction(asyncJobJoinVO, userVmJoinDao.findById(vo.getId()));
|
||||
} catch (Exception e) {
|
||||
throw new CloudRuntimeException("Failed to shutdown VM: " + e.getMessage(), e);
|
||||
} finally {
|
||||
CallContext.unregister();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -579,8 +622,8 @@ public class ServerAdapter extends ManagerBase {
|
|||
if (volumeVO == null) {
|
||||
throw new InvalidParameterValueException("Disk with ID " + request.disk.id + " not found");
|
||||
}
|
||||
Account serviceAccount = createServiceAccountIfNeeded();
|
||||
CallContext.register(serviceAccount.getId(), serviceAccount.getId());
|
||||
Pair<User, Account> serviceUserAccount = createServiceAccountIfNeeded();
|
||||
CallContext.register(serviceUserAccount.first(), serviceUserAccount.second());
|
||||
try {
|
||||
Volume volume = volumeApiService.attachVolumeToVM(vmVo.getId(), volumeVO.getId(), 0L, false);
|
||||
VolumeJoinVO attachedVolumeVO = volumeJoinDao.findById(volume.getId());
|
||||
|
|
@ -638,7 +681,8 @@ public class ServerAdapter extends ManagerBase {
|
|||
initialSize = Long.parseLong(request.initialSize);
|
||||
} catch (NumberFormatException ignored) {}
|
||||
}
|
||||
Account serviceAccount = createServiceAccountIfNeeded();
|
||||
Pair<User, Account> serviceUserAccount = createServiceAccountIfNeeded();
|
||||
Account serviceAccount = serviceUserAccount.second();
|
||||
DataCenterVO zone = dataCenterDao.findById(pool.getDataCenterId());
|
||||
if (zone == null || !Grouping.AllocationState.Enabled.equals(zone.getAllocationState())) {
|
||||
throw new InvalidParameterValueException("Datacenter for the specified storage domain is not found or not active");
|
||||
|
|
@ -647,7 +691,7 @@ public class ServerAdapter extends ManagerBase {
|
|||
if (diskOfferingId == null) {
|
||||
throw new CloudRuntimeException("Failed to find custom offering for disk" + zone.getName());
|
||||
}
|
||||
CallContext.register(serviceAccount.getId(), serviceAccount.getId());
|
||||
CallContext ctx = CallContext.register(serviceUserAccount.first(), serviceUserAccount.second());
|
||||
try {
|
||||
return createDisk(serviceAccount, pool, name, diskOfferingId, provisionedSizeInGb, initialSize);
|
||||
} finally {
|
||||
|
|
@ -705,8 +749,8 @@ public class ServerAdapter extends ManagerBase {
|
|||
if (networkVO == null) {
|
||||
throw new InvalidParameterValueException("VNic profile " + request.getVnicProfile().id+ " not found");
|
||||
}
|
||||
Account serviceAccount = createServiceAccountIfNeeded();
|
||||
CallContext.register(serviceAccount.getId(), serviceAccount.getId());
|
||||
Pair<User, Account> serviceUserAccount = createServiceAccountIfNeeded();
|
||||
CallContext.register(serviceUserAccount.first(), serviceUserAccount.second());
|
||||
try {
|
||||
AddNicToVMCmd cmd = new AddNicToVMCmd();
|
||||
ComponentContext.inject(cmd);
|
||||
|
|
@ -775,8 +819,8 @@ public class ServerAdapter extends ManagerBase {
|
|||
}
|
||||
|
||||
private ImageTransfer createImageTransfer(Long backupId, Long volumeId, Direction direction, Format format) {
|
||||
Account serviceAccount = createServiceAccountIfNeeded();
|
||||
CallContext.register(serviceAccount.getId(), serviceAccount.getId());
|
||||
Pair<User, Account> serviceUserAccount = createServiceAccountIfNeeded();
|
||||
CallContext.register(serviceUserAccount.first(), serviceUserAccount.second());
|
||||
try {
|
||||
org.apache.cloudstack.backup.ImageTransfer imageTransfer =
|
||||
incrementalBackupService.createImageTransfer(volumeId, null, direction, format);
|
||||
|
|
@ -819,7 +863,7 @@ public class ServerAdapter extends ManagerBase {
|
|||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
public Job getJob(String uuid) {
|
||||
public Job getTempJob(String uuid) {
|
||||
// final ClusterVO vo = clusterDao.findByUuid(uuid);
|
||||
// if (vo == null) {
|
||||
// throw new InvalidParameterValueException("Cluster with ID " + uuid + " not found");
|
||||
|
|
@ -832,4 +876,12 @@ public class ServerAdapter extends ManagerBase {
|
|||
return AsyncJobJoinVOToJobConverter.toJob(uuid, "started", startTime);
|
||||
}
|
||||
}
|
||||
|
||||
public Job getJob(String uuid) {
|
||||
final AsyncJobJoinVO vo = asyncJobJoinDao.findByUuid(uuid);
|
||||
if (vo == null) {
|
||||
throw new InvalidParameterValueException("Job with ID " + uuid + " not found");
|
||||
}
|
||||
return AsyncJobJoinVOToJobConverter.toJob(vo);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ public class JobsRouteHandler extends ManagerBase implements RouteHandler {
|
|||
protected void handleGetById(final String id, final HttpServletResponse resp, final Negotiation.OutFormat outFormat,
|
||||
final VeeamControlServlet io) throws IOException {
|
||||
try {
|
||||
Job response = serverAdapter.getJob(id);
|
||||
Job response = serverAdapter.getTempJob(id);
|
||||
io.getWriter().write(resp, HttpServletResponse.SC_OK, response, outFormat);
|
||||
} catch (InvalidParameterValueException e) {
|
||||
io.getWriter().writeFault(resp, HttpServletResponse.SC_NOT_FOUND, "Not found", e.getMessage(), outFormat);
|
||||
|
|
|
|||
|
|
@ -19,11 +19,16 @@ package org.apache.cloudstack.veeam.api.converter;
|
|||
|
||||
import java.util.Collections;
|
||||
|
||||
import org.apache.cloudstack.jobs.JobInfo;
|
||||
import org.apache.cloudstack.veeam.VeeamControlService;
|
||||
import org.apache.cloudstack.veeam.api.JobsRouteHandler;
|
||||
import org.apache.cloudstack.veeam.api.dto.Actions;
|
||||
import org.apache.cloudstack.veeam.api.dto.Job;
|
||||
import org.apache.cloudstack.veeam.api.dto.Ref;
|
||||
import org.apache.cloudstack.veeam.api.dto.VmAction;
|
||||
|
||||
import com.cloud.api.query.vo.AsyncJobJoinVO;
|
||||
import com.cloud.api.query.vo.UserVmJoinVO;
|
||||
|
||||
public class AsyncJobJoinVOToJobConverter {
|
||||
|
||||
|
|
@ -47,4 +52,40 @@ public class AsyncJobJoinVOToJobConverter {
|
|||
job.setLink(Collections.emptyList());
|
||||
return job;
|
||||
}
|
||||
|
||||
public static Job toJob(AsyncJobJoinVO vo) {
|
||||
Job job = new Job();
|
||||
final String basePath = VeeamControlService.ContextPath.value();
|
||||
job.setId(vo.getUuid());
|
||||
job.setHref(basePath + JobsRouteHandler.BASE_ROUTE + "/" + vo.getUuid());
|
||||
job.setAutoCleared(Boolean.TRUE.toString());
|
||||
job.setExternal(Boolean.TRUE.toString());
|
||||
job.setLastUpdated(System.currentTimeMillis());
|
||||
job.setStartTime(vo.getCreated().getTime());
|
||||
JobInfo.Status status = JobInfo.Status.values()[vo.getStatus()];
|
||||
if (status == JobInfo.Status.SUCCEEDED) {
|
||||
job.setStatus("finished");
|
||||
job.setEndTime(System.currentTimeMillis());
|
||||
} else if (status == JobInfo.Status.FAILED) {
|
||||
job.setStatus(status.name().toLowerCase());
|
||||
} else if (status == JobInfo.Status.CANCELLED) {
|
||||
job.setStatus("aborted");
|
||||
} else {
|
||||
job.setStatus("started");
|
||||
}
|
||||
job.setOwner(Ref.of(basePath + "/api/users/" + vo.getUserUuid(), vo.getUserUuid()));
|
||||
job.setActions(new Actions());
|
||||
job.setDescription("Something");
|
||||
job.setLink(Collections.emptyList());
|
||||
return job;
|
||||
}
|
||||
|
||||
public static VmAction toVmAction(final AsyncJobJoinVO vo, final UserVmJoinVO vm) {
|
||||
VmAction action = new VmAction();
|
||||
final String basePath = VeeamControlService.ContextPath.value();
|
||||
action.setVm(UserVmJoinVOToVmConverter.toVm(vm, null, null, null));
|
||||
action.setJob(Ref.of(basePath + JobsRouteHandler.BASE_ROUTE + vo.getUuid(), vo.getUuid()));
|
||||
action.setStatus("complete");
|
||||
return action;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,6 +16,10 @@
|
|||
// under the License.
|
||||
package com.cloud.api;
|
||||
|
||||
import static com.cloud.user.AccountManagerImpl.apiKeyAccess;
|
||||
import static org.apache.cloudstack.api.ApiConstants.PASSWORD_CHANGE_REQUIRED;
|
||||
import static org.apache.cloudstack.user.UserPasswordResetManager.UserPasswordResetEnabled;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InterruptedIOException;
|
||||
|
|
@ -31,6 +35,7 @@ import java.security.SecureRandom;
|
|||
import java.security.Security;
|
||||
import java.text.ParseException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.EnumSet;
|
||||
|
|
@ -39,7 +44,6 @@ import java.util.HashMap;
|
|||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TimeZone;
|
||||
|
|
@ -58,16 +62,6 @@ import javax.naming.ConfigurationException;
|
|||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
import com.cloud.cluster.ManagementServerHostVO;
|
||||
import com.cloud.cluster.dao.ManagementServerHostDao;
|
||||
import com.cloud.utils.Ternary;
|
||||
import com.cloud.user.Account;
|
||||
import com.cloud.user.AccountManager;
|
||||
import com.cloud.user.AccountManagerImpl;
|
||||
import com.cloud.user.DomainManager;
|
||||
import com.cloud.user.User;
|
||||
import com.cloud.user.UserAccount;
|
||||
import com.cloud.user.UserVO;
|
||||
import org.apache.cloudstack.acl.APIChecker;
|
||||
import org.apache.cloudstack.acl.ApiKeyPairManagerImpl;
|
||||
import org.apache.cloudstack.acl.apikeypair.ApiKeyPair;
|
||||
|
|
@ -161,6 +155,8 @@ import org.springframework.stereotype.Component;
|
|||
import com.cloud.api.dispatch.DispatchChainFactory;
|
||||
import com.cloud.api.dispatch.DispatchTask;
|
||||
import com.cloud.api.response.ApiResponseSerializer;
|
||||
import com.cloud.cluster.ManagementServerHostVO;
|
||||
import com.cloud.cluster.dao.ManagementServerHostDao;
|
||||
import com.cloud.domain.Domain;
|
||||
import com.cloud.domain.DomainVO;
|
||||
import com.cloud.domain.dao.DomainDao;
|
||||
|
|
@ -179,14 +175,22 @@ import com.cloud.exception.ResourceUnavailableException;
|
|||
import com.cloud.exception.UnavailableCommandException;
|
||||
import com.cloud.projects.dao.ProjectDao;
|
||||
import com.cloud.storage.VolumeApiService;
|
||||
import com.cloud.user.Account;
|
||||
import com.cloud.user.AccountManager;
|
||||
import com.cloud.user.AccountManagerImpl;
|
||||
import com.cloud.user.DomainManager;
|
||||
import com.cloud.user.User;
|
||||
import com.cloud.user.UserAccount;
|
||||
import com.cloud.user.UserVO;
|
||||
import com.cloud.utils.ConstantTimeComparator;
|
||||
import com.cloud.utils.DateUtil;
|
||||
import com.cloud.utils.HttpUtils;
|
||||
import com.cloud.utils.HttpUtils.ApiSessionKeySameSite;
|
||||
import com.cloud.utils.HttpUtils.ApiSessionKeyCheckOption;
|
||||
import com.cloud.utils.HttpUtils.ApiSessionKeySameSite;
|
||||
import com.cloud.utils.Pair;
|
||||
import com.cloud.utils.ReflectUtil;
|
||||
import com.cloud.utils.StringUtils;
|
||||
import com.cloud.utils.Ternary;
|
||||
import com.cloud.utils.component.ComponentContext;
|
||||
import com.cloud.utils.component.ManagerBase;
|
||||
import com.cloud.utils.component.PluggableService;
|
||||
|
|
@ -199,10 +203,6 @@ import com.cloud.utils.exception.ExceptionProxyObject;
|
|||
import com.cloud.utils.net.NetUtils;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
|
||||
import static com.cloud.user.AccountManagerImpl.apiKeyAccess;
|
||||
import static org.apache.cloudstack.api.ApiConstants.PASSWORD_CHANGE_REQUIRED;
|
||||
import static org.apache.cloudstack.user.UserPasswordResetManager.UserPasswordResetEnabled;
|
||||
|
||||
@Component
|
||||
public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiServerService, Configurable {
|
||||
private static final Logger ACCESSLOGGER = LogManager.getLogger("apiserver." + ApiServer.class.getName());
|
||||
|
|
@ -792,85 +792,14 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer
|
|||
// BaseAsyncCreateCmd: cmd params are processed and create() is called, then same workflow as BaseAsyncCmd.
|
||||
// BaseAsyncCmd: cmd is processed and submitted as an AsyncJob, job related info is serialized and returned.
|
||||
if (cmdObj instanceof BaseAsyncCmd) {
|
||||
if (!asyncMgr.isAsyncJobsEnabled()) {
|
||||
String msg = "Maintenance or Shutdown has been initiated on this management server. Can not accept new jobs";
|
||||
logger.warn(msg);
|
||||
throw new ServerApiException(ApiErrorCode.SERVICE_UNAVAILABLE, msg);
|
||||
}
|
||||
Long objectId = null;
|
||||
String objectUuid;
|
||||
if (cmdObj instanceof BaseAsyncCreateCmd) {
|
||||
final BaseAsyncCreateCmd createCmd = (BaseAsyncCreateCmd)cmdObj;
|
||||
dispatcher.dispatchCreateCmd(createCmd, params);
|
||||
objectId = createCmd.getEntityId();
|
||||
objectUuid = createCmd.getEntityUuid();
|
||||
params.put("id", objectId.toString());
|
||||
Class entityClass = EventTypes.getEntityClassForEvent(createCmd.getEventType());
|
||||
if (entityClass != null)
|
||||
ctx.putContextParameter(entityClass, objectUuid);
|
||||
} else {
|
||||
// Extract the uuid before params are processed and id reflects internal db id
|
||||
objectUuid = params.get(ApiConstants.ID);
|
||||
dispatchChainFactory.getStandardDispatchChain().dispatch(new DispatchTask(cmdObj, params));
|
||||
}
|
||||
|
||||
final BaseAsyncCmd asyncCmd = (BaseAsyncCmd)cmdObj;
|
||||
|
||||
if (callerUserId != null) {
|
||||
params.put("ctxUserId", callerUserId.toString());
|
||||
}
|
||||
if (caller != null) {
|
||||
params.put("ctxAccountId", String.valueOf(caller.getId()));
|
||||
}
|
||||
if (objectUuid != null) {
|
||||
params.put("uuid", objectUuid);
|
||||
}
|
||||
|
||||
long startEventId = ctx.getStartEventId();
|
||||
asyncCmd.setStartEventId(startEventId);
|
||||
|
||||
// save the scheduled event
|
||||
final Long eventId =
|
||||
ActionEventUtils.onScheduledActionEvent((callerUserId == null) ? (Long)User.UID_SYSTEM : callerUserId, asyncCmd.getEntityOwnerId(), asyncCmd.getEventType(),
|
||||
asyncCmd.getEventDescription(), asyncCmd.getApiResourceId(), asyncCmd.getApiResourceType().toString(), asyncCmd.isDisplay(), startEventId);
|
||||
if (startEventId == 0) {
|
||||
// There was no create event before, set current event id as start eventId
|
||||
startEventId = eventId;
|
||||
}
|
||||
|
||||
params.put("ctxStartEventId", String.valueOf(startEventId));
|
||||
params.put("cmdEventType", asyncCmd.getEventType());
|
||||
params.put("ctxDetails", ApiGsonHelper.getBuilder().create().toJson(ctx.getContextParameters()));
|
||||
if (asyncCmd.getHttpMethod() != null) {
|
||||
params.put(ApiConstants.HTTPMETHOD, asyncCmd.getHttpMethod().toString());
|
||||
}
|
||||
|
||||
Long instanceId = (objectId == null) ? asyncCmd.getApiResourceId() : objectId;
|
||||
|
||||
// users can provide the job id they want to use, so log as it is a uuid and is unique
|
||||
String injectedJobId = asyncCmd.getInjectedJobId();
|
||||
uuidMgr.checkUuidSimple(injectedJobId, AsyncJob.class);
|
||||
|
||||
AsyncJobVO job = new AsyncJobVO("", callerUserId, caller.getId(), cmdObj.getClass().getName(),
|
||||
ApiGsonHelper.getBuilder().create().toJson(params), instanceId,
|
||||
asyncCmd.getApiResourceType() != null ? asyncCmd.getApiResourceType().toString() : null,
|
||||
injectedJobId);
|
||||
job.setDispatcher(asyncDispatcher.getName());
|
||||
|
||||
final long jobId = asyncMgr.submitAsyncJob(job);
|
||||
|
||||
if (jobId == 0L) {
|
||||
final String errorMsg = "Unable to schedule async job for command " + job.getCmd();
|
||||
logger.warn(errorMsg);
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, errorMsg);
|
||||
}
|
||||
AsyncCmdResult result = processAsyncCmd((BaseAsyncCmd)cmdObj, params, ctx, callerUserId, caller);
|
||||
final String response;
|
||||
if (objectId != null) {
|
||||
final String objUuid = (objectUuid == null) ? objectId.toString() : objectUuid;
|
||||
response = getBaseAsyncCreateResponse(jobId, (BaseAsyncCreateCmd)asyncCmd, objUuid);
|
||||
if (result.objectId != null) {
|
||||
final String objUuid = (result.objectUuid == null) ? result.objectId.toString() : result.objectUuid;
|
||||
response = getBaseAsyncCreateResponse(result.jobId, (BaseAsyncCreateCmd) result.asyncCmd, objUuid);
|
||||
} else {
|
||||
SerializationContext.current().setUuidTranslation(true);
|
||||
response = getBaseAsyncResponse(jobId, asyncCmd);
|
||||
response = getBaseAsyncResponse(result.jobId, result.asyncCmd);
|
||||
}
|
||||
// Always log response for async for now, I don't think any sensitive data will be in here.
|
||||
// It might be nice to send this through scrubbing similar to how
|
||||
|
|
@ -900,6 +829,81 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public AsyncCmdResult processAsyncCmd(BaseAsyncCmd asyncCmd, Map<String, String> params, CallContext ctx, Long callerUserId, Account caller) throws Exception {
|
||||
if (!asyncMgr.isAsyncJobsEnabled()) {
|
||||
String msg = "Maintenance or Shutdown has been initiated on this management server. Can not accept new jobs";
|
||||
logger.warn(msg);
|
||||
throw new ServerApiException(ApiErrorCode.SERVICE_UNAVAILABLE, msg);
|
||||
}
|
||||
Long objectId = null;
|
||||
String objectUuid;
|
||||
if (asyncCmd instanceof BaseAsyncCreateCmd) {
|
||||
final BaseAsyncCreateCmd createCmd = (BaseAsyncCreateCmd) asyncCmd;
|
||||
dispatcher.dispatchCreateCmd(createCmd, params);
|
||||
objectId = createCmd.getEntityId();
|
||||
objectUuid = createCmd.getEntityUuid();
|
||||
params.put("id", objectId.toString());
|
||||
Class entityClass = EventTypes.getEntityClassForEvent(createCmd.getEventType());
|
||||
if (entityClass != null)
|
||||
ctx.putContextParameter(entityClass, objectUuid);
|
||||
} else {
|
||||
// Extract the uuid before params are processed and id reflects internal db id
|
||||
objectUuid = params.get(ApiConstants.ID);
|
||||
dispatchChainFactory.getStandardDispatchChain().dispatch(new DispatchTask(asyncCmd, params));
|
||||
}
|
||||
|
||||
if (callerUserId != null) {
|
||||
params.put("ctxUserId", callerUserId.toString());
|
||||
}
|
||||
if (caller != null) {
|
||||
params.put("ctxAccountId", String.valueOf(caller.getId()));
|
||||
}
|
||||
if (objectUuid != null) {
|
||||
params.put("uuid", objectUuid);
|
||||
}
|
||||
|
||||
long startEventId = ctx.getStartEventId();
|
||||
asyncCmd.setStartEventId(startEventId);
|
||||
|
||||
// save the scheduled event
|
||||
final Long eventId =
|
||||
ActionEventUtils.onScheduledActionEvent((callerUserId == null) ? (Long)User.UID_SYSTEM : callerUserId, asyncCmd.getEntityOwnerId(), asyncCmd.getEventType(),
|
||||
asyncCmd.getEventDescription(), asyncCmd.getApiResourceId(), asyncCmd.getApiResourceType().toString(), asyncCmd.isDisplay(), startEventId);
|
||||
if (startEventId == 0) {
|
||||
// There was no create event before, set current event id as start eventId
|
||||
startEventId = eventId;
|
||||
}
|
||||
|
||||
params.put("ctxStartEventId", String.valueOf(startEventId));
|
||||
params.put("cmdEventType", asyncCmd.getEventType());
|
||||
params.put("ctxDetails", ApiGsonHelper.getBuilder().create().toJson(ctx.getContextParameters()));
|
||||
if (asyncCmd.getHttpMethod() != null) {
|
||||
params.put(ApiConstants.HTTPMETHOD, asyncCmd.getHttpMethod().toString());
|
||||
}
|
||||
|
||||
Long instanceId = (objectId == null) ? asyncCmd.getApiResourceId() : objectId;
|
||||
|
||||
// users can provide the job id they want to use, so log as it is a uuid and is unique
|
||||
String injectedJobId = asyncCmd.getInjectedJobId();
|
||||
uuidMgr.checkUuidSimple(injectedJobId, AsyncJob.class);
|
||||
|
||||
AsyncJobVO job = new AsyncJobVO("", callerUserId, caller.getId(), asyncCmd.getClass().getName(),
|
||||
ApiGsonHelper.getBuilder().create().toJson(params), instanceId,
|
||||
asyncCmd.getApiResourceType() != null ? asyncCmd.getApiResourceType().toString() : null,
|
||||
injectedJobId);
|
||||
job.setDispatcher(asyncDispatcher.getName());
|
||||
|
||||
final long jobId = asyncMgr.submitAsyncJob(job);
|
||||
|
||||
if (jobId == 0L) {
|
||||
final String errorMsg = "Unable to schedule async job for command " + job.getCmd();
|
||||
logger.warn(errorMsg);
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, errorMsg);
|
||||
}
|
||||
return new AsyncCmdResult(objectId, objectUuid, asyncCmd, jobId);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void buildAsyncListResponse(final BaseListCmd command, final Account account) {
|
||||
final List<ResponseObject> responses = ((ListResponse<ResponseObject>)command.getResponseObject()).getResponses();
|
||||
|
|
|
|||
Loading…
Reference in New Issue