package org.zstack.simulator;
import org.springframework.beans.factory.annotation.Autowired;
import org.zstack.core.cloudbus.CloudBus;
import org.zstack.core.db.DatabaseFacade;
import org.zstack.core.db.SimpleQuery;
import org.zstack.core.errorcode.ErrorFacade;
import org.zstack.header.core.Completion;
import org.zstack.header.errorcode.ErrorCode;
import org.zstack.header.host.HypervisorType;
import org.zstack.header.simulator.SimulatorConstant;
import org.zstack.header.vm.*;
import org.zstack.network.securitygroup.*;
import org.zstack.utils.CollectionUtils;
import org.zstack.utils.Utils;
import org.zstack.utils.function.Function;
import org.zstack.utils.function.ListFunction;
import org.zstack.utils.gson.JSONObjectUtil;
import org.zstack.utils.logging.CLogger;
import java.util.*;
public class SimulatorSecurityGroupBackend implements
SecurityGroupHypervisorBackend, VmInstanceStateChangeNotifyPoint {
private static CLogger logger = Utils.getLogger(SimulatorSecurityGroupBackend.class);
private Map<String, Set<SecurityGroupRuleTO>> rules = new HashMap<String, Set<SecurityGroupRuleTO>>();
public volatile boolean securityGroupSuccess = true;
@Autowired
private CloudBus bus;
@Autowired
private ErrorFacade errf;
@Autowired
private DatabaseFacade dbf;
@Override
public void applyRules(HostRuleTO hto, Completion complete) {
logger.debug(String.format("apply security rules to simulator host[uuid:%s]:\n%s", hto.getHostUuid(), JSONObjectUtil.toJsonString(hto.getRules())));
if (!securityGroupSuccess) {
ErrorCode errorCode = errf.stringToOperationError("on purpose");
complete.fail(errorCode);
return;
}
if (hto.isRefreshHost()) {
rules.remove(hto.getHostUuid());
}
Set<SecurityGroupRuleTO> oldTos = rules.get(hto.getHostUuid());
if (oldTos == null) {
Set<SecurityGroupRuleTO> tos = new HashSet<SecurityGroupRuleTO>();
tos.addAll(hto.getRules());
rules.put(hto.getHostUuid(), tos);
} else {
oldTos.removeAll(hto.getRules());
oldTos.addAll(hto.getRules());
}
complete.success();
}
@Override
public void cleanUpUnusedRuleOnHost(String hostUuid, Completion completion) {
SimpleQuery<VmInstanceVO> q = dbf.createQuery(VmInstanceVO.class);
q.add(VmInstanceVO_.hostUuid, SimpleQuery.Op.EQ, hostUuid);
List<VmInstanceVO> vms = q.list();
List<VmNicVO> nics = CollectionUtils.transformToList(vms, new ListFunction<VmNicVO, VmInstanceVO>() {
@Override
public List<VmNicVO> call(VmInstanceVO arg) {
List<VmNicVO> lst = new ArrayList<VmNicVO>();
lst.addAll(arg.getVmNics());
return lst;
}
});
List<String> nicNames = CollectionUtils.transformToList(nics, new Function<String, VmNicVO>() {
@Override
public String call(VmNicVO arg) {
return arg.getInternalName();
}
});
Set<SecurityGroupRuleTO> tos = rules.get(hostUuid);
Set<SecurityGroupRuleTO> ntos = new HashSet<SecurityGroupRuleTO>();
for (SecurityGroupRuleTO to : tos) {
if (nicNames.contains(to.getVmNicInternalName())) {
ntos.add(to);
}
}
rules.put(hostUuid, ntos);
completion.success();
}
public Set<SecurityGroupRuleTO> getRulesOnHost(String hostUuid) {
return rules.get(hostUuid);
}
public SecurityGroupRuleTO getRulesOnHost(String hostUuid, String vmNicName) {
Set<SecurityGroupRuleTO> tos = getRulesOnHost(hostUuid);
if (tos == null) {
return null;
}
for (SecurityGroupRuleTO to : tos) {
if (to.getVmNicInternalName().equals(vmNicName)) {
return to;
}
}
return null;
}
public List<RuleTO> getRulesByNicName(String nicName) {
for (Set<SecurityGroupRuleTO> rs : rules.values()) {
for (SecurityGroupRuleTO sto : rs) {
if (sto.getVmNicInternalName().equals(nicName)) {
return sto.getRules();
}
}
}
return null;
}
@Override
public HypervisorType getSecurityGroupBackendHypervisorType() {
return HypervisorType.valueOf(SimulatorConstant.SIMULATOR_HYPERVISOR_TYPE);
}
@Override
public void notifyVmInstanceStateChange(VmInstanceInventory inv, VmInstanceState previousState, VmInstanceState currentState) {
if (previousState == VmInstanceState.Unknown && currentState == VmInstanceState.Running) {
RefreshSecurityGroupRulesOnVmMsg msg = new RefreshSecurityGroupRulesOnVmMsg();
msg.setVmInstanceUuid(inv.getUuid());
msg.setServiceId(bus.makeLocalServiceId(SecurityGroupConstant.SERVICE_ID));
bus.send(msg);
}
}
@Override
public HypervisorType getSupportedHypervisorTypeForVmInstanceStateChangeNotifyPoint() {
return HypervisorType.valueOf(SimulatorConstant.SIMULATOR_HYPERVISOR_TYPE);
}
}