使用jclouds

时间:2015-10-24 18:50:00

标签: ssh amazon-ec2 jclouds

我正在尝试使用jclouds 1.9.0创建一个aws实例,然后在其上运行一个脚本(通过ssh)。我正在关注示例locate here但是当客户端(java程序)尝试在实例连接时,我收到身份验证失败错误。 AWS控制台显示该实例已启动并正在运行。

该示例尝试创建LoginCrendentials对象

String user = System.getProperty("user.name");
String privateKey = Files.toString(new File(System.getProperty("user.home") + "/.ssh/id_rsa"), UTF_8);
return LoginCredentials.builder().user(user).privateKey(privateKey).build();

后者从ssh客户端使用

responses = compute.runScriptOnNodesMatching(
                inGroup(groupName),             // predicate used to select nodes
                exec(command),                  // what you actually intend to run
                overrideLoginCredentials(login) // use my local user & ssh key
                        .runAsRoot(false)       // don't attempt to run as root (sudo)
                        .wrapInInitScript(false));

使用以下命令

将一些登录信息注入实例
Statement bootInstructions = AdminAccess.standard();
templateBuilder.options(runScript(bootInstructions));

由于我在Windows机器上,因此创建了LoginCrendentials'失败'因此我将其代码改为

String user = "ec2-user";
String privateKey = "-----BEGIN RSA PRIVATE KEY-----.....-----END RSA PRIVATE KEY-----";
return  LoginCredentials.builder().user(user).privateKey(privateKey).build();

我还要在构建模板时定义凭据,如"EC2: In Depth"指南中所述,但没有运气。

另一种方法是构建实例并按如下方式注入密钥对,但这意味着我需要将ssh密钥存储在我的AWS控制台中,目前情况并非如此,并且还会破坏运行脚本的功能(通过ssh)因为我无法从NodeMetadata对象推断出RunningInstance

RunInstancesOptions options = RunInstancesOptions.Builder.asType("t2.micro").withKeyName(keypair).withSecurityGroup(securityGroup).withUserData(script.getBytes());

有什么建议吗?

注意:虽然我目前正在对aws进行测试,但我希望尽可能将代码与提供程序分离。

更新26/10/2015

基于@Ignasi Barrera answer,我在创建.init(new MyAdminAccessConfiguration())

时添加了bootInstructions来更改了我的实施
Statement bootInstructions = AdminAccess.standard().init(new MyAdminAccessConfiguration());
templateBuilder.options(runScript(bootInstructions));

其中MyAdminAccessConfiguration是我自己的AdminAccessConfiguration接口实现,正如@Ignasi Barrera所描述的那样。

1 个答案:

答案 0 :(得分:1)

我认为这个问题依赖于jclouds代码在Windows机器上运行的事实,而jclouds默认会做出一些Unix假设。

这里有两个不同的东西:首先,AdminAccess.standard()用于在部署的节点启动后配置用户,稍后传递给运行脚本方法的LoginCredentials对象用于对使用前一个语句创建的用户进行身份验证。

这里的问题是AdminAccess.standard()读取“当前用户”信息并假设是Unix系统。该用户信息由this Default class提供,在您的情况下,我非常确定它将回退到catch块并返回自动生成的SSH密钥对。这意味着,AdminAccess.standard()正在使用自动生成的(随机)SSH密钥在节点中创建用户,但您正在构建的LoginCredentials与这些密钥不匹配,因此身份验证失败。 / p>

由于AdminAccess实体是不可变的,因此更好更清晰的解决方法是创建自己的AdminAccessConfiguration interface实现。您可以复制整个Default类并更改Unix特定位以适应Windows机器中的SSH设置。一旦有了实现类,就可以通过创建Guice模块并将其传递给创建jclouds上下文时提供的模块列表来注入它。类似的东西:

// Create the custom module to inject your implementation
Module windowsAdminAccess = new AbstractModule() {
   @Override protected void configure() {
      bind(AdminAccessConfiguration.class).to(YourCustomWindowsImpl.class).in(Scopes.SINGLETON);
   }
};

// Provide the module in the module list when creating the context
ComputeServiceContext context = ContextBuilder.newBuilder("aws-ec2")
   .credentials("api-key", "api-secret")
   .modules(ImmutableSet.<Module> of(windowsAdminAccess, new SshjSshClientModule()))
   .buildView(ComputeServiceContext.class);