jClouds + OpenStack: (NoSuchElementException) key

2019-08-09 04:19发布

I'm trying to integrate Apache jClouds into a Java project so I can access the OpenStack API. The following code fails:

neutronApi = ContextBuilder.newBuilder("openstack-neutron")
                    .credentials(USERNAME, API_KEY)
                    .endpoint(AUTH_URL)
                    .modules(modules)
                    .buildApi(NeutronApi.class);

With the following error message:

Java.util.NoSuchElementException: key [openstack-neutron] not in the list of providers or apis: {providers=[ultradns-ws], apis=[swift, swift-keystone]}

This is apparently a common problem, however the suggestions offered in jClouds troubleshooting don't resolve it. There's another StackOverflow discussion about this problem but does not have an accepted answer.

A few useful points:

  • Our Java project uses Ant, whereas jClouds is based on Maven. The jClouds Installation Guide provides directions to install using Ant, but none of them work correctly. Instead, I compiled jClouds from source (https://github.com/jclouds/jclouds) and copied the .jar files into a folder on my classpath. Now I can access the jClouds objects in my code.
  • The default jclouds source does not include OpenStack Neutron objects. I eventually found these in the OpenStack Labs source (https://github.com/jclouds/jclouds-labs-openstack). Compiled from source, copied the openstack-neutron-1.9.1.jar file into classpath folder, now I can access Neutron objects.
  • All online sources suggest this is a classpath/dependency problem. I've verified the openstack-neutron-1.9.1.jar library is available in both my .classpath and build.xml files. No resolution.

I'd appreciate any ideas or suggestions!

3条回答
何必那么认真
2楼-- · 2019-08-09 04:34

If you're using maven, you should add the following dependency:

<dependency>
    <groupId>org.apache.jclouds.provider</groupId>
    <artifactId>aws-ec2</artifactId>
    <version>${jclouds.version}</version>
</dependency>

and then, package from the command line:

mvn clean package

and add the dependencies:

mvn dependency:copy-dependencies -DoutputDirectory="./lib"

and execute:

java -cp "target/jar-with-dependencies.jar:lib/*" YourClass
查看更多
贼婆χ
3楼-- · 2019-08-09 04:46

There are some examples here:

https://github.com/jclouds/jclouds-examples/blob/master/rackspace/src/main/java/org/jclouds/examples/rackspace/cloudnetworks/CreateNetwork.java

They use maven, but they are a good starting point to compare code/dependencies.

Also, maybe you can use something like this to manage jclouds dependencies as an alternative? https://maven.apache.org/ant-tasks/

You can also try to download jclouds-neutron from maven, instead of compiling it:

https://search.maven.org/#artifactdetails%7Corg.apache.jclouds.labs%7Copenstack-neutron%7C1.9.1%7Cbundle

What problems are you hitting with the ant instructions?

查看更多
放荡不羁爱自由
4楼-- · 2019-08-09 04:47

When you pass a provider/api id as a string to the ContextBuilder, the java ServiceLoader will be used to load the api classes. It will scan the META-INF/services folder in the classpath and look for implementations of ApiMetadata and ProviderMetadata.

Can you verify that in your environment there are no class loading issues that could prevent the ServiceLoader from operating normally?

As an alternative, you can bypass the ServiceLoader lookup and provide directly the concrete ApiMetadata implementation. In your case it would be something like:

NeutronApi neutron = ContextBuilder.newBuilder(new NeutronApiMetadata())
   .credentials(USERNAME, API_KEY)
   .endpoint(AUTH_URL)
   .modules(modules)
   .buildApi(NeutronApi.class);

If you have the openstack-neutron jar in your classpath this should work. And if it does, it also indicates that there is something in your project that is preventing the ServiceLoader from operating properly. It won't affect jclouds, as it only uses it when creating the context, but it is something you may want to fix.

查看更多
登录 后发表回答