@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(); }
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; }