JClouds厨师:IllegalAccessError上TokenType2?(JClouds-C

2019-10-20 11:24发布

我现在用的是JClouds厨师 API来引导一个Linux VM( myapp01.me.example.com )与厨师客户端,并再运行客户端,并通过其应用程序堆栈配置VM typicalapp作用:

package com.me.myorg.chef;

import org.jclouds.Constants
import org.jclouds.ContextBuilder
import org.jclouds.chef.ChefContext
import org.jclouds.chef.ChefService
import org.jclouds.chef.config.ChefProperties
import org.jclouds.chef.domain.BootstrapConfig
import org.jclouds.chef.util.RunListBuilder
import org.jclouds.compute.domain.ExecResponse
import org.jclouds.compute.domain.OsFamily
import org.jclouds.domain.LoginCredentials
import org.jclouds.scriptbuilder.domain.Statement
import org.jclouds.ssh.SshClient
import org.jclouds.sshj.config.SshjSshClientModule

import com.google.common.base.Charsets
import com.google.common.collect.ImmutableSet
import com.google.common.io.Files
import com.google.common.net.HostAndPort
import com.google.inject.Key
import com.google.inject.TypeLiteral

public class ChefProvisioner {
    public static void main(String[] args) {
        ChefProvisioner.provision()
    }

    public static provision() {
        String vmIp = "myapp01.me.example.com";     // A Linux VM living in our local vCenter
        String vmSshUsername = "admin";
        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");

        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();
        BootstrapConfig bootstrapConfig = BootstrapConfig.builder().runlist(runlist).build();

        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();
        try {
            String rawScript = bootstrap.render(OsFamily.UNIX);
            ExecResponse result = ssh.exec(rawScript);
        } finally {
            ssh.disconnect();
        }
    }
}

当我运行此我得到:

Exception in thread "main" java.util.ServiceConfigurationError: org.jclouds.apis.ApiMetadata: Provider org.jclouds.openstack.swift.SwiftApiMetadata could not be instantiated: java.lang.IllegalAccessError: tried to access class com.google.common.reflect.TypeResolver from class org.jclouds.util.TypeToken2
    at java.util.ServiceLoader.fail(ServiceLoader.java:224)
    at java.util.ServiceLoader.access$100(ServiceLoader.java:181)
    at java.util.ServiceLoader$LazyIterator.next(ServiceLoader.java:377)
    at java.util.ServiceLoader$1.next(ServiceLoader.java:445)
    at com.google.common.collect.ImmutableCollection$Builder.addAll(ImmutableCollection.java:323)
    at com.google.common.collect.ImmutableSet$Builder.addAll(ImmutableSet.java:633)
    at org.jclouds.apis.Apis.all(Apis.java:72)
    at org.jclouds.apis.Apis.withId(Apis.java:89)
    at org.jclouds.ContextBuilder.newBuilder(ContextBuilder.java:168)
    at org.jclouds.ContextBuilder$newBuilder.call(Unknown Source)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:45)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:108)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:116)
    at com.me.myorg.chef.ChefProvisioner.provision(ChefProvisioner.groovy:51)
    at com.me.myorg.chef.ChefProvisioner$provision.call(Unknown Source)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:45)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:108)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:112)
    at com.me.myorg.chef.ChefProvisioner.main(ChefProvisioner.groovy:27)
Caused by: java.lang.IllegalAccessError: tried to access class com.google.common.reflect.TypeResolver from class org.jclouds.util.TypeToken2
    at org.jclouds.util.TypeToken2.where(TypeToken2.java:47)
    at org.jclouds.rest.internal.BaseRestApiMetadata.contextToken(BaseRestApiMetadata.java:60)
    at org.jclouds.rest.internal.BaseRestApiMetadata$Builder.<init>(BaseRestApiMetadata.java:74)
    at org.jclouds.openstack.swift.SwiftApiMetadata$Builder.<init>(SwiftApiMetadata.java:85)
    at org.jclouds.openstack.swift.SwiftApiMetadata$Builder.<init>(SwiftApiMetadata.java:81)
    at org.jclouds.openstack.swift.SwiftApiMetadata$ConcreteBuilder.<init>(SwiftApiMetadata.java:108)
    at org.jclouds.openstack.swift.SwiftApiMetadata$ConcreteBuilder.<init>(SwiftApiMetadata.java:108)
    at org.jclouds.openstack.swift.SwiftApiMetadata.<init>(SwiftApiMetadata.java:60)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
    at java.lang.Class.newInstance(Class.java:374)
    at java.util.ServiceLoader$LazyIterator.next(ServiceLoader.java:373)
    ... 16 more

任何想法,这是怎么回事?

Answer 1:

你将需要以下,为了能够引导你的虚拟机:

  • 虚拟机的IP地址。 它必须是可达的,有22端口打开(如引导将通过SSH进行),并具有接入互联网,因此它可以安装Ruby和厨师。
  • 厨师服务器在客户端和其相应的私钥。 该客户端使用jclouds兑厨师服务器REST API执行的操作。
  • 验证证书。 该证书将被上传到节点,以便它可以在厨师服务器自行注册。

在这种情况下,如不使用jclouds ComputeService,你必须手动实例化一个SSH客户端连接到虚拟机,但它应该是相当简单的。

在你提到的例子中,Git的回购使用ChefSolo当克隆,但因为你有一个厨师服务器,你需要做的唯一一件事就是配置连接和所需的运行列表和属性。

一个最小的程序要做到这一点就需要下面的依赖关系:

<!-- Required 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>

它可能是类似以下内容:

更新:我已经改变了配置,以匹配提供knife.rb配置,同时还增加了几个属性,以避免SSL错误,因为你的厨师终点为https。

// Configuration
String vmIp = "vm-ip";
String vmSshUsername = "root";
String vmSshPassword = "foo";

String endpoint = "https://mychefserver.example.com";
String client = "myuser";
String validator = "chef-validator";
String clientCredential = Files.toString(new File("/home/myuser/.chef/myuser.pem"), Charsets.UTF_8);
String validatorCredential = Files.toString(new File("/home/myuser/.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");

/* *** First, create the context to connect to the Chef Server *** */

// Create the context and configure the SSH driver to use. sshj in this example
ChefContext ctx = ContextBuilder.newBuilder("chef")
    .endpoint(endpoint)
    .credentials(client, clientCredential)
    .overrides(props)
    .modules(ImmutableSet.of(new SshjSshClientModule())) //
    .buildView(ChefContext.class);
CherService chef = ctx.getChefService();

/* *** Second, generate the bootstrap script *** */

// Generate the bootsrap configuration
List<String> runlist = new RunListBuilder().addRole("typicalapp").build();
BootstrapConfig bootstrapConfig = BootstrapConfig.builder().runlist(runlist).build();

// Generate the bootstrap script to be executed in the VM (this will persist
// the configuration in a data bag under the key 'jclouds-chef' so it can be reused
// and then build the bootstrap script with the information in the configuration data bag)
chef.updateBootstrapConfigForGroup("jclouds-chef", bootstrapConfig);
Statement bootstrap = chef.createBootstrapScriptForGroup("jclouds-chef");

/* *** Finally create an SSH connection manually and run the script on the VM *** */

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();
try {
    String rawScript = bootstrap.render(OsFamily.UNIX);
    ExecResponse result = ssh.exec(rawScript);
} finally {
    ssh.disconnect();
}


文章来源: JClouds-Chef: IllegalAccessError on TokenType2?