package io.cattle.platform.core.dao.impl;
import static io.cattle.platform.core.model.tables.AccountTable.*;
import static io.cattle.platform.core.model.tables.HostTable.*;
import static io.cattle.platform.core.model.tables.StorageDriverTable.*;
import static io.cattle.platform.core.model.tables.StoragePoolHostMapTable.*;
import static io.cattle.platform.core.model.tables.StoragePoolTable.*;
import static io.cattle.platform.core.model.tables.VolumeStoragePoolMapTable.*;
import static io.cattle.platform.core.model.tables.VolumeTable.*;
import io.cattle.platform.core.constants.CommonStatesConstants;
import io.cattle.platform.core.constants.HostConstants;
import io.cattle.platform.core.constants.VolumeConstants;
import io.cattle.platform.core.dao.GenericMapDao;
import io.cattle.platform.core.dao.GenericResourceDao;
import io.cattle.platform.core.dao.StoragePoolDao;
import io.cattle.platform.core.model.Host;
import io.cattle.platform.core.model.StoragePool;
import io.cattle.platform.core.model.StoragePoolHostMap;
import io.cattle.platform.core.model.Volume;
import io.cattle.platform.core.model.VolumeStoragePoolMap;
import io.cattle.platform.core.model.tables.records.StoragePoolHostMapRecord;
import io.cattle.platform.core.model.tables.records.StoragePoolRecord;
import io.cattle.platform.db.jooq.dao.impl.AbstractJooqDao;
import io.cattle.platform.object.ObjectManager;
import io.cattle.platform.object.process.ObjectProcessManager;
import io.github.ibuildthecloud.gdapi.id.IdFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.inject.Inject;
import javax.inject.Named;
import org.jooq.Record;
import org.jooq.Record2;
import org.jooq.RecordHandler;
@Named
public class StoragePoolDaoImpl extends AbstractJooqDao implements StoragePoolDao {
@Inject
GenericResourceDao resourceDao;
@Inject
GenericMapDao genericMapDao;
@Inject
ObjectManager objectManager;
@Inject
ObjectProcessManager objectProcessManager;
@Override
public List<? extends StoragePool> findExternalActivePools() {
return create()
.selectFrom(STORAGE_POOL)
.where(
STORAGE_POOL.EXTERNAL.eq(true)
.and(STORAGE_POOL.STATE.eq(CommonStatesConstants.ACTIVE))
).fetch();
}
@Override
public StoragePool mapNewPool(Host host, Map<String, Object> properties) {
return mapNewPool(host.getId(), properties);
}
@Override
public StoragePool mapNewPool(Long hostId, Map<String, Object> properties) {
StoragePool pool = resourceDao.createAndSchedule(StoragePool.class, properties);
resourceDao.createAndSchedule(StoragePoolHostMap.class,
STORAGE_POOL_HOST_MAP.HOST_ID, hostId,
STORAGE_POOL_HOST_MAP.STORAGE_POOL_ID, pool.getId());
return pool;
}
@Override
public List<? extends StoragePool> findStoragePoolByDriverName(Long accountId, String driverName) {
return create().selectFrom(STORAGE_POOL)
.where(STORAGE_POOL.ACCOUNT_ID.eq(accountId))
.and((STORAGE_POOL.REMOVED.isNull().or(STORAGE_POOL.STATE.eq(CommonStatesConstants.REMOVING))))
.and(STORAGE_POOL.DRIVER_NAME.eq(driverName))
.fetchInto(StoragePoolRecord.class);
}
@Override
public List<? extends StoragePoolHostMap> findMapsToRemove(Long storagePoolId) {
return create()
.selectFrom(STORAGE_POOL_HOST_MAP)
.where(STORAGE_POOL_HOST_MAP.STORAGE_POOL_ID.eq(storagePoolId)
.and((STORAGE_POOL_HOST_MAP.REMOVED.isNull()
.or(STORAGE_POOL_HOST_MAP.STATE.eq(CommonStatesConstants.REMOVING)))))
.fetchInto(StoragePoolHostMap.class);
}
@Override
public StoragePoolHostMap findNonremovedMap(Long storagePoolId, Long hostId) {
List<StoragePoolHostMap> maps = objectManager.find(StoragePoolHostMap.class,
STORAGE_POOL_HOST_MAP.STORAGE_POOL_ID,
storagePoolId, STORAGE_POOL_HOST_MAP.HOST_ID, hostId);
for (StoragePoolHostMap map : maps) {
if (map != null && (map.getRemoved() == null
|| map.getState().equals(CommonStatesConstants.REMOVING))) {
return map;
}
}
return null;
}
@Override
public void createStoragePoolHostMap(StoragePoolHostMap map) {
StoragePoolHostMap found = findNonremovedMap(map.getStoragePoolId(), map.getHostId());
if (found == null) {
resourceDao.createAndSchedule(map);
}
}
@Override
public Map<Long, Long> findStoragePoolHostsByDriver(Long accountId, Long storageDriverId) {
final Map<Long, Long> result = new HashMap<>();
create().select(HOST.ID, STORAGE_POOL.ID)
.from(HOST)
.leftOuterJoin(STORAGE_POOL_HOST_MAP)
.on(STORAGE_POOL_HOST_MAP.HOST_ID.eq(HOST.ID))
.leftOuterJoin(STORAGE_POOL)
.on(STORAGE_POOL_HOST_MAP.STORAGE_POOL_ID.eq(STORAGE_POOL.ID)
.and(STORAGE_POOL.STORAGE_DRIVER_ID.eq(storageDriverId)))
.where(STORAGE_POOL.REMOVED.isNull()
.and(STORAGE_POOL_HOST_MAP.REMOVED.isNull())
.and(HOST.ACCOUNT_ID.eq(accountId))
.and(HOST.REMOVED.isNull()))
.fetchInto(new RecordHandler<Record2<Long, Long>>() {
@Override
public void next(Record2<Long, Long> record) {
Long hostId = record.getValue(HOST.ID);
Long storagePoolId = record.getValue(STORAGE_POOL.ID);
if (!result.containsKey(hostId) || storagePoolId != null) {
result.put(hostId, storagePoolId);
}
}
});
return result;
}
@Override
public List<? extends StoragePool> findNonRemovedStoragePoolByDriver(Long storageDriverId) {
return create().select(STORAGE_POOL.fields())
.from(STORAGE_POOL)
.where(STORAGE_POOL.REMOVED.isNull()
.and(STORAGE_POOL.STORAGE_DRIVER_ID.eq(storageDriverId)))
.fetchInto(StoragePoolRecord.class);
}
@Override
public List<Long> findVolumesInUseByServiceDriver(Long serviceId) {
return create().select(VOLUME.ID)
.from(VOLUME)
.join(VOLUME_STORAGE_POOL_MAP)
.on(VOLUME_STORAGE_POOL_MAP.VOLUME_ID.eq(VOLUME.ID))
.join(STORAGE_POOL)
.on(VOLUME_STORAGE_POOL_MAP.STORAGE_POOL_ID.eq(STORAGE_POOL.ID))
.join(STORAGE_DRIVER)
.on(STORAGE_DRIVER.ID.eq(STORAGE_POOL.STORAGE_DRIVER_ID))
.where(STORAGE_DRIVER.REMOVED.isNull()
.and(STORAGE_DRIVER.SERVICE_ID.eq(serviceId))
.and(VOLUME.REMOVED.isNull()))
.fetch().into(Long.class);
}
@Override
public StoragePool associateVolumeToPool(Long volumeId, Long storageDriverId, Long hostId) {
Record record = create().select(STORAGE_POOL.fields())
.from(STORAGE_POOL)
.join(STORAGE_POOL_HOST_MAP)
.on(STORAGE_POOL_HOST_MAP.STORAGE_POOL_ID.eq(STORAGE_POOL.ID))
.where(STORAGE_POOL.STORAGE_DRIVER_ID.eq(storageDriverId)
.and(STORAGE_POOL_HOST_MAP.HOST_ID.eq(hostId)))
.fetchAny();
if (record == null) {
return null;
}
StoragePool storagePool = record.into(StoragePoolRecord.class);
VolumeStoragePoolMap map = genericMapDao.findNonRemoved(VolumeStoragePoolMap.class,
StoragePool.class, storagePool.getId(), Volume.class, volumeId);
if (map == null) {
resourceDao.createAndSchedule(VolumeStoragePoolMap.class,
VOLUME_STORAGE_POOL_MAP.VOLUME_ID, volumeId,
VOLUME_STORAGE_POOL_MAP.STORAGE_POOL_ID, storagePool.getId());
}
return storagePool;
}
@Override
public Map<Long, List<Object>> findHostsForPools(List<Long> ids, final IdFormatter idFormatter) {
final Map<Long, List<Object>> result = new HashMap<>();
create().select(STORAGE_POOL_HOST_MAP.STORAGE_POOL_ID, STORAGE_POOL_HOST_MAP.HOST_ID)
.from(STORAGE_POOL_HOST_MAP)
.where(STORAGE_POOL_HOST_MAP.REMOVED.isNull()
.and(STORAGE_POOL_HOST_MAP.STORAGE_POOL_ID.in(ids)))
.fetchInto(new RecordHandler<Record2<Long, Long>>() {
@Override
public void next(Record2<Long, Long> record) {
Long hostId = record.getValue(STORAGE_POOL_HOST_MAP.HOST_ID);
Long storagePoolId = record.getValue(STORAGE_POOL_HOST_MAP.STORAGE_POOL_ID);
List<Object> pools = result.get(storagePoolId);
if (pools == null) {
pools = new ArrayList<>();
result.put(storagePoolId, pools);
}
pools.add(idFormatter.formatId(HostConstants.TYPE, hostId));
}
});
return result;
}
@Override
public Map<Long, List<Object>> findVolumesForPools(List<Long> ids, final IdFormatter idFormatter) {
final Map<Long, List<Object>> result = new HashMap<>();
create().select(VOLUME_STORAGE_POOL_MAP.STORAGE_POOL_ID, VOLUME_STORAGE_POOL_MAP.VOLUME_ID)
.from(VOLUME_STORAGE_POOL_MAP)
.join(STORAGE_POOL)
.on(STORAGE_POOL.ID.eq(VOLUME_STORAGE_POOL_MAP.STORAGE_POOL_ID))
.where(VOLUME_STORAGE_POOL_MAP.REMOVED.isNull()
.and(STORAGE_POOL.KIND.ne("docker"))
.and(VOLUME_STORAGE_POOL_MAP.STORAGE_POOL_ID.in(ids)))
.fetchInto(new RecordHandler<Record2<Long, Long>>() {
@Override
public void next(Record2<Long, Long> record) {
Long volumeId = record.getValue(VOLUME_STORAGE_POOL_MAP.VOLUME_ID);
Long storagePoolId = record.getValue(VOLUME_STORAGE_POOL_MAP.STORAGE_POOL_ID);
List<Object> pools = result.get(storagePoolId);
if (pools == null) {
pools = new ArrayList<>();
result.put(storagePoolId, pools);
}
pools.add(idFormatter.formatId(VolumeConstants.TYPE, volumeId));
}
});
return result;
}
@Override
public List<? extends StoragePool> findBadPools(int count) {
return create().select(STORAGE_POOL.fields())
.from(STORAGE_POOL)
.join(ACCOUNT)
.on(ACCOUNT.ID.eq(STORAGE_POOL.ACCOUNT_ID))
.where(STORAGE_POOL.REMOVED.isNull()
.and(ACCOUNT.STATE.eq(CommonStatesConstants.PURGED))
.and(STORAGE_POOL.STATE.notIn(CommonStatesConstants.DEACTIVATING, CommonStatesConstants.REMOVING)))
.limit(count)
.fetchInto(StoragePoolRecord.class);
}
@Override
public List<? extends StoragePool> findBadDockerPools(int count) {
return create().select(STORAGE_POOL.fields())
.from(STORAGE_POOL)
.join(STORAGE_POOL_HOST_MAP)
.on(STORAGE_POOL_HOST_MAP.STORAGE_POOL_ID.eq(STORAGE_POOL.ID))
.join(HOST)
.on(HOST.ID.eq(STORAGE_POOL_HOST_MAP.HOST_ID))
.where(STORAGE_POOL.REMOVED.isNull()
.and(STORAGE_POOL.KIND.eq("docker"))
.and(HOST.STATE.eq(CommonStatesConstants.PURGED))
.and(STORAGE_POOL.STATE.notIn(CommonStatesConstants.DEACTIVATING, CommonStatesConstants.REMOVING)))
.limit(count)
.fetchInto(StoragePoolRecord.class);
}
@Override
public List<? extends StoragePoolHostMap> findBadPoolMapss(int limit) {
return create().select(STORAGE_POOL_HOST_MAP.fields())
.from(STORAGE_POOL_HOST_MAP)
.join(STORAGE_POOL)
.on(STORAGE_POOL.ID.eq(STORAGE_POOL_HOST_MAP.STORAGE_POOL_ID))
.join(HOST)
.on(HOST.ID.eq(STORAGE_POOL_HOST_MAP.HOST_ID))
.where(STORAGE_POOL_HOST_MAP.REMOVED.isNull()
.and(HOST.STATE.eq(CommonStatesConstants.PURGED).or(STORAGE_POOL.STATE.eq(CommonStatesConstants.PURGED))))
.limit(limit)
.fetchInto(StoragePoolHostMapRecord.class);
}
}