JClouds-Chef not bootstrapping & configuring VM

佐手、 提交于 2019-12-12 02:55:15

问题


I am trying to get the following JClouds-Chef code (v1.7.3) to bootstrap Chef Client on a brand new Linux VM and then execute a run list to actually configure that VM with an app stack (typical_app):

public class ChefPlugin {
    public static void main(String[] args) {
        ChefPlugin.provision();
        System.out.println("And done!");
        System.exit(0);
    }

    public static provision() {
        String vmIp = "myapp01";
        String vmSshUsername = "myadmin";
        String vmSshPassword = "12345";

        String endpoint = "https://mychefserver";
        String client = "myuser";
        String validator = "chef-validator";
        String clientCredential = Files.toString(new File("C:\\Users\\myuser\\sandbox\\chef\\myuser.pem"), Charsets.UTF_8);
        String validatorCredential = Files.toString(new File("C:\\Users\\myuser\\sandbox\\chef\\chef-validator.pem"), Charsets.UTF_8);

        Properties props = new Properties();
        props.put(ChefProperties.CHEF_VALIDATOR_NAME, validator);
        props.put(ChefProperties.CHEF_VALIDATOR_CREDENTIAL, validatorCredential);
        props.put(Constants.PROPERTY_RELAX_HOSTNAME, "true");
        props.put(Constants.PROPERTY_TRUST_ALL_CERTS, "true");

        System.out.println("Setup complete.");

        ChefContext ctx = ContextBuilder.newBuilder("chef")
            .endpoint(endpoint)
            .credentials(client, clientCredential)
            .overrides(props)
            .modules(ImmutableSet.of(new SshjSshClientModule())) //
            .buildView(ChefContext.class);
        ChefService chef = ctx.getChefService();

        List<String> runlist = new RunListBuilder().addRole("typicalapp").build();

        ArrayList<String> runList2 = new ArrayList<String>();
        for(String item : runlist) {
            runList2.add(item);
        }

        BootstrapConfig bootstrapConfig = BootstrapConfig.builder().runList(runList2).build();

        System.out.println("Configured the bootstrapper.");

        chef.updateBootstrapConfigForGroup("jclouds-chef", bootstrapConfig);
        Statement bootstrap = chef.createBootstrapScriptForGroup("jclouds-chef");
        SshClient.Factory sshFactory = ctx.unwrap().utils()
            .injector().getInstance(Key.get(new TypeLiteral<SshClient.Factory>() {}));
        SshClient ssh = sshFactory.create(HostAndPort.fromParts(vmIp, 22),
        LoginCredentials.builder().user(vmSshUsername).password(vmSshPassword).build());

        ssh.connect();

        System.out.println("Connected to SSH.");
        try {
            String rawScript = bootstrap.render(OsFamily.UNIX);
            System.out.println("Raw script rendered.");
            ExecResponse result = ssh.exec(rawScript);

            System.out.println("Bootstrap script executed...");
        } catch(Throwable t) {
            System.out.println("Exception: " + t.getMessage());
        } finally {
            ssh.disconnect();
            System.out.println("SSH closed.");
        }
    }
}

When I run this I get the following output from SLF4J:

Setup complete.
Configured the bootstrapper.
[main] INFO net.schmizz.sshj.common.SecurityUtils - BouncyCastle registration succeeded
[main] WARN net.schmizz.sshj.DefaultConfig - Disabling high-strength ciphers: cipher strengths apparently limited by JCE policy
[main] INFO net.schmizz.sshj.transport.TransportImpl - Client identity string: SSH-2.0-SSHJ_0_8_1_SNAPSHOT
[main] INFO net.schmizz.sshj.transport.TransportImpl - Server identity string: SSH-2.0-OpenSSH_6.6p1 Ubuntu-2ubuntu1
Connected to SSH.
Raw script rendered.
[main] INFO net.schmizz.sshj.connection.channel.direct.SessionChannel - Will request to exec `setupPublicCurl || exit 1
curl -q -s -S -L --connect-timeout 10 --max-time 600 --retry 20 -X GET  https://www.opscode.com/chef/install.sh |(bash)
mkdir -p /etc/chef
cat >> /etc/chef/client.rb <<-'END_OF_JCLOUDS_FILE'
    require 'rubygems'
    require 'ohai'
    o = Ohai::System.new
    o.all_plugins
    node_name "jclouds-chef-" + o[:ipaddress]
    log_level :info
    log_location STDOUT
    validation_client_name "chef-validator"
    chef_server_url "https://mychefserver"
END_OF_JCLOUDS_FILE
cat >> /etc/chef/validation.pem <<-'END_OF_JCLOUDS_FILE'
    -----BEGIN RSA PRIVATE KEY-----
    <omitted for security purposes>
    -----END RSA PRIVATE KEY-----

END_OF_JCLOUDS_FILE
cat >> /etc/chef/first-boot.json <<-'END_OF_JCLOUDS_FILE'
    {"id":"jclouds-chef","run_list":["role[typical_app]"]}
END_OF_JCLOUDS_FILE
chef-client -j /etc/chef/first-boot.json
`
Bootstrap script executed...
[main] INFO net.schmizz.sshj.transport.TransportImpl - Disconnected - BY_APPLICATION
SSH closed.
And done!

When I SSH onto the server (myapp01), if I run which ruby I see that Ruby is installed. However which chef-client produces no output, and neither does which java. There is also no /etc/chef directory on the server. This makes me think that my code is only partially working, and perhaps only installing Ruby on the VM but nothing else. On top of this, unless I place a System.exit(0) after the "And done!" print statement, the code never exits. THis makes me think that there is a background/worker thread (maybe an SSH process doing something on the server) not returning/finishing.

There are no errors or exceptions that get thrown here.

My questions:

  1. Can anyone see why this code isn't working (by "working", I mean, seems to only be partially installing Chef Client, and is not even installing Java, which is a part of the typical_app role)?
  2. Am I missing anything in my code to prevent a background thread from finishing? Why does it never exit?

To reproduce, use the following Maven POM to pull down dependencies, and then run the code above, exactly as it is (just use your own Chef server and Linux VM).

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <properties>
        <jclouds.version>1.7.3</jclouds.version>
    </properties>
    <groupId>com.mycompany.app</groupId>
    <artifactId>my-app</artifactId>
    <version>1.0-SNAPSHOT</version>
    <dependencies>
        <dependency>
            <groupId>org.apache.jclouds.driver</groupId>
            <artifactId>jclouds-sshj</artifactId>
            <version>${jclouds.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.jclouds.api</groupId>
            <artifactId>chef</artifactId>
            <version>${jclouds.version}</version>
        </dependency>
    </dependencies>
</project>

Update: here is my /tmp/stderr file I get after running @Ignasi Barrera's suggested changes:

--2014-07-22 10:58:14--  https://opscode-omnibus-packages.s3.amazonaws.com/ubuntu/13.04/x86_64/chef_11.12.8-2_amd64.deb
Resolving opscode-omnibus-packages.s3.amazonaws.com (opscode-omnibus-packages.s3.amazonaws.com)... 176.32.100.240
Connecting to opscode-omnibus-packages.s3.amazonaws.com (opscode-omnibus-packages.s3.amazonaws.com)|176.32.100.240|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 33399362 (32M) [application/x-debian-package]
Saving to: ‘/tmp/install.sh.10185/chef_11.12.8-2_amd64.deb’

    0K .......... .......... .......... .......... ..........  0%  908K 36s
   50K .......... .......... .......... .......... ..........  0% 1.13M 32s
  100K .......... .......... .......... .......... ..........  0% 26.9M 22s
  150K .......... .......... .......... .......... ..........  0% 1.36M 22s
  200K .......... .......... .......... .......... ..........  0% 17.2M 18s
... omitted for brevity
32400K .......... .......... .......... .......... .......... 99% 2.64M 0s
32450K .......... .......... .......... .......... .......... 99% 26.2M 0s
32500K .......... .......... .......... .......... .......... 99% 31.9M 0s
32550K .......... .......... .......... .......... .......... 99% 6.12M 0s
32600K .......... ......                                     100% 4.09M=7.1s

2014-07-22 10:58:22 (4.49 MB/s) - ‘/tmp/install.sh.10185/chef_11.12.8-2_amd64.deb’ saved [33399362/33399362]

回答1:


The main challenge here is that you're trying to run a script on a node without using the jclouds compute service. The code uses jclouds-chef to generate a Statement, but that Statement is assumed to be executed by the jclouds compute service, which has its own mechanisms to render the scripts it executes.

In order to get the complete raw script and to be able to execute it directly using a raw SSH connection, a few things must be done manually. In particular, the jclouds-chef script assumes a few bash functions are defined, and those are missing when rendering the script this way.

You should change the creation of the rawString String as follows:

StringBuilder rawScript = new StringBuilder();

Map<String, String> resolvedFunctions = ScriptBuilder.resolveFunctionDependenciesForStatements(
    new HashMap<String, String>(), ImmutableSet.of(bootstrap), OsFamily.UNIX);

ScriptBuilder.writeFunctions(resolvedFunctions, OsFamily.UNIX, rawScript);
rawScript.append(bootstrap.render(OsFamily.UNIX));

ssh.put("/tmp/chef-bootstrap.sh", rawScript.toString());
ExecResponse result = ssh.exec("bash /tmp/chef-bootstrap.sh");

This way the final script will have all the dependent functions. Also note that instead of directly running the script, I've changed the code to upload it, and then run the file locally. This will help you troubleshoot what is going on in case the script fails.

Also note that the script will generate the contents of the /etc/chef directory on each run, so before running it again you might need to delete that directory.



来源:https://stackoverflow.com/questions/24867971/jclouds-chef-not-bootstrapping-configuring-vm

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!