package com.microsoft.dhalion; import com.google.inject.AbstractModule; import com.google.inject.Guice; import com.google.inject.Injector; import com.google.inject.Singleton; import com.google.inject.name.Names; import com.microsoft.dhalion.api.IHealthPolicy; import com.microsoft.dhalion.api.MetricsProvider; import com.microsoft.dhalion.conf.Config; import com.microsoft.dhalion.conf.ConfigBuilder; import com.microsoft.dhalion.conf.Key; import com.microsoft.dhalion.conf.PolicyConfig; import com.microsoft.dhalion.policy.PoliciesExecutor; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.CommandLineParser; import org.apache.commons.cli.DefaultParser; import org.apache.commons.cli.HelpFormatter; import org.apache.commons.cli.Option; import org.apache.commons.cli.Options; import org.apache.commons.cli.ParseException; import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.concurrent.ExecutionException; import java.util.concurrent.ScheduledFuture; import java.util.logging.Logger; public class HealthManager { public static final String CONF_DIR = "conf.dir"; private static final Logger LOG = Logger.getLogger(HealthManager.class.getName()); private final String configDir; private Injector injector; private Config config; private List<IHealthPolicy> healthPolicies = new ArrayList<>(); private final MetricsProvider metricsProvider; enum CliArgs { CONFIG_DIR("config_dir"); private String text; CliArgs(String name) { this.text = name; } public String text() { return text; } } public static void main(String[] args) throws Exception { CommandLineParser parser = new DefaultParser(); Options slaManagerCliOptions = constructCliOptions(); // parse the help options first. Options helpOptions = constructHelpOptions(); CommandLine cmd = parser.parse(helpOptions, args, true); if (cmd.hasOption("h")) { usage(slaManagerCliOptions); return; } try { cmd = parser.parse(slaManagerCliOptions, args); } catch (ParseException e) { usage(slaManagerCliOptions); throw new RuntimeException("Error parsing command line options: ", e); } LOG.info("Initializing the health manager"); HealthManager healthmgr = new HealthManager(cmd); healthmgr.start(); } private HealthManager(CommandLine cmd) throws ClassNotFoundException { this.configDir = getOptionValue(cmd, CliArgs.CONFIG_DIR); AbstractModule module = new AbstractModule() { @Override protected void configure() { bind(String.class) .annotatedWith(Names.named(CONF_DIR)) .toInstance(configDir); } }; injector = Guice.createInjector(module); //Read healthmgr.yaml and create a hashmap with the configurations ConfigBuilder confBuilder = new ConfigBuilder(configDir); confBuilder.loadConfig(Paths.get(configDir, (String) Key.HEALTHMGR_CONF.getDefault())); Map<String, Object> conf = confBuilder.getKeyValues(); ConfigBuilder cb = injector.getInstance(ConfigBuilder.class); cb.loadConfig(conf).loadPolicyConf(); config = cb.build(); //Read the MetricsProvider class String metricsProviderClass = (String) conf.get(Key.METRICS_PROVIDER_CLASS.value()); Class<MetricsProvider> mpClass = (Class<MetricsProvider>) this.getClass().getClassLoader().loadClass(metricsProviderClass); injector = injector.createChildInjector(new AbstractModule() { @Override protected void configure() { bind(Config.class).toInstance(config); bind(mpClass).in(Singleton.class); } }); metricsProvider = injector.getInstance(mpClass); injector = injector.createChildInjector(new AbstractModule() { @Override protected void configure() { bind(MetricsProvider.class).toInstance(metricsProvider); } }); initializePolicies(); } private void initializePolicies() throws ClassNotFoundException { for (PolicyConfig policyConf : config.policies()) { String policyClassName = policyConf.policyClass(); LOG.info(String.format("Initializing %s with class %s", policyConf.id(), policyClassName)); Class<IHealthPolicy> policyClass = (Class<IHealthPolicy>) this.getClass().getClassLoader().loadClass(policyClassName); AbstractModule module = constructPolicySpecificModule(policyConf); IHealthPolicy policy = injector.createChildInjector(module).getInstance(policyClass); healthPolicies.add(policy); } } private AbstractModule constructPolicySpecificModule(final PolicyConfig policyConfig) { return new AbstractModule() { @Override protected void configure() { bind(PolicyConfig.class).toInstance(policyConfig); } }; } private void start() throws InterruptedException, ExecutionException { LOG.info("Starting Health Manager"); PoliciesExecutor policyExecutor = new PoliciesExecutor(healthPolicies); ScheduledFuture<?> future = policyExecutor.start(); try { future.get(); } finally { policyExecutor.destroy(); metricsProvider.close(); } } private static Options constructCliOptions() { Options options = new Options(); Option configFile = Option.builder("p") .desc("Path of the config files") .longOpt(CliArgs.CONFIG_DIR.text) .hasArgs() .required() .argName("config path") .build(); options.addOption(configFile); return options; } // construct command line help options private static Options constructHelpOptions() { Options options = new Options(); Option help = Option.builder("h") .desc("List all options and their description") .longOpt("help") .build(); options.addOption(help); return options; } // Print usage options private static void usage(Options options) { HelpFormatter formatter = new HelpFormatter(); formatter.printHelp(HealthManager.class.getSimpleName(), options); } private String getOptionValue(CommandLine cmd, CliArgs argName) { return cmd.getOptionValue(argName.text, null); } }