package io.cattle.platform.core.dao.impl; import static io.cattle.platform.core.model.tables.AccountTable.*; import static io.cattle.platform.core.model.tables.AgentTable.*; import static io.cattle.platform.core.model.tables.HostIpAddressMapTable.*; import static io.cattle.platform.core.model.tables.HostTable.*; import static io.cattle.platform.core.model.tables.InstanceHostMapTable.*; import static io.cattle.platform.core.model.tables.InstanceTable.*; import static io.cattle.platform.core.model.tables.IpAddressTable.*; import static io.cattle.platform.core.model.tables.PhysicalHostTable.*; import io.cattle.platform.core.constants.AgentConstants; import io.cattle.platform.core.constants.CommonStatesConstants; import io.cattle.platform.core.constants.HostConstants; import io.cattle.platform.core.constants.InstanceConstants; import io.cattle.platform.core.constants.MachineConstants; import io.cattle.platform.core.dao.GenericResourceDao; import io.cattle.platform.core.dao.HostDao; import io.cattle.platform.core.model.Host; import io.cattle.platform.core.model.IpAddress; import io.cattle.platform.core.model.PhysicalHost; import io.cattle.platform.core.model.tables.records.HostRecord; import io.cattle.platform.core.model.tables.records.IpAddressRecord; import io.cattle.platform.core.model.tables.records.PhysicalHostRecord; import io.cattle.platform.db.jooq.dao.impl.AbstractJooqDao; import io.cattle.platform.deferred.util.DeferredUtils; import io.cattle.platform.object.ObjectManager; import io.cattle.platform.object.util.DataAccessor; import io.cattle.platform.object.util.DataUtils; import io.cattle.platform.util.resource.UUID; import io.github.ibuildthecloud.gdapi.id.IdFormatter; import java.util.ArrayList; import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.Callable; import javax.inject.Inject; import javax.inject.Named; import org.jooq.Record2; import org.jooq.RecordHandler; @Named public class HostDaoImpl extends AbstractJooqDao implements HostDao { @Inject ObjectManager objectManager; @Inject GenericResourceDao genericResourceDao; Long startTime; @Override public List<? extends Host> getHosts(Long accountId, List<String> uuids) { return create() .selectFrom(HOST) .where(HOST.ACCOUNT_ID.eq(accountId) .and(HOST.STATE.notIn(CommonStatesConstants.REMOVED, CommonStatesConstants.REMOVING)) .and(HOST.UUID.in(uuids))).fetch(); } @Override public boolean hasActiveHosts(Long accountId) { return create() .select(HOST.ID.count()) .from(HOST) .join(AGENT) .on(AGENT.ID.eq(HOST.AGENT_ID)) .where(HOST.ACCOUNT_ID.eq(accountId) .and(HOST.STATE.in(CommonStatesConstants.ACTIVATING, CommonStatesConstants.ACTIVE, CommonStatesConstants.UPDATING_ACTIVE) .and(AGENT.STATE.in(CommonStatesConstants.ACTIVATING, CommonStatesConstants.ACTIVE, AgentConstants.STATE_FINISHING_RECONNECT, AgentConstants.STATE_RECONNECTED)))) .fetchOneInto(Integer.class) > 0; } @Override public IpAddress getIpAddressForHost(Long hostId) { List<? extends IpAddress> result = create() .select(IP_ADDRESS.fields()) .from(IP_ADDRESS) .join(HOST_IP_ADDRESS_MAP) .on(IP_ADDRESS.ID.eq(HOST_IP_ADDRESS_MAP.IP_ADDRESS_ID)) .where(HOST_IP_ADDRESS_MAP.HOST_ID.eq(hostId) .and(HOST_IP_ADDRESS_MAP.REMOVED.isNull()) .and(IP_ADDRESS.REMOVED.isNull())) .fetchInto(IpAddressRecord.class); return result.size() == 0 ? null : result.get(0); } @Override public Host getHostForIpAddress(long ipAddressId) { List<? extends Host> hosts = create() .select(HOST.fields()) .from(HOST) .join(HOST_IP_ADDRESS_MAP) .on(HOST_IP_ADDRESS_MAP.HOST_ID.eq(HOST.ID)) .where(HOST_IP_ADDRESS_MAP.IP_ADDRESS_ID.eq(ipAddressId) .and(HOST_IP_ADDRESS_MAP.REMOVED.isNull())) .fetchInto(HostRecord.class); if (hosts.isEmpty()) { return null; } return hosts.get(0); } @Override public Map<Long, List<Object>> getInstancesPerHost(List<Long> hosts, final IdFormatter idFormatter) { final Map<Long, List<Object>> result = new HashMap<>(); create().select(INSTANCE_HOST_MAP.INSTANCE_ID, INSTANCE_HOST_MAP.HOST_ID) .from(INSTANCE_HOST_MAP) .join(INSTANCE) .on(INSTANCE.ID.eq(INSTANCE_HOST_MAP.INSTANCE_ID)) .where(INSTANCE_HOST_MAP.REMOVED.isNull() .and(INSTANCE.REMOVED.isNull()) .and(INSTANCE_HOST_MAP.HOST_ID.in(hosts))) .fetchInto(new RecordHandler<Record2<Long, Long>>() { @Override public void next(Record2<Long, Long> record) { Long hostId = record.getValue(INSTANCE_HOST_MAP.HOST_ID); Long instanceId = record.getValue(INSTANCE_HOST_MAP.INSTANCE_ID); List<Object> list = result.get(hostId); if (list == null) { list = new ArrayList<>(); result.put(hostId, list); } list.add(idFormatter.formatId(InstanceConstants.TYPE, instanceId)); } }); return result; } @Override public PhysicalHost createMachineForHost(final Host host) { String uuid = UUID.randomUUID().toString(); final Map<Object, Object> data = new HashMap<Object, Object>(DataUtils.getFields(host)); data.put(PHYSICAL_HOST.KIND, MachineConstants.KIND_MACHINE); data.put(PHYSICAL_HOST.NAME, DataAccessor.fieldString(host, HostConstants.FIELD_HOSTNAME)); data.put(PHYSICAL_HOST.DESCRIPTION, host.getDescription()); data.put(PHYSICAL_HOST.ACCOUNT_ID, host.getAccountId()); data.put(PHYSICAL_HOST.EXTERNAL_ID, uuid); PhysicalHost phyHost = DeferredUtils.nest(new Callable<PhysicalHost>() { @Override public PhysicalHost call() throws Exception { return genericResourceDao.createAndSchedule(PhysicalHost.class, objectManager.convertToPropertiesFor(PhysicalHost.class, data)); } }); objectManager.setFields(host, HOST.PHYSICAL_HOST_ID, phyHost.getId(), HostConstants.FIELD_REPORTED_UUID, uuid); return phyHost; } @Override public Map<Long, PhysicalHost> getPhysicalHostsForHosts(List<Long> hostIds) { Map<Long, PhysicalHost> hosts = new HashMap<>(); List<? extends PhysicalHost> hostList = create().select(PHYSICAL_HOST.fields()) .from(PHYSICAL_HOST) .join(HOST) .on(HOST.PHYSICAL_HOST_ID.eq(PHYSICAL_HOST.ID)) .where(HOST.ID.in(hostIds)) .fetchInto(PhysicalHostRecord.class); for (PhysicalHost host : hostList) { hosts.put(host.getId(), host); } return hosts; } @Override public void updateNullUpdatedHosts() { if (HOST_REMOVE_DELAY.get() < 0) { return; } create().update(HOST) .set(HOST.REMOVE_AFTER, new Date(System.currentTimeMillis() + HOST_REMOVE_DELAY.get() * 1000)) .where(HOST.REMOVE_AFTER.isNull()) .execute(); } @Override public List<? extends Host> findHostsRemove() { if (startTime == null) { startTime = System.currentTimeMillis(); } if ((System.currentTimeMillis() - startTime) <= (HOST_REMOVE_START_DELAY.get() * 1000)) { return Collections.emptyList(); } return create().select(HOST.fields()) .from(HOST) .join(AGENT) .on(AGENT.ID.eq(HOST.AGENT_ID)) .join(ACCOUNT) .on(ACCOUNT.ID.eq(HOST.ACCOUNT_ID)) .where(AGENT.STATE.eq(AgentConstants.STATE_DISCONNECTED) .and(HOST.STATE.in(CommonStatesConstants.ACTIVE, CommonStatesConstants.INACTIVE)) .and(HOST.REMOVE_AFTER.lt(new Date()))) .fetchInto(HostRecord.class); } }