package io.cattle.platform.docker.machine.launch; import static io.cattle.platform.core.model.tables.MachineDriverTable.*; import io.cattle.platform.archaius.util.ArchaiusUtil; import io.cattle.platform.core.model.MachineDriver; import io.cattle.platform.core.model.tables.records.MachineDriverRecord; import io.cattle.platform.json.JsonMapper; import io.cattle.platform.lock.LockCallbackNoReturn; import io.cattle.platform.lock.LockManager; import io.cattle.platform.object.ObjectManager; import io.cattle.platform.object.process.ObjectProcessManager; import io.cattle.platform.object.process.StandardProcess; import io.cattle.platform.util.type.InitializationTask; import java.io.FileNotFoundException; import java.io.InputStream; import java.net.URL; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.inject.Inject; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.netflix.config.DynamicStringProperty; public class MachineDriverLoader implements InitializationTask { public static final DynamicStringProperty CONFIG_FILE = ArchaiusUtil.getString("machine.driver.config"); private static final Logger log = LoggerFactory.getLogger(MachineDriverLoader.class); @Inject LockManager lockManager; @Inject ObjectManager objectManager; @Inject ObjectProcessManager processManager; @Inject JsonMapper jsonMapper; @Override public void start() { // do logic once CONFIG_FILE.addCallback(new Runnable() { @Override public void run() { loadDrivers(); } }); try { loadDrivers(); } catch (Exception e) { log.error("Failed to load drivers.", e); } } public void loadDrivers() { lockManager.lock(new MachineDriverLoaderLock(), new LockCallbackNoReturn() { @Override public void doWithLockNoResult() { String configLocation = CONFIG_FILE.get(); if (StringUtils.isBlank(configLocation)) { return; } InputStream in = null; byte[] configJson = null; DriverConfig dc = null; try { URL configUrl = new URL(configLocation); in = configUrl.openStream(); configJson = IOUtils.toByteArray(in); dc = jsonMapper.readValue(configJson, DriverConfig.class); } catch (FileNotFoundException e) { log.info("Not loading [{}], file is not found", configLocation); return; } catch (Exception e) { log.error("Error while reading machine driver config json.", e); return; } finally { IOUtils.closeQuietly(in); } if (dc.getDrivers() == null || dc.getDrivers().isEmpty()) { return; } List<MachineDriver> driverList = objectManager.find(MachineDriver.class, MACHINE_DRIVER.REMOVED, (Object)null); Map<String, MachineDriver> existingDrivers = new HashMap<>(); for (MachineDriver d : driverList) { existingDrivers.put(d.getName(), d); } for (MachineDriver newDriver : dc.getDrivers()) { if (StringUtils.isBlank(newDriver.getName()) || StringUtils.isBlank(newDriver.getUri())) { log.error("Machine driver invalid. Name and uri must not be blank. Name: {}, Uri: {}", newDriver.getName(), newDriver.getUri()); continue; } if (existingDrivers.containsKey(newDriver.getName())) { MachineDriver existing = existingDrivers.get(newDriver.getName()); if (!StringUtils.equals(existing.getMd5checksum(), newDriver.getMd5checksum()) || !StringUtils.equals(existing.getUri(), newDriver.getUri())) { processManager.executeStandardProcess(StandardProcess.REMOVE, existing, null); } else { continue; } } log.info("Loading machine driver with name {}, uri {}, checksum {}", newDriver.getName(), newDriver.getUri(), newDriver.getMd5checksum()); objectManager.create(newDriver); processManager.scheduleStandardProcess(StandardProcess.CREATE, newDriver, null); } } }); } } class DriverConfig { List<MachineDriverRecord> drivers; public List<MachineDriverRecord> getDrivers() { return drivers; } public void setDrivers(List<MachineDriverRecord> drivers) { this.drivers = drivers; } }