package org.zstack.storage.ceph.primary;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.zstack.core.cloudbus.CloudBus;
import org.zstack.core.db.DatabaseFacade;
import org.zstack.header.core.workflow.Flow;
import org.zstack.header.core.workflow.FlowTrigger;
import org.zstack.header.core.workflow.NoRollbackFlow;
import org.zstack.header.errorcode.OperationFailureException;
import org.zstack.header.host.HostConnectionReestablishExtensionPoint;
import org.zstack.header.host.HostException;
import org.zstack.header.host.HostInventory;
import org.zstack.header.host.HypervisorType;
import org.zstack.header.message.MessageReply;
import org.zstack.header.storage.primary.PrimaryStorageConstant;
import org.zstack.kvm.KVMConstant;
import org.zstack.kvm.KVMHostConnectExtensionPoint;
import org.zstack.kvm.KVMHostConnectedContext;
import org.zstack.kvm.KVMHostFactory;
import org.zstack.storage.ceph.CephConstants;
import org.zstack.utils.CollectionUtils;
import org.zstack.utils.function.Function;
import javax.persistence.TypedQuery;
import java.util.List;
import java.util.Map;
import static org.zstack.utils.CollectionDSL.list;
/**
* Created by frank on 8/17/2015.
*/
public class CephKvmExtension implements KVMHostConnectExtensionPoint, HostConnectionReestablishExtensionPoint {
@Autowired
private CloudBus bus;
@Autowired
private DatabaseFacade dbf;
@Override
public void connectionReestablished(HostInventory inv) throws HostException {
if (!KVMConstant.KVM_HYPERVISOR_TYPE.equals(inv.getHypervisorType())) {
return;
}
createSecret(inv.getUuid(), inv.getClusterUuid());
}
@Override
public HypervisorType getHypervisorTypeForReestablishExtensionPoint() {
return KVMHostFactory.hypervisorType;
}
@Transactional(readOnly = true)
private List<String> findCephPrimaryStorage(String clusterUuid) {
String sql = "select pri.uuid from PrimaryStorageVO pri, PrimaryStorageClusterRefVO ref where" +
" ref.clusterUuid = :cuuid and pri.uuid = ref.primaryStorageUuid and pri.type = :ptype";
TypedQuery<String> q = dbf.getEntityManager().createQuery(sql, String.class);
q.setParameter("cuuid", clusterUuid);
q.setParameter("ptype", CephConstants.CEPH_PRIMARY_STORAGE_TYPE);
return q.getResultList();
}
private void createSecret(final String hostUuid, String clusterUuid) {
List<String> psUuids = findCephPrimaryStorage(clusterUuid);
if (psUuids.isEmpty()) {
return;
}
List<CreateKvmSecretMsg> msgs = CollectionUtils.transformToList(psUuids, new Function<CreateKvmSecretMsg, String>() {
@Override
public CreateKvmSecretMsg call(String puuid) {
CreateKvmSecretMsg msg = new CreateKvmSecretMsg();
msg.setPrimaryStorageUuid(puuid);
msg.setHostUuids(list(hostUuid));
bus.makeTargetServiceIdByResourceUuid(msg, PrimaryStorageConstant.SERVICE_ID, puuid);
return msg;
}
});
List<MessageReply> replies = bus.call(msgs);
for (MessageReply r : replies) {
if (!r.isSuccess()) {
throw new OperationFailureException(r.getError());
}
}
}
@Override
public Flow createKvmHostConnectingFlow(final KVMHostConnectedContext context) {
return new NoRollbackFlow() {
String __name__ = "prepare-ceph-primary-storage";
@Override
public void run(FlowTrigger trigger, Map data) {
//TODO: change to async
createSecret(context.getInventory().getUuid(), context.getInventory().getClusterUuid());
trigger.next();
}
};
}
}