Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,13 @@ public class VmGlobalConfig {
public static GlobalConfig VM_EXPUNGE_INTERVAL = new GlobalConfig(CATEGORY, "expungeInterval");
@GlobalConfigValidation(validValues = {"true", "false"})
public static GlobalConfig VM_CLEAN_TRAFFIC = new GlobalConfig(CATEGORY, "cleanTraffic");
@GlobalConfigDef(defaultValue = "true", type = Boolean.class, description = "whether reset TPM state after VM clone")
@GlobalConfigValidation(validValues = {"true", "false"})
@BindResourceConfig(value = {VmInstanceVO.class, ClusterVO.class})
public static GlobalConfig RESET_TPM_AFTER_VM_CLONE = new GlobalConfig(CATEGORY, "reset.tpm.after.vm.clone");
@GlobalConfigDef(defaultValue = "false", type = Boolean.class, description = "allowed TPM VM start without KMS")
@GlobalConfigValidation(validValues = {"true", "false"})
public static GlobalConfig ALLOWED_TPM_VM_WITHOUT_KMS = new GlobalConfig(CATEGORY, "allowed.tpm.vm.without.kms");
@GlobalConfigValidation(validValues = {"cirrus","vga", "qxl", "virtio"})
@BindResourceConfig(value = {VmInstanceVO.class, ClusterVO.class})
public static GlobalConfig VM_VIDEO_TYPE = new GlobalConfig(CATEGORY, "videoType");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1261,6 +1261,28 @@ public void rollback(FlowRollback trigger, Map data) {
}
});

flow(new Flow() {
List<VmInstanceCreateExtensionPoint> done = new ArrayList<>();
String __name__ = String.format("after-persist-create-vm-extension-%s", finalVo.getUuid());

@Override
public void run(FlowTrigger trigger, Map data) {
for (VmInstanceCreateExtensionPoint extension : pluginRgty.getExtensionList(VmInstanceCreateExtensionPoint.class)) {
done.add(extension);
extension.afterPersistVmInstanceVO(finalVo, msg);
}
trigger.next();
}

@Override
public void rollback(FlowRollback trigger, Map data) {
Collections.reverse(done);
CollectionUtils.safeForEach(done,
extension -> extension.afterRollbackPersistVmInstanceVO(finalVo, msg));
trigger.rollback();
}
});

flow(new Flow() {
List<ErrorCode> errorCodes = Collections.emptyList();
String __name__ = String.format("instantiate-ssh-key-pair-for-vm-%s", finalVo.getUuid());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ public static CreateVmInstanceMsg fromAPICreateVmInstanceMsg(APICreateVmInstance
cmsg.setPrimaryStorageUuidForRootVolume(msg.getPrimaryStorageUuidForRootVolume());
cmsg.setDataVolumeSystemTagsOnIndex(msg.getDataVolumeSystemTagsOnIndex());
cmsg.setStrategy(msg.getStrategy());
cmsg.setDevicesSpec(msg.getDevicesSpec());

cmsg.setDiskAOs(msg.getDiskAOs());

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package org.zstack.compute.vm.devices;

import org.zstack.header.errorcode.OperationFailureException;
import org.zstack.header.keyprovider.EncryptedResourceKeyManager;
import org.zstack.header.core.Completion;
import org.zstack.header.core.ReturnValueCompletion;
import org.zstack.utils.Utils;
import org.zstack.utils.logging.CLogger;

import static org.zstack.core.Platform.operr;
import static org.zstack.header.tpm.TpmErrors.GENERAL_ERROR;

public class DummyEncryptedResourceKeyManager implements EncryptedResourceKeyManager {
private static final CLogger logger = Utils.getLogger(DummyEncryptedResourceKeyManager.class);

@Override
public void getOrCreateKey(GetOrCreateResourceKeyContext ctx,
ReturnValueCompletion<ResourceKeyResult> completion) {
logger.warn(String.format("crypto module not installed, cannot create resource key for %s[uuid:%s]",
ctx.getResourceType(), ctx.getResourceUuid()));
completion.fail(operr(GENERAL_ERROR.toString(),
"crypto module is not installed, cannot manage resource encryption keys"));
}

@Override
public ResourceKeyResult getKey(GetOrCreateResourceKeyContext ctx) {
logger.warn(String.format("crypto module not installed, cannot get resource key for %s[uuid:%s]",
ctx.getResourceType(), ctx.getResourceUuid()));
throw new OperationFailureException(operr(GENERAL_ERROR.toString(),
"crypto module is not installed, cannot manage resource encryption keys"));
}

@Override
public void rollbackCreatedKey(ResourceKeyResult result, Completion completion) {
completion.success();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package org.zstack.compute.vm.devices;

import org.zstack.header.core.Completion;
import org.zstack.utils.Utils;
import org.zstack.utils.logging.CLogger;

public class DummyTpmEncryptedResourceKeyBackend implements TpmEncryptedResourceKeyBackend {
private static final CLogger logger = Utils.getLogger(DummyTpmEncryptedResourceKeyBackend.class);

@Override
public void attachKeyProviderToTpm(String tpmUuid, String keyProviderUuid) {
logger.debug("ignore attach key provider to TPM request for TPM uuid " + tpmUuid +
" and key provider uuid " + keyProviderUuid);
}

@Override
public void detachKeyProviderFromTpm(String tpmUuid) {
logger.debug("ignore detach key provider from TPM request for TPM uuid " + tpmUuid);
}

@Override
public String findKeyProviderUuidByTpm(String tpmUuid) {
return null;
}

@Override
public String findKeyProviderUuidByName(String providerName) {
return null;
}

@Override
public String findKeyProviderNameByTpm(String tpmUuid) {
return null;
}

@Override
public Integer findKeyVersionByTpm(String tpmUuid) {
return null;
}

@Override
public String defaultKeyProviderUuid() {
return null;
}

@Override
public int applyKeyProviderWithKek(String tpmUuid, String providerUuid) {
return 0;
}

@Override
public boolean checkTpmKeyProviderAttached(String tpmUuid) {
return false;
}

@Override
public void cloneEncryptedResourceKey(CloneEncryptedResourceKeyContext context, Completion completion) {
// do nothing
logger.debug("ignore clone encrypted resource key request for TPM uuid "
+ context.srcTpmUuid + " -> " + context.dstTpmUuid);
completion.success();
}

@Override
public void backupEncryptedResourceKey(BackupEncryptedResourceKeyContext context) {
// do nothing
logger.debug("ignore backup encrypted resource key request for src resource: "
+ context.srcResourceUuid + " -> dest resource: " + context.dstResourceUuid);
}

@Override
public void restoreEncryptedResourceKey(RestoreEncryptedResourceKeyContext context) {
// do nothing
logger.debug("ignore restore encrypted resource key request for src resource: "
+ context.srcResourceUuid + " -> dest resource: " + context.dstResourceUuid);
}

@Override
public void cleanEncryptedResourceKey(String vmHostBackupFileUuid) {
// do nothing
logger.debug("ignore cleanup encrypted resource key request for VmHostBackupFileVO: " + vmHostBackupFileUuid);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
package org.zstack.compute.vm.devices;

import org.springframework.beans.factory.annotation.Autowired;
import org.zstack.core.Platform;
import org.zstack.core.cloudbus.CloudBus;
import org.zstack.core.db.Q;
import org.zstack.header.apimediator.ApiMessageInterceptionException;
import org.zstack.header.apimediator.ApiMessageInterceptor;
import org.zstack.header.apimediator.StopRoutingException;
import org.zstack.header.errorcode.SysErrors;
import org.zstack.header.message.APIMessage;
import org.zstack.header.tpm.api.*;
import org.zstack.header.tpm.entity.TpmVO;
import org.zstack.header.tpm.entity.TpmVO_;
import org.zstack.header.vm.VmInstanceVO;
import org.zstack.header.vm.VmInstanceVO_;
import org.zstack.utils.Utils;
import org.zstack.utils.logging.CLogger;

import static org.zstack.core.Platform.err;
import static org.zstack.header.tpm.TpmConstants.*;
import static org.zstack.header.tpm.TpmErrors.*;
import static org.zstack.header.vm.VmInstanceConstant.KVM_HYPERVISOR_TYPE;

public class TpmApiInterceptor implements ApiMessageInterceptor {
private static final CLogger logger = Utils.getLogger(TpmApiInterceptor.class);

@Autowired
private CloudBus bus;

@Override
public APIMessage intercept(APIMessage msg) throws ApiMessageInterceptionException {
if (msg instanceof APIGetTpmCapabilityMsg) {
validate((APIGetTpmCapabilityMsg) msg);
} else if (msg instanceof APIAddTpmMsg) {
validate((APIAddTpmMsg) msg);
} else if (msg instanceof APIRemoveTpmMsg) {
validate((APIRemoveTpmMsg) msg);
} else if (msg instanceof APIUpdateTpmMsg) {
validate((APIUpdateTpmMsg) msg);
}

return msg;
}

private void validate(APIGetTpmCapabilityMsg msg) {
makeSureVmInstanceIsKvmType(msg.getVmInstanceUuid());
}

private void validate(APIAddTpmMsg msg) {
makeSureVmInstanceIsKvmType(msg.getVmInstanceUuid());

boolean tpmExists = Q.New(TpmVO.class)
.eq(TpmVO_.vmInstanceUuid, msg.getVmInstanceUuid())
.isExists();
if (tpmExists) {
throw new ApiMessageInterceptionException(err(TPM_ALREADY_EXISTS.toString(), TPM_ALREADY_EXISTS,
"tpm device already exists"));
}

boolean vmInSupportState = Q.New(VmInstanceVO.class)
.eq(VmInstanceVO_.uuid, msg.getVmInstanceUuid())
.in(VmInstanceVO_.state, SUPPORT_VM_STATES_FOR_TPM_OPERATION)
.isExists();
if (!vmInSupportState) {
throw new ApiMessageInterceptionException(err(VM_STATE_ERROR.toString(), VM_STATE_ERROR,
"The current VM state does not support adding TPM operations")
.withOpaque("support.vm.state", SUPPORT_VM_STATES_FOR_TPM_OPERATION));
}

if (msg.getResourceUuid() == null) {
msg.setResourceUuid(Platform.getUuid());
}
}

private void validate(APIRemoveTpmMsg msg) {
makeSureVmInstanceIsKvmType(msg.getVmInstanceUuid());

boolean tpmExists = Q.New(TpmVO.class)
.eq(TpmVO_.vmInstanceUuid, msg.getVmInstanceUuid())
.isExists();
if (!tpmExists) {
APIRemoveTpmEvent evt = new APIRemoveTpmEvent(msg.getId());
bus.publish(evt);
throw new StopRoutingException();
}

boolean vmInSupportState = Q.New(VmInstanceVO.class)
.eq(VmInstanceVO_.uuid, msg.getVmInstanceUuid())
.in(VmInstanceVO_.state, SUPPORT_VM_STATES_FOR_TPM_OPERATION)
.isExists();
if (!vmInSupportState) {
throw new ApiMessageInterceptionException(err(VM_STATE_ERROR.toString(), VM_STATE_ERROR,
"The current VM state does not support removing TPM operations")
.withOpaque("support.vm.state", SUPPORT_VM_STATES_FOR_TPM_OPERATION));
}
}

private void validate(APIUpdateTpmMsg msg) {
makeSureVmInstanceIsKvmType(msg.getVmInstanceUuid());
bus.makeTargetServiceIdByResourceUuid(msg, SERVICE_ID, msg.getTpmUuid());
}

private void makeSureVmInstanceIsKvmType(String vmInstanceUuid) {
String hypervisorType = Q.New(VmInstanceVO.class)
.select(VmInstanceVO_.hypervisorType)
.eq(VmInstanceVO_.uuid, vmInstanceUuid)
.findValue();
if (!KVM_HYPERVISOR_TYPE.equals(hypervisorType)) {
throw new ApiMessageInterceptionException(err(GENERAL_ERROR.toString(), SysErrors.OPERATION_ERROR,
"only allowed for kvm type VM instance"));
}
}
}
Loading