@Override
  public void customize() {
    List<String> commands = Lists.newLinkedList();

    String gitRepoUrl = getEntity().getConfig(NodeJsWebAppService.APP_GIT_REPOSITORY_URL);
    String archiveUrl = getEntity().getConfig(NodeJsWebAppService.APP_ARCHIVE_URL);
    String appName = getEntity().getConfig(NodeJsWebAppService.APP_NAME);
    if (Strings.isNonBlank(gitRepoUrl) && Strings.isNonBlank(archiveUrl)) {
      throw new IllegalStateException(
          "Only one of Git or archive URL must be set for " + getEntity());
    } else if (Strings.isNonBlank(gitRepoUrl)) {
      commands.add(String.format("git clone %s %s", gitRepoUrl, appName));
      commands.add(String.format("cd %s", appName));
    } else if (Strings.isNonBlank(archiveUrl)) {
      ArchiveUtils.deploy(archiveUrl, getMachine(), getRunDir());
    } else {
      throw new IllegalStateException(
          "At least one of Git or archive URL must be set for " + getEntity());
    }

    commands.add(BashCommands.ifFileExistsElse1("package.json", "npm install"));
    List<String> packages = getEntity().getConfig(NodeJsWebAppService.NODE_PACKAGE_LIST);
    if (packages != null && packages.size() > 0) {
      commands.add(BashCommands.sudo("npm install -g " + Joiner.on(' ').join(packages)));
    }

    newScript(CUSTOMIZING).body.append(commands).execute();
  }
Example #2
0
 private void insertCallback(Entity entity, ConfigKey<String> commandKey, String callback) {
   String command = entity.config().get(commandKey);
   if (Strings.isNonBlank(command)) {
     command = BashCommands.chain(String.format("( %s )", command), callback);
   } else {
     command = callback;
   }
   entity.config().set(commandKey, command);
 }
 protected void appendTemplate(String template, String destination, SshMachineLocation machine) {
   String content = ((BindDnsServerSshDriver) getDriver()).processTemplate(template);
   String temp = "/tmp/template-" + Strings.makeRandomId(6);
   machine.copyTo(new ByteArrayInputStream(content.getBytes()), temp);
   machine.execScript(
       "updating file",
       ImmutableList.of(
           BashCommands.sudo(String.format("tee -a %s < %s", destination, temp)),
           String.format("rm -f %s", temp)));
 }
  /**
   * Sets the machine's hostname to the given value, ensuring /etc/hosts and /etc/sysconfig/network
   * are both correctly updated.
   */
  public String setLocalHostname(SshMachineLocation machine, String hostName, String domainFixed) {
    log.info(
        "Setting local hostname of "
            + machine
            + " to "
            + hostName
            + (Strings.isNonBlank(domainFixed) ? ", " + domainFixed : ""));

    boolean hasDomain = Strings.isNonBlank(domainFixed);
    String fqdn = hasDomain ? hostName + "." + domainFixed : hostName;

    exec(
        machine,
        true,
        BashCommands.sudo(
            String.format(
                "sed -i.bak -e '1i127.0.0.1 %s %s' -e '/^127.0.0.1/d' /etc/hosts", fqdn, hostName)),
        BashCommands.sudo(
            String.format(
                "sed -i.bak -e 's/^HOSTNAME=.*$/HOSTNAME=%s/' /etc/sysconfig/network", fqdn)),
        BashCommands.sudo(String.format("hostname %s", fqdn)));

    return hostName;
  }
  @Override
  public void install() {
    Maybe<Object> url =
        ((EntityInternal) getEntity()).config().getRaw(SoftwareProcess.DOWNLOAD_URL);
    if (url.isPresentAndNonNull()) {
      DownloadResolver resolver = Entities.newDownloader(this);
      List<String> urls = resolver.getTargets();
      downloadedFilename = resolver.getFilename();

      List<String> commands = new LinkedList<String>();
      commands.addAll(BashCommands.commandsToDownloadUrlsAs(urls, downloadedFilename));
      commands.addAll(ArchiveUtils.installCommands(downloadedFilename));

      int result =
          newScript(ImmutableMap.of(INSTALL_INCOMPLETE, true), INSTALLING)
              .failOnNonZeroResultCode(false)
              .body
              .append(commands)
              .execute();

      if (result != 0) {
        // could not install at remote machine; try resolving URL here and copying across
        for (String urlI : urls) {
          result =
              ArchiveUtils.install(
                  getMachine(), urlI, Urls.mergePaths(getInstallDir(), downloadedFilename));
          if (result == 0) break;
        }
        if (result != 0)
          throw new IllegalStateException("Error installing archive: " + downloadedFilename);
      }
    }

    // If downloadUrl did partial install (see INSTALL_INCOMPLETE above) then always execute install
    // so mark it as completed.
    String installCommand = getEntity().getConfig(VanillaSoftwareProcess.INSTALL_COMMAND);
    if (url.isPresentAndNonNull() && Strings.isBlank(installCommand))
      installCommand = "# mark as complete";

    if (Strings.isNonBlank(installCommand)) {
      newScript(INSTALLING)
          .failOnNonZeroResultCode()
          .environmentVariablesReset(getShellEnvironment())
          .body
          .append(installCommand)
          .execute();
    }
  }
  @Override
  public void init() {
    super.init();

    ConfigToAttributes.apply(this, DOCKER_HOST);
    ConfigToAttributes.apply(this, DOCKER_REGISTRY_PORT);

    DockerHost host = (DockerHost) sensors().get(DOCKER_HOST);
    String installDir = host.sensors().get(SoftwareProcess.INSTALL_DIR);
    SshMachineLocation sshMachine = host.getDynamicLocation().getMachine();
    String sshMachineInstallDir = getSSHMachineInstallDir();

    config()
        .set(
            DockerAttributes.DOCKER_PORT_BINDINGS,
            MutableMap.of(sensors().get(DOCKER_REGISTRY_PORT), 5000));
    config()
        .set(
            DockerAttributes.DOCKER_HOST_VOLUME_MAPPING,
            MutableMap.of(Os.mergePaths(installDir, "certs"), "/certs"));

    sshMachine.installTo(
        ImmutableMap.of(SshTool.PROP_PERMISSIONS.getName(), "0755"),
        SCRIPT_LOCATION,
        Os.mergePaths(sshMachineInstallDir, CREATE_CERTS_SCRIPT_NAME));
    sshMachine.installTo(
        config().get(DockerInfrastructure.DOCKER_CA_CERTIFICATE_PATH),
        Os.mergePaths(sshMachineInstallDir, "ca-cert.pem"));
    sshMachine.installTo(
        config().get(DockerInfrastructure.DOCKER_CA_KEY_PATH),
        Os.mergePaths(sshMachineInstallDir, "ca-key.pem"));

    int result =
        sshMachine.execCommands(
            "installCerts",
            ImmutableList.of(
                BashCommands.sudo(
                    String.format(
                        "%s %s %s",
                        Os.mergePaths(sshMachineInstallDir, CREATE_CERTS_SCRIPT_NAME),
                        host.sensors().get(Attributes.ADDRESS),
                        sshMachineInstallDir))));
    if (result != 0) {
      throw new IllegalStateException("Could not create certificates for docker registry");
    }
  }
 protected void configureResolver(Entity entity) {
   Maybe<SshMachineLocation> machine =
       Machines.findUniqueSshMachineLocation(entity.getLocations());
   if (machine.isPresent()) {
     if (getConfig(REPLACE_RESOLV_CONF)) {
       machine.get().copyTo(new StringReader(getConfig(RESOLV_CONF_TEMPLATE)), "/etc/resolv.conf");
     } else {
       appendTemplate(
           getConfig(INTERFACE_CONFIG_TEMPLATE),
           "/etc/sysconfig/network-scripts/ifcfg-eth0",
           machine.get());
       machine
           .get()
           .execScript(
               "reload network", ImmutableList.of(BashCommands.sudo("service network reload")));
     }
     LOG.info("configured resolver on {}", machine);
   } else {
     LOG.debug("{} can't configure resolver at {}: no SshMachineLocation", this, entity);
   }
 }
  @Override
  public void install() {
    String uploadUrl = entity.getConfig(BrooklynNode.DISTRO_UPLOAD_URL);

    // Need to explicitly give file, because for snapshot URLs you don't get a clean filename from
    // the URL.
    // This filename is used to generate the first URL to try: [BROOKLYN_VERSION_BELOW]
    // file://$HOME/.brooklyn/repository/BrooklynNode/0.9.0-SNAPSHOT/brooklynnode-0.8.0-snapshot.tar.gz
    // (DOWNLOAD_URL overrides this and has a default which comes from maven)
    List<String> urls = resolver.getTargets();
    String saveAs = resolver.getFilename();

    newScript("createInstallDir")
        .body
        .append("mkdir -p " + getInstallDir())
        .failOnNonZeroResultCode()
        .execute();

    List<String> commands = Lists.newArrayList();
    // TODO use machine.installTo ... but that only works w a single location currently
    if (uploadUrl != null) {
      // Only upload if not already installed
      boolean exists =
          newScript("checkIfInstalled")
                  .body
                  .append("cd " + getInstallDir(), "test -f BROOKLYN")
                  .execute()
              == 0;
      if (!exists) {
        InputStream distroStream = resource.getResourceFromUrl(uploadUrl);
        getMachine().copyTo(distroStream, getInstallDir() + "/" + saveAs);
      }
    } else {
      commands.addAll(BashCommands.commandsToDownloadUrlsAs(urls, saveAs));
    }
    commands.add(BashCommands.INSTALL_TAR);
    commands.add("tar xzfv " + saveAs);

    newScript(INSTALLING).failOnNonZeroResultCode().body.append(commands).execute();
  }
  protected boolean tryStopPid() {
    Integer pid = entity().getAttribute(Attributes.PID);
    if (pid == null) {
      if (entity().getAttribute(Attributes.SERVICE_STATE_ACTUAL) == Lifecycle.RUNNING
          && getPidFile() == null)
        log.warn(
            "No PID recorded for "
                + entity()
                + " when running, with PID file "
                + getPidFile()
                + "; skipping kill in "
                + Tasks.current());
      else if (log.isDebugEnabled())
        log.debug(
            "No PID recorded for "
                + entity()
                + "; skipping ("
                + entity().getAttribute(Attributes.SERVICE_STATE_ACTUAL)
                + " / "
                + getPidFile()
                + ")");
      return false;
    }

    // allow non-zero exit as process may have already been killed
    DynamicTasks.queue(
            SshEffectorTasks.ssh("kill " + pid, "sleep 5", BashCommands.ok("kill -9 " + pid))
                .allowingNonZeroExitCode()
                .runAsRoot())
        .block();

    if (DynamicTasks.queue(SshEffectorTasks.isPidRunning(pid).runAsRoot()).get()) {
      throw new IllegalStateException(
          "Process for " + entity() + " in " + pid + " still running after kill");
    }
    entity().sensors().set(Attributes.PID, null);
    return true;
  }
  @Override
  public void install() {
    LOG.info("Installing Node.JS {}", getVersion());

    List<String> commands =
        MutableList.<String>builder()
            .add(BashCommands.INSTALL_CURL)
            .add(
                BashCommands.ifExecutableElse0(
                    "apt-get",
                    BashCommands.chain(
                        BashCommands.installPackage(
                            "software-properties-common python-software-properties python g++ make"),
                        BashCommands.sudo("add-apt-repository ppa:chris-lea/node.js"))))
            .add(
                BashCommands.installPackage(
                    MutableMap.of("yum", "git nodejs npm", "apt", "git-core nodejs"), null))
            .add("mkdir -p \"$HOME/.npm\"")
            .add(BashCommands.sudo("npm install -g n"))
            .add(BashCommands.sudo("n " + getVersion()))
            .build();

    newScript(INSTALLING).body.append(commands).execute();
  }
  /**
   * Resolves the on-box dir.
   *
   * <p>Initialize and pre-create the right onbox working dir, if an ssh machine location. Logs a
   * warning if not.
   */
  @SuppressWarnings("deprecation")
  public static String resolveOnBoxDir(EntityInternal entity, MachineLocation machine) {
    String base = entity.getConfig(BrooklynConfigKeys.ONBOX_BASE_DIR);
    if (base == null) base = machine.getConfig(BrooklynConfigKeys.ONBOX_BASE_DIR);
    if (base != null && Boolean.TRUE.equals(entity.getConfig(ON_BOX_BASE_DIR_RESOLVED)))
      return base;
    if (base == null)
      base = entity.getManagementContext().getConfig().getConfig(BrooklynConfigKeys.ONBOX_BASE_DIR);
    if (base == null) base = entity.getConfig(BrooklynConfigKeys.BROOKLYN_DATA_DIR);
    if (base == null) base = machine.getConfig(BrooklynConfigKeys.BROOKLYN_DATA_DIR);
    if (base == null)
      base =
          entity.getManagementContext().getConfig().getConfig(BrooklynConfigKeys.BROOKLYN_DATA_DIR);
    if (base == null) base = "~/brooklyn-managed-processes";
    if (base.equals("~")) base = ".";
    if (base.startsWith("~/")) base = "." + base.substring(1);

    String resolvedBase = null;
    if (entity.getConfig(BrooklynConfigKeys.SKIP_ON_BOX_BASE_DIR_RESOLUTION)
        || machine.getConfig(BrooklynConfigKeys.SKIP_ON_BOX_BASE_DIR_RESOLUTION)) {
      if (log.isDebugEnabled())
        log.debug("Skipping on-box base dir resolution for " + entity + " at " + machine);
      if (!Os.isAbsolutish(base)) base = "~/" + base;
      resolvedBase = Os.tidyPath(base);
    } else if (machine instanceof SshMachineLocation) {
      SshMachineLocation ms = (SshMachineLocation) machine;
      ProcessTaskWrapper<Integer> baseTask =
          SshEffectorTasks.ssh(
                  BashCommands.alternatives(
                      "mkdir -p \"${BASE_DIR}\"",
                      BashCommands.chain(
                          BashCommands.sudo("mkdir -p \"${BASE_DIR}\""),
                          BashCommands.sudo("chown " + ms.getUser() + " \"${BASE_DIR}\""))),
                  "cd ~",
                  "cd ${BASE_DIR}",
                  "echo BASE_DIR_RESULT':'`pwd`:BASE_DIR_RESULT")
              .environmentVariable("BASE_DIR", base)
              .requiringExitCodeZero()
              .summary("initializing on-box base dir " + base)
              .newTask();
      DynamicTasks.queueIfPossible(baseTask).orSubmitAsync(entity);
      resolvedBase =
          Strings.getFragmentBetween(
              baseTask.block().getStdout(), "BASE_DIR_RESULT:", ":BASE_DIR_RESULT");
    }
    if (resolvedBase == null) {
      if (!Os.isAbsolutish(base)) base = "~/" + base;
      resolvedBase = Os.tidyPath(base);
      log.warn(
          "Could not resolve on-box directory for "
              + entity
              + " at "
              + machine
              + "; using "
              + resolvedBase
              + ", though this may not be accurate at the target (and may fail shortly)");
    }
    entity.config().set(BrooklynConfigKeys.ONBOX_BASE_DIR, resolvedBase);
    entity.config().set(ON_BOX_BASE_DIR_RESOLVED, true);
    return resolvedBase;
  }