package org.zstack.compute.vm;
import org.springframework.beans.factory.annotation.Autowire;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Configurable;
import org.zstack.core.cloudbus.CloudBus;
import org.zstack.core.cloudbus.CloudBusCallBack;
import org.zstack.core.db.DatabaseFacade;
import org.zstack.core.errorcode.ErrorFacade;
import org.zstack.header.core.workflow.Flow;
import org.zstack.header.core.workflow.FlowRollback;
import org.zstack.header.core.workflow.FlowTrigger;
import org.zstack.header.host.HostInventory;
import org.zstack.header.host.HostVO;
import org.zstack.header.message.MessageReply;
import org.zstack.header.storage.primary.*;
import org.zstack.header.vm.VmInstanceConstant;
import org.zstack.header.vm.VmInstanceSpec;
import org.zstack.header.volume.VolumeInventory;
import org.zstack.utils.DebugUtils;
import org.zstack.utils.gson.JSONObjectUtil;
import java.util.Map;
@Configurable(preConstruction = true, autowire = Autowire.BY_TYPE)
public class VmAllocatePrimaryStorageForAttachingDiskFlow implements Flow {
@Autowired
protected DatabaseFacade dbf;
@Autowired
protected CloudBus bus;
@Autowired
protected ErrorFacade errf;
@Override
public void run(final FlowTrigger chain, final Map data) {
final VolumeInventory volume = (VolumeInventory) data.get(VmInstanceConstant.Params.AttachingVolumeInventory.toString());
final VmInstanceSpec spec = (VmInstanceSpec) data.get(VmInstanceConstant.Params.VmInstanceSpec.toString());
String hostUuid = spec.getVmInventory().getHostUuid() == null ? spec.getVmInventory().getLastHostUuid() : spec.getVmInventory().getHostUuid();
DebugUtils.Assert(hostUuid != null, String.format(
"hostUuid from VmInventory should not be null, the vmInventory is [%s]",
JSONObjectUtil.toJsonString(spec.getVmInventory())));
HostVO hvo = dbf.findByUuid(hostUuid, HostVO.class);
HostInventory hinv = HostInventory.valueOf(hvo);
spec.setDestHost(hinv);
AllocatePrimaryStorageMsg msg = new AllocatePrimaryStorageMsg();
msg.setSize(volume.getSize());
msg.setPurpose(PrimaryStorageAllocationPurpose.CreateVolume.toString());
msg.setRequiredHostUuid(hinv.getUuid());
msg.setDiskOfferingUuid(volume.getDiskOfferingUuid());
msg.setServiceId(bus.makeLocalServiceId(PrimaryStorageConstant.SERVICE_ID));
bus.send(msg, new CloudBusCallBack(chain) {
@Override
public void run(MessageReply reply) {
if (reply.isSuccess()) {
AllocatePrimaryStorageReply ar = (AllocatePrimaryStorageReply)reply;
data.put(VmInstanceConstant.Params.DestPrimaryStorageInventoryForAttachingVolume.toString(), ar.getPrimaryStorageInventory());
data.put(VmAllocatePrimaryStorageForAttachingDiskFlow.class, ar.getSize());
chain.next();
} else {
chain.fail(reply.getError());
}
}
});
}
@Override
public void rollback(FlowRollback chain, Map data) {
Long size = (Long) data.get(VmAllocatePrimaryStorageForAttachingDiskFlow.class);
if (size != null) {
PrimaryStorageInventory pri = (PrimaryStorageInventory) data.get(VmInstanceConstant.Params.DestPrimaryStorageInventoryForAttachingVolume.toString());
IncreasePrimaryStorageCapacityMsg imsg = new IncreasePrimaryStorageCapacityMsg();
imsg.setPrimaryStorageUuid(pri.getUuid());
imsg.setDiskSize(size);
bus.makeTargetServiceIdByResourceUuid(imsg, PrimaryStorageConstant.SERVICE_ID, pri.getUuid());
bus.send(imsg);
}
chain.rollback();
}
}