package io.cattle.platform.agent.connection.simulator.impl;
import io.cattle.platform.agent.connection.simulator.AgentConnectionSimulator;
import io.cattle.platform.agent.connection.simulator.AgentSimulatorEventProcessor;
import io.cattle.platform.core.constants.HostConstants;
import io.cattle.platform.core.constants.InstanceConstants;
import io.cattle.platform.core.model.Agent;
import io.cattle.platform.eventing.model.Event;
import io.cattle.platform.eventing.model.EventVO;
import io.cattle.platform.framework.event.FrameworkEvents;
import io.cattle.platform.framework.event.Ping;
import io.cattle.platform.json.JsonMapper;
import io.cattle.platform.object.ObjectManager;
import io.cattle.platform.object.meta.ObjectMetaDataManager;
import io.cattle.platform.object.util.DataAccessor;
import io.cattle.platform.util.type.CollectionUtils;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.inject.Inject;
import org.apache.commons.lang3.StringUtils;
public class SimulatorPingProcessor implements AgentSimulatorEventProcessor {
JsonMapper jsonMapper;
ObjectManager objectManager;
@Override
public Event handle(AgentConnectionSimulator simulator, Event event) throws Exception {
if (!FrameworkEvents.PING.equals(event.getName()))
return null;
Agent agent = simulator.getAgent();
Ping ping = jsonMapper.convertValue(event, Ping.class);
Ping pong = jsonMapper.convertValue(EventVO.reply(event).withData(ping.getData()), Ping.class);
if (ping.getOption(Ping.RESOURCES) && !agent.getUri().startsWith("delegate://")) {
addResources(pong, agent);
}
if (ping.getOption(Ping.INSTANCES) && !agent.getUri().startsWith("delegate://")) {
addInstances(simulator, pong, agent);
}
return pong;
}
protected void addInstances(AgentConnectionSimulator simulator, Ping pong, Agent agent) {
List<Map<String, Object>> resources = pong.getData().getResources();
for (Map.Entry<String, Object[]> kv : simulator.getInstances().entrySet()) {
// This matches the data structure returned by the ping logic in the real ping agent.
Map<String, Object> instanceMap = CollectionUtils.asMap(
ObjectMetaDataManager.TYPE_FIELD, InstanceConstants.TYPE,
ObjectMetaDataManager.UUID_FIELD, kv.getKey(),
ObjectMetaDataManager.STATE_FIELD, kv.getValue()[0],
"systemContainer", null,
"dockerId", kv.getValue()[1],
"image", kv.getValue()[2],
"labels", new String[0],
"created", kv.getValue()[3]);
resources.add(instanceMap);
}
String hostUuid = agent.getUuid() + "-" + 0;
Map<String, Object> hostUuidResource = new HashMap<String, Object>();
hostUuidResource.put(ObjectMetaDataManager.TYPE_FIELD, "hostUuid");
hostUuidResource.put(ObjectMetaDataManager.UUID_FIELD, hostUuid);
resources.add(hostUuidResource);
pong.setOption(Ping.INSTANCES, true);
}
protected void addResources(Ping pong, Agent agent) {
List<Map<String, Object>> resources = pong.getData().getResources();
String externalId = DataAccessor.fromDataFieldOf(agent).withScope(AgentConnectionSimulator.class).withKey("externalId").as(jsonMapper,
String.class);
String physicalHostUuid = externalId;
if (StringUtils.isEmpty(physicalHostUuid)) {
physicalHostUuid = agent.getUuid() + "-physical-host";
}
Map<String, Object> physicalHost = new HashMap<String, Object>();
physicalHost.put(ObjectMetaDataManager.UUID_FIELD, physicalHostUuid);
physicalHost.put(ObjectMetaDataManager.KIND_FIELD, "sim");
physicalHost.put(ObjectMetaDataManager.TYPE_FIELD, "physicalHost");
Boolean addPhysicalHost = DataAccessor.fromDataFieldOf(agent).withScope(AgentConnectionSimulator.class).withKey("addPhysicalHost").withDefault(true)
.as(jsonMapper, Boolean.class);
long hosts = DataAccessor.fromDataFieldOf(agent).withScope(AgentConnectionSimulator.class).withKey("hosts").withDefault(1L).as(jsonMapper, Long.class);
long poolsPerHost = DataAccessor.fromDataFieldOf(agent).withScope(AgentConnectionSimulator.class).withKey("storagePoolsPerHost").withDefault(1L).as(
jsonMapper, Long.class);
for (long i = 0; i < hosts; i++) {
String hostUuid = agent.getUuid() + "-" + i;
if (i == 0 && StringUtils.isNotBlank(externalId)) {
hostUuid = externalId;
}
Map<String, Object> host = new HashMap<String, Object>();
host.put(ObjectMetaDataManager.UUID_FIELD, hostUuid);
host.put(ObjectMetaDataManager.KIND_FIELD, "sim");
host.put(ObjectMetaDataManager.TYPE_FIELD, "host");
host.put(ObjectMetaDataManager.NAME_FIELD, "testhost-" + io.cattle.platform.util.resource.UUID.randomUUID());
Long cpu = DataAccessor.fromDataFieldOf(agent).withScope(AgentConnectionSimulator.class)
.withKey(HostConstants.FIELD_MILLI_CPU).as(jsonMapper, Long.class);
if (cpu != null) {
host.put(HostConstants.FIELD_MILLI_CPU, cpu);
}
Long mem = DataAccessor.fromDataFieldOf(agent).withScope(AgentConnectionSimulator.class)
.withKey(HostConstants.FIELD_MEMORY).as(jsonMapper, Long.class);
if (mem != null) {
host.put(HostConstants.FIELD_MEMORY, mem);
}
Long storage = DataAccessor.fromDataFieldOf(agent).withScope(AgentConnectionSimulator.class)
.withKey(HostConstants.FIELD_LOCAL_STORAGE_MB).as(jsonMapper, Long.class);
if (storage != null) {
host.put(HostConstants.FIELD_LOCAL_STORAGE_MB, storage);
}
if (addPhysicalHost) {
host.put("physicalHostUuid", physicalHostUuid);
}
for (long j = 0; j < poolsPerHost; j++) {
String poolUuid = hostUuid + "-" + j;
Map<String, Object> pool = new HashMap<String, Object>();
pool.put(ObjectMetaDataManager.UUID_FIELD, poolUuid);
pool.put(ObjectMetaDataManager.KIND_FIELD, "sim");
pool.put(ObjectMetaDataManager.TYPE_FIELD, "storagePool");
pool.put("hostUuid", hostUuid);
resources.add(pool);
}
/*
* Purposely put host after storagePool so that AgentResourceManager
* will have to reorder then on insert
*/
resources.add(host);
String ipAddress = DataAccessor.fromDataFieldOf(agent)
.withScope(AgentConnectionSimulator.class)
.withKey("ipAddress")
.withDefault("192.168.0.21").as(String.class);
String ipUuid = agent.getUuid() + "-" + ipAddress;
Map<String, Object> ip = new HashMap<>();
ip.put(ObjectMetaDataManager.UUID_FIELD, ipUuid);
ip.put(ObjectMetaDataManager.KIND_FIELD, "sim");
ip.put(ObjectMetaDataManager.TYPE_FIELD, "ipAddress");
ip.put("address", ipAddress);
ip.put("hostUuid", hostUuid);
resources.add(ip);
}
if (addPhysicalHost) {
/*
* Purposely put physical host after host so that
* AgentResourceManager will have to reorder then on insert
*/
resources.add(physicalHost);
}
}
public JsonMapper getJsonMapper() {
return jsonMapper;
}
@Inject
public void setJsonMapper(JsonMapper jsonMapper) {
this.jsonMapper = jsonMapper;
}
public ObjectManager getObjectManager() {
return objectManager;
}
@Inject
public void setObjectManager(ObjectManager objectManager) {
this.objectManager = objectManager;
}
}