java - JClouds- Chef : IllegalAccessError on TokenType2?

标签 java chef-infra jclouds

我正在使用 JClouds-Chef使用 Chef Client 引导 Linux VM (myapp01.me.example.com) 的 API,然后运行客户端并通过 typicalapp 使用其应用堆栈配置 VM作用:

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

关于这里发生的事情有什么想法吗?

最佳答案

为了能够引导您的 VM,您将需要以下内容:

  • VM 的 IP 地址。它必须可以访问,打开端口 22(因为 Bootstrap 将通过 SSH 完成)并且可以访问 Internet,以便它可以安装 Ruby 和 Chef。
  • Chef 服务器中的客户端及其对应的私钥。 jclouds 使用该客户端对 Chef Server REST API 执行操作。
  • validator 证书。该证书将上传到节点,以便它可以在 Chef 服务器中自行注册。

在这种情况下,由于未使用 jclouds ComputeService,您必须手动实例化 SSH 客户端以连接到虚拟机,但这应该非常简单。

在您提到的示例中,Git 存储库在使用 ChefSolo 时被克隆,但由于您有 Chef 服务器,您唯一需要做的就是配置连接和所需的运行列表和属性。

执行此操作的最小程序需要以下依赖项:

<!-- 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 错误,因为您的 Chef 端点是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();
}

关于java - JClouds- Chef : IllegalAccessError on TokenType2?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24777085/

相关文章:

linux - 如何在 Linux 中将参数传递给 .run 文件

ssh - 在 openstack 中使用 jclouds 传递 ssh key

java - 使用 jclouds 和 Java 创建具有特定风格的 AWS EC2 实例

java - org.jclouds.openstack.nova.v2_0.domain.ServerCreated API

chef-infra - 设置独特 Chef 节点属性的最佳实践

java - 如何在 Eclipse 中的 Tomcat 中使用导致 InvalidJarIndexException 的损坏的 JAR 索引来追踪 JAR

java - 线程 "main"org.openqa.selenium.NoSuchElementException : An element could not be located on the page using the given search parameters 中出现异常

java - Drools 规则在 Spring Boot Controller 中不起作用,但在 Junit Test 中起作用

chef-infra - 如何保持菜谱的幂等性

java - Hibernate 命名查询不知道错误