mirror of https://github.com/apache/jclouds.git
JCLOUDS-486 This will allow booting up nova servers with fixed IPs and ports.
This commit is contained in:
parent
04e6620fb9
commit
d99ad1b94a
|
@ -110,7 +110,12 @@ public class NovaComputeServiceAdapter implements
|
||||||
options.userData(templateOptions.getUserData());
|
options.userData(templateOptions.getUserData());
|
||||||
options.diskConfig(templateOptions.getDiskConfig());
|
options.diskConfig(templateOptions.getDiskConfig());
|
||||||
options.configDrive(templateOptions.getConfigDrive());
|
options.configDrive(templateOptions.getConfigDrive());
|
||||||
options.networks(templateOptions.getNetworks());
|
if (templateOptions.getNovaNetworks() != null) {
|
||||||
|
options.novaNetworks(templateOptions.getNovaNetworks());
|
||||||
|
}
|
||||||
|
if (templateOptions.getNetworks() != null) {
|
||||||
|
options.networks(templateOptions.getNetworks());
|
||||||
|
}
|
||||||
|
|
||||||
Optional<String> privateKey = Optional.absent();
|
Optional<String> privateKey = Optional.absent();
|
||||||
if (templateOptions.getKeyPairName() != null) {
|
if (templateOptions.getKeyPairName() != null) {
|
||||||
|
|
|
@ -27,6 +27,8 @@ import java.util.Set;
|
||||||
|
|
||||||
import org.jclouds.compute.options.TemplateOptions;
|
import org.jclouds.compute.options.TemplateOptions;
|
||||||
import org.jclouds.domain.LoginCredentials;
|
import org.jclouds.domain.LoginCredentials;
|
||||||
|
import org.jclouds.openstack.nova.v2_0.domain.Network;
|
||||||
|
import org.jclouds.openstack.nova.v2_0.options.CreateServerOptions;
|
||||||
import org.jclouds.scriptbuilder.domain.Statement;
|
import org.jclouds.scriptbuilder.domain.Statement;
|
||||||
|
|
||||||
import com.google.common.base.Objects;
|
import com.google.common.base.Objects;
|
||||||
|
@ -76,6 +78,7 @@ public class NovaTemplateOptions extends TemplateOptions implements Cloneable {
|
||||||
}
|
}
|
||||||
|
|
||||||
eTo.configDrive(getConfigDrive());
|
eTo.configDrive(getConfigDrive());
|
||||||
|
eTo.novaNetworks(getNovaNetworks());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,6 +89,7 @@ public class NovaTemplateOptions extends TemplateOptions implements Cloneable {
|
||||||
protected byte[] userData;
|
protected byte[] userData;
|
||||||
protected String diskConfig;
|
protected String diskConfig;
|
||||||
protected boolean configDrive;
|
protected boolean configDrive;
|
||||||
|
protected Set<Network> novaNetworks;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
|
@ -100,12 +104,13 @@ public class NovaTemplateOptions extends TemplateOptions implements Cloneable {
|
||||||
&& equal(this.keyPairName, that.keyPairName)
|
&& equal(this.keyPairName, that.keyPairName)
|
||||||
&& Arrays.equals(this.userData, that.userData)
|
&& Arrays.equals(this.userData, that.userData)
|
||||||
&& equal(this.diskConfig, that.diskConfig)
|
&& equal(this.diskConfig, that.diskConfig)
|
||||||
&& equal(this.configDrive, that.configDrive);
|
&& equal(this.configDrive, that.configDrive)
|
||||||
|
&& equal(this.novaNetworks, that.novaNetworks);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return Objects.hashCode(super.hashCode(), autoAssignFloatingIp, securityGroupNames, generateKeyPair, keyPairName, userData, diskConfig, configDrive);
|
return Objects.hashCode(super.hashCode(), autoAssignFloatingIp, securityGroupNames, generateKeyPair, keyPairName, userData, diskConfig, configDrive, novaNetworks);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -121,6 +126,7 @@ public class NovaTemplateOptions extends TemplateOptions implements Cloneable {
|
||||||
toString.add("userData", userData);
|
toString.add("userData", userData);
|
||||||
toString.add("diskConfig", diskConfig);
|
toString.add("diskConfig", diskConfig);
|
||||||
toString.add("configDrive", configDrive);
|
toString.add("configDrive", configDrive);
|
||||||
|
toString.add("novaNetworks", novaNetworks);
|
||||||
return toString;
|
return toString;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -228,6 +234,13 @@ public class NovaTemplateOptions extends TemplateOptions implements Cloneable {
|
||||||
return configDrive;
|
return configDrive;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see CreateServerOptions#getNetworks()
|
||||||
|
*/
|
||||||
|
public Set<Network> getNovaNetworks() {
|
||||||
|
return novaNetworks;
|
||||||
|
}
|
||||||
|
|
||||||
public static class Builder {
|
public static class Builder {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -396,6 +409,14 @@ public class NovaTemplateOptions extends TemplateOptions implements Cloneable {
|
||||||
NovaTemplateOptions options = new NovaTemplateOptions();
|
NovaTemplateOptions options = new NovaTemplateOptions();
|
||||||
return NovaTemplateOptions.class.cast(options.configDrive(configDrive));
|
return NovaTemplateOptions.class.cast(options.configDrive(configDrive));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see org.jclouds.openstack.nova.v2_0.options.CreateServerOptions#getNetworks()
|
||||||
|
*/
|
||||||
|
public static NovaTemplateOptions novaNetworks(Set<Network> novaNetworks) {
|
||||||
|
NovaTemplateOptions options = new NovaTemplateOptions();
|
||||||
|
return NovaTemplateOptions.class.cast(options.novaNetworks(novaNetworks));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// methods that only facilitate returning the correct object type
|
// methods that only facilitate returning the correct object type
|
||||||
|
@ -537,13 +558,23 @@ public class NovaTemplateOptions extends TemplateOptions implements Cloneable {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* <br>Ensures NovaTemplateOptions can work with networks specified as Strings.
|
||||||
|
* Also provides for compatibility with the abstraction layer.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public NovaTemplateOptions networks(Iterable<String> networks) {
|
public NovaTemplateOptions networks(Iterable<String> networks) {
|
||||||
return NovaTemplateOptions.class.cast(super.networks(networks));
|
return NovaTemplateOptions.class.cast(super.networks(networks));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <br>Ensures NovaTemplateOptions can work with networks specified as Strings.
|
||||||
|
* Also provides for compatibility with the abstraction layer.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public NovaTemplateOptions networks(String... networks) {
|
||||||
|
return NovaTemplateOptions.class.cast(super.networks(networks));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User data as bytes (not base64-encoded)
|
* User data as bytes (not base64-encoded)
|
||||||
*/
|
*/
|
||||||
|
@ -575,4 +606,15 @@ public class NovaTemplateOptions extends TemplateOptions implements Cloneable {
|
||||||
this.configDrive = configDrive;
|
this.configDrive = configDrive;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param novaNetworks The list of network declarations.
|
||||||
|
* Nova-specific network declarations allow for specifying network UUIDs, port UUIDs, and fixed IPs.
|
||||||
|
* Unline {@link #networks(Iterable)} this supports setting additional network parameters and not just network UUIDs.
|
||||||
|
* @see CreateServerOptions#getNetworks()
|
||||||
|
*/
|
||||||
|
public NovaTemplateOptions novaNetworks(Set<Network> novaNetworks) {
|
||||||
|
this.novaNetworks = novaNetworks;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,173 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jclouds.openstack.nova.v2_0.domain;
|
||||||
|
|
||||||
|
import java.beans.ConstructorProperties;
|
||||||
|
|
||||||
|
import com.google.common.base.Objects;
|
||||||
|
import com.google.common.base.Objects.ToStringHelper;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkArgument;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Nova (or Neutron) network definition
|
||||||
|
* Used to provide support for network, port, and fixed_ip when booting Nova servers.
|
||||||
|
* OpenStack will support either a Nova Network or Neutron, but not both at the same time.
|
||||||
|
* Specifying a port is only possible with Neutron.
|
||||||
|
* @author Zack Shoylev
|
||||||
|
*/
|
||||||
|
public class Network implements Comparable<Network> {
|
||||||
|
private final String networkUuid;
|
||||||
|
private final String portUuid;
|
||||||
|
private final String fixedIp;
|
||||||
|
|
||||||
|
@ConstructorProperties({
|
||||||
|
"networkUuid", "portUuid", "fixedIp"
|
||||||
|
})
|
||||||
|
protected Network(String networkUuid, String portUuid, String fixedIp) {
|
||||||
|
checkArgument(networkUuid != null || portUuid != null, "At least one of networkUuid or portUuid should be specified");
|
||||||
|
this.networkUuid = networkUuid;
|
||||||
|
this.portUuid = portUuid;
|
||||||
|
this.fixedIp = fixedIp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the network uuid - Neutron or Nova
|
||||||
|
*/
|
||||||
|
public String getNetworkUuid() {
|
||||||
|
return this.networkUuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the port uuid - Neutron only
|
||||||
|
*/
|
||||||
|
public String getPortUuid() {
|
||||||
|
return this.portUuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the fixed IP address - Neutron or Nova
|
||||||
|
*/
|
||||||
|
public String getFixedIp() {
|
||||||
|
return this.fixedIp;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hashCode(networkUuid, portUuid, fixedIp);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj) return true;
|
||||||
|
if (obj == null || getClass() != obj.getClass()) return false;
|
||||||
|
Network that = Network.class.cast(obj);
|
||||||
|
return Objects.equal(this.networkUuid, that.networkUuid) &&
|
||||||
|
Objects.equal(this.portUuid, that.portUuid) &&
|
||||||
|
Objects.equal(this.fixedIp, that.fixedIp);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ToStringHelper string() {
|
||||||
|
return Objects.toStringHelper(this)
|
||||||
|
.add("networkUuid", networkUuid)
|
||||||
|
.add("portUuid", portUuid)
|
||||||
|
.add("fixedIp", fixedIp);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return string().toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return A new builder object
|
||||||
|
*/
|
||||||
|
public static Builder builder() {
|
||||||
|
return new Builder();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return A new Builder object from another Network
|
||||||
|
*/
|
||||||
|
public Builder toBuilder() {
|
||||||
|
return new Builder().fromNetwork(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implements the Builder pattern for this class
|
||||||
|
*/
|
||||||
|
public static class Builder {
|
||||||
|
protected String networkUuid;
|
||||||
|
protected String portUuid;
|
||||||
|
protected String fixedIp;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param networkUuid The UUID for the Nova network or Neutron subnet to be attached.
|
||||||
|
* @return The builder object.
|
||||||
|
* @see Network#getNetworkUuid()
|
||||||
|
*/
|
||||||
|
public Builder networkUuid(String networkUuid) {
|
||||||
|
this.networkUuid = networkUuid;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param portUuid The port UUID for this Neutron Network.
|
||||||
|
* @return The builder object.
|
||||||
|
* @see Network#getPortUuid()
|
||||||
|
*/
|
||||||
|
public Builder portUuid(String portUuid) {
|
||||||
|
this.portUuid = portUuid;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param fixedIp The fixed IP address for this Network (if any).
|
||||||
|
* Service automatically assigns IP address if this is not provided.
|
||||||
|
* Fixed IP is compatible with both Nova Network and Neutron.
|
||||||
|
* @return The builder object.
|
||||||
|
* @see Network#getFixedIp()
|
||||||
|
*/
|
||||||
|
public Builder fixedIp(String fixedIp) {
|
||||||
|
this.fixedIp = fixedIp;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return A new Network object.
|
||||||
|
*/
|
||||||
|
public Network build() {
|
||||||
|
return new Network(networkUuid, portUuid, fixedIp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param in The target Network
|
||||||
|
* @return A Builder from the provided Network
|
||||||
|
*/
|
||||||
|
public Builder fromNetwork(Network in) {
|
||||||
|
return this
|
||||||
|
.networkUuid(in.getNetworkUuid())
|
||||||
|
.portUuid(in.getPortUuid())
|
||||||
|
.fixedIp(in.getFixedIp());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compareTo(Network that) {
|
||||||
|
return this.toString().compareTo(that.toString());
|
||||||
|
}
|
||||||
|
}
|
|
@ -16,24 +16,6 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.openstack.nova.v2_0.options;
|
package org.jclouds.openstack.nova.v2_0.options;
|
||||||
|
|
||||||
import com.google.common.base.Objects;
|
|
||||||
import com.google.common.base.Objects.ToStringHelper;
|
|
||||||
import com.google.common.collect.ForwardingObject;
|
|
||||||
import com.google.common.collect.ImmutableMap;
|
|
||||||
import com.google.common.collect.ImmutableSet;
|
|
||||||
import com.google.common.collect.Lists;
|
|
||||||
import com.google.common.collect.Sets;
|
|
||||||
import org.jclouds.http.HttpRequest;
|
|
||||||
import org.jclouds.rest.MapBinder;
|
|
||||||
import org.jclouds.rest.binders.BindToJsonPayload;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
|
||||||
import javax.inject.Named;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Map.Entry;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import static com.google.common.base.Objects.equal;
|
import static com.google.common.base.Objects.equal;
|
||||||
import static com.google.common.base.Objects.toStringHelper;
|
import static com.google.common.base.Objects.toStringHelper;
|
||||||
import static com.google.common.base.Preconditions.checkArgument;
|
import static com.google.common.base.Preconditions.checkArgument;
|
||||||
|
@ -42,9 +24,34 @@ import static com.google.common.base.Preconditions.checkState;
|
||||||
import static com.google.common.base.Strings.emptyToNull;
|
import static com.google.common.base.Strings.emptyToNull;
|
||||||
import static com.google.common.io.BaseEncoding.base64;
|
import static com.google.common.io.BaseEncoding.base64;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Named;
|
||||||
|
|
||||||
|
import org.jclouds.http.HttpRequest;
|
||||||
|
import org.jclouds.openstack.nova.v2_0.NovaApi;
|
||||||
|
import org.jclouds.openstack.nova.v2_0.domain.Network;
|
||||||
|
import org.jclouds.openstack.nova.v2_0.domain.Server;
|
||||||
|
import org.jclouds.rest.MapBinder;
|
||||||
|
import org.jclouds.rest.binders.BindToJsonPayload;
|
||||||
|
|
||||||
|
import com.google.common.base.Objects;
|
||||||
|
import com.google.common.base.Objects.ToStringHelper;
|
||||||
|
import com.google.common.base.Optional;
|
||||||
|
import com.google.common.collect.ForwardingObject;
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
import com.google.common.collect.Sets;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
* @author Inbar Stolberg
|
* @author Inbar Stolberg
|
||||||
|
* @author Zack Shoylev
|
||||||
*/
|
*/
|
||||||
public class CreateServerOptions implements MapBinder {
|
public class CreateServerOptions implements MapBinder {
|
||||||
@Inject
|
@Inject
|
||||||
|
@ -106,6 +113,7 @@ public class CreateServerOptions implements MapBinder {
|
||||||
private byte[] userData;
|
private byte[] userData;
|
||||||
private String diskConfig;
|
private String diskConfig;
|
||||||
private Set<String> networks = ImmutableSet.of();
|
private Set<String> networks = ImmutableSet.of();
|
||||||
|
private Set<Network> novaNetworks = ImmutableSet.of();
|
||||||
private String availabilityZone;
|
private String availabilityZone;
|
||||||
private boolean configDrive;
|
private boolean configDrive;
|
||||||
|
|
||||||
|
@ -216,8 +224,22 @@ public class CreateServerOptions implements MapBinder {
|
||||||
server.diskConfig = diskConfig;
|
server.diskConfig = diskConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!networks.isEmpty()) {
|
if (!networks.isEmpty() || !novaNetworks.isEmpty()) {
|
||||||
server.networks = Sets.newLinkedHashSet(); // ensures ordering is preserved - helps testing and more intuitive for users.
|
server.networks = Sets.newLinkedHashSet(); // ensures ordering is preserved - helps testing and more intuitive for users.
|
||||||
|
for (Network network : novaNetworks) {
|
||||||
|
// Avoid serializing null values, which are common here.
|
||||||
|
ImmutableMap.Builder<String, String> networkMap = new ImmutableMap.Builder<String, String>();
|
||||||
|
if(network.getNetworkUuid() != null) {
|
||||||
|
networkMap.put("uuid", network.getNetworkUuid());
|
||||||
|
}
|
||||||
|
if(network.getPortUuid() != null) {
|
||||||
|
networkMap.put("port", network.getPortUuid());
|
||||||
|
}
|
||||||
|
if(network.getFixedIp() != null) {
|
||||||
|
networkMap.put("fixed_ip", network.getFixedIp());
|
||||||
|
}
|
||||||
|
server.networks.add(networkMap.build());
|
||||||
|
}
|
||||||
for (String network : networks) {
|
for (String network : networks) {
|
||||||
server.networks.add(ImmutableMap.of("uuid", network));
|
server.networks.add(ImmutableMap.of("uuid", network));
|
||||||
}
|
}
|
||||||
|
@ -365,6 +387,16 @@ public class CreateServerOptions implements MapBinder {
|
||||||
return networks;
|
return networks;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get custom networks specified for the server.
|
||||||
|
*
|
||||||
|
* @return A set of uuids defined by Neutron (previously Quantum)
|
||||||
|
* @see <a href="https://wiki.openstack.org/wiki/Neutron/APIv2-specification#Network">Neutron Networks<a/>
|
||||||
|
*/
|
||||||
|
public Set<Network> getNovaNetworks() {
|
||||||
|
return novaNetworks;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see #getSecurityGroupNames
|
* @see #getSecurityGroupNames
|
||||||
*/
|
*/
|
||||||
|
@ -406,22 +438,37 @@ public class CreateServerOptions implements MapBinder {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see #getNetworks
|
* Determines if a configuration drive will be attached to the server or not.
|
||||||
|
* This can be used for cloud-init or other configuration purposes.
|
||||||
*/
|
*/
|
||||||
public CreateServerOptions networks(String... networks) {
|
public boolean getConfigDrive() {
|
||||||
return networks(ImmutableSet.copyOf(networks));
|
return configDrive;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see #getNetworks
|
* @see #getNetworks
|
||||||
*/
|
*/
|
||||||
public CreateServerOptions networks(Iterable<String> networks) {
|
public CreateServerOptions networks(Iterable<String> networks) {
|
||||||
for (String network : checkNotNull(networks, "networks"))
|
|
||||||
checkNotNull(emptyToNull(network), "all networks must be non-empty");
|
|
||||||
this.networks = ImmutableSet.copyOf(networks);
|
this.networks = ImmutableSet.copyOf(networks);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see #getNetworks
|
||||||
|
* Overwrites networks supplied by {@link #networks(Iterable)}
|
||||||
|
*/
|
||||||
|
public CreateServerOptions novaNetworks(Iterable<Network> networks) {
|
||||||
|
this.novaNetworks = ImmutableSet.copyOf(networks);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see #getNetworks
|
||||||
|
*/
|
||||||
|
public CreateServerOptions networks(String... networks) {
|
||||||
|
return networks(ImmutableSet.copyOf(networks));
|
||||||
|
}
|
||||||
|
|
||||||
public static class Builder {
|
public static class Builder {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -493,6 +540,14 @@ public class CreateServerOptions implements MapBinder {
|
||||||
return CreateServerOptions.class.cast(options.networks(networks));
|
return CreateServerOptions.class.cast(options.networks(networks));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see CreateServerOptions#getNetworks
|
||||||
|
*/
|
||||||
|
public static CreateServerOptions novaNetworks(Iterable<Network> networks) {
|
||||||
|
CreateServerOptions options = new CreateServerOptions();
|
||||||
|
return CreateServerOptions.class.cast(options.novaNetworks(networks));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see org.jclouds.openstack.nova.v2_0.options.CreateServerOptions#getAvailabilityZone()
|
* @see org.jclouds.openstack.nova.v2_0.options.CreateServerOptions#getAvailabilityZone()
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -32,6 +32,7 @@ import org.jclouds.http.HttpRequest;
|
||||||
import org.jclouds.http.HttpResponse;
|
import org.jclouds.http.HttpResponse;
|
||||||
import org.jclouds.openstack.nova.v2_0.compute.options.NovaTemplateOptions;
|
import org.jclouds.openstack.nova.v2_0.compute.options.NovaTemplateOptions;
|
||||||
import org.jclouds.openstack.nova.v2_0.domain.KeyPair;
|
import org.jclouds.openstack.nova.v2_0.domain.KeyPair;
|
||||||
|
import org.jclouds.openstack.nova.v2_0.domain.Network;
|
||||||
import org.jclouds.openstack.nova.v2_0.domain.Server;
|
import org.jclouds.openstack.nova.v2_0.domain.Server;
|
||||||
import org.jclouds.openstack.nova.v2_0.domain.zonescoped.ServerInZone;
|
import org.jclouds.openstack.nova.v2_0.domain.zonescoped.ServerInZone;
|
||||||
import org.jclouds.openstack.nova.v2_0.domain.zonescoped.ZoneAndName;
|
import org.jclouds.openstack.nova.v2_0.domain.zonescoped.ZoneAndName;
|
||||||
|
@ -40,6 +41,7 @@ import org.testng.annotations.Test;
|
||||||
|
|
||||||
import com.google.common.cache.LoadingCache;
|
import com.google.common.cache.LoadingCache;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.inject.Injector;
|
import com.google.inject.Injector;
|
||||||
import com.google.inject.Key;
|
import com.google.inject.Key;
|
||||||
import com.google.inject.TypeLiteral;
|
import com.google.inject.TypeLiteral;
|
||||||
|
@ -165,6 +167,53 @@ public class NovaComputeServiceAdapterExpectTest extends BaseNovaComputeServiceC
|
||||||
assertNotNull(server);
|
assertNotNull(server);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testCreateNodeWithGroupEncodedIntoNameWithNovaNetworks() throws Exception {
|
||||||
|
|
||||||
|
HttpRequest createServer = HttpRequest
|
||||||
|
.builder()
|
||||||
|
.method("POST")
|
||||||
|
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/servers")
|
||||||
|
.addHeader("Accept", "application/json")
|
||||||
|
.addHeader("X-Auth-Token", authToken)
|
||||||
|
.payload(payloadFromStringWithContentType(
|
||||||
|
"{\"server\":{\"name\":\"test-e92\",\"imageRef\":\"1241\",\"flavorRef\":\"100\",\"networks\":[{\"uuid\":\"12345\", \"port\":\"67890\", \"fixed_ip\":\"192.168.0.1\"},{\"uuid\":\"54321\", \"port\":\"09876\", \"fixed_ip\":\"192.168.0.2\"},{\"uuid\":\"non-nova-uuid\"}]}}","application/json"))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
HttpResponse createServerResponse = HttpResponse.builder().statusCode(202).message("HTTP/1.1 202 Accepted")
|
||||||
|
.payload(payloadFromResourceWithContentType("/new_server_nova_networks.json","application/json; charset=UTF-8")).build();
|
||||||
|
|
||||||
|
Map<HttpRequest, HttpResponse> requestResponseMap = ImmutableMap.<HttpRequest, HttpResponse> builder()
|
||||||
|
.put(keystoneAuthWithUsernameAndPasswordAndTenantName, responseWithKeystoneAccess)
|
||||||
|
.put(extensionsOfNovaRequest, extensionsOfNovaResponse)
|
||||||
|
.put(listDetail, listDetailResponse)
|
||||||
|
.put(listFlavorsDetail, listFlavorsDetailResponse)
|
||||||
|
.put(createServer, createServerResponse)
|
||||||
|
.put(serverDetail, serverDetailResponse).build();
|
||||||
|
|
||||||
|
Injector forNovaNetworks = requestsSendResponses(requestResponseMap);
|
||||||
|
|
||||||
|
Template template = forNovaNetworks.getInstance(TemplateBuilder.class).build();
|
||||||
|
template.getOptions().as(NovaTemplateOptions.class)
|
||||||
|
.networks("non-nova-uuid")
|
||||||
|
.novaNetworks(
|
||||||
|
ImmutableSet.of(
|
||||||
|
Network.builder()
|
||||||
|
.networkUuid("12345")
|
||||||
|
.portUuid("67890")
|
||||||
|
.fixedIp("192.168.0.1")
|
||||||
|
.build(),
|
||||||
|
Network.builder()
|
||||||
|
.networkUuid("54321")
|
||||||
|
.portUuid("09876")
|
||||||
|
.fixedIp("192.168.0.2")
|
||||||
|
.build()));
|
||||||
|
|
||||||
|
NovaComputeServiceAdapter adapter = forNovaNetworks.getInstance(NovaComputeServiceAdapter.class);
|
||||||
|
|
||||||
|
NodeAndInitialCredentials<ServerInZone> server = adapter.createNodeWithGroupEncodedIntoName("test", "test-e92", template);
|
||||||
|
assertNotNull(server);
|
||||||
|
}
|
||||||
|
|
||||||
public void testCreateNodeWithGroupEncodedIntoNameWhenSecurityGroupsArePresent() throws Exception {
|
public void testCreateNodeWithGroupEncodedIntoNameWhenSecurityGroupsArePresent() throws Exception {
|
||||||
|
|
||||||
HttpRequest createServer = HttpRequest
|
HttpRequest createServer = HttpRequest
|
||||||
|
|
|
@ -21,6 +21,7 @@ import static org.testng.Assert.assertFalse;
|
||||||
import static org.testng.Assert.assertNotNull;
|
import static org.testng.Assert.assertNotNull;
|
||||||
import static org.testng.Assert.assertTrue;
|
import static org.testng.Assert.assertTrue;
|
||||||
|
|
||||||
|
import org.jclouds.openstack.nova.v2_0.domain.Network;
|
||||||
import org.jclouds.openstack.nova.v2_0.domain.Server;
|
import org.jclouds.openstack.nova.v2_0.domain.Server;
|
||||||
import org.jclouds.openstack.nova.v2_0.domain.ServerCreated;
|
import org.jclouds.openstack.nova.v2_0.domain.ServerCreated;
|
||||||
import org.jclouds.openstack.nova.v2_0.internal.BaseNovaApiLiveTest;
|
import org.jclouds.openstack.nova.v2_0.internal.BaseNovaApiLiveTest;
|
||||||
|
@ -31,6 +32,7 @@ import org.jclouds.openstack.v2_0.domain.Resource;
|
||||||
import org.jclouds.openstack.v2_0.predicates.LinkPredicates;
|
import org.jclouds.openstack.v2_0.predicates.LinkPredicates;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -42,133 +44,163 @@ import com.google.common.collect.Iterables;
|
||||||
@Test(groups = "live", testName = "ServerApiLiveTest")
|
@Test(groups = "live", testName = "ServerApiLiveTest")
|
||||||
public class ServerApiLiveTest extends BaseNovaApiLiveTest {
|
public class ServerApiLiveTest extends BaseNovaApiLiveTest {
|
||||||
|
|
||||||
@Test(description = "GET /v${apiVersion}/{tenantId}/servers")
|
@Test(description = "GET /v${apiVersion}/{tenantId}/servers")
|
||||||
public void testListServers() throws Exception {
|
public void testListServers() throws Exception {
|
||||||
for (String zoneId : zones) {
|
for (String zoneId : zones) {
|
||||||
ServerApi serverApi = api.getServerApiForZone(zoneId);
|
ServerApi serverApi = api.getServerApiForZone(zoneId);
|
||||||
for (Resource server : serverApi.list().concat()) {
|
for (Resource server : serverApi.list().concat()) {
|
||||||
checkResource(server);
|
checkResource(server);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(description = "GET /v${apiVersion}/{tenantId}/servers/detail")
|
@Test(description = "GET /v${apiVersion}/{tenantId}/servers/detail")
|
||||||
public void testListServersInDetail() throws Exception {
|
public void testListServersInDetail() throws Exception {
|
||||||
for (String zoneId : zones) {
|
for (String zoneId : zones) {
|
||||||
ServerApi serverApi = api.getServerApiForZone(zoneId);
|
ServerApi serverApi = api.getServerApiForZone(zoneId);
|
||||||
for (Server server : serverApi.listInDetail().concat()) {
|
for (Server server : serverApi.listInDetail().concat()) {
|
||||||
checkServer(server);
|
checkServer(server);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(description = "GET /v${apiVersion}/{tenantId}/servers/{id}", dependsOnMethods = { "testListServersInDetail" })
|
@Test(description = "GET /v${apiVersion}/{tenantId}/servers/{id}", dependsOnMethods = { "testListServersInDetail" })
|
||||||
public void testGetServerById() throws Exception {
|
public void testGetServerById() throws Exception {
|
||||||
for (String zoneId : zones) {
|
for (String zoneId : zones) {
|
||||||
ServerApi serverApi = api.getServerApiForZone(zoneId);
|
ServerApi serverApi = api.getServerApiForZone(zoneId);
|
||||||
for (Resource server : serverApi.list().concat()) {
|
for (Resource server : serverApi.list().concat()) {
|
||||||
Server details = serverApi.get(server.getId());
|
Server details = serverApi.get(server.getId());
|
||||||
assertEquals(details.getId(), server.getId());
|
assertEquals(details.getId(), server.getId());
|
||||||
assertEquals(details.getName(), server.getName());
|
assertEquals(details.getName(), server.getName());
|
||||||
assertEquals(details.getLinks(), server.getLinks());
|
assertEquals(details.getLinks(), server.getLinks());
|
||||||
checkServer(details);
|
checkServer(details);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCreateInAvailabilityZone() {
|
public void testCreateInAvailabilityZone() {
|
||||||
String serverId = null;
|
String serverId = null;
|
||||||
for (String zoneId : zones) {
|
for (String zoneId : zones) {
|
||||||
ServerApi serverApi = api.getServerApiForZone(zoneId);
|
ServerApi serverApi = api.getServerApiForZone(zoneId);
|
||||||
try {
|
try {
|
||||||
serverId = createServer(zoneId, "nova", Server.Status.ACTIVE).getId();
|
serverId = createServer(zoneId, "nova", Server.Status.ACTIVE).getId();
|
||||||
Server server = serverApi.get(serverId);
|
Server server = serverApi.get(serverId);
|
||||||
assertEquals(server.getStatus(), Server.Status.ACTIVE);
|
assertEquals(server.getStatus(), Server.Status.ACTIVE);
|
||||||
} finally {
|
} finally {
|
||||||
serverApi.delete(serverId);
|
serverApi.delete(serverId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This needs to be supported by the provider, and is usually not supported.
|
||||||
|
* However this can be tested on devstack:
|
||||||
|
* In apis/openstack-nova:
|
||||||
|
* mvn -Plive clean install "-Dtest.openstack-nova.endpoint=http://localhost:5000/v2.0" "-Dtest.openstack-nova.identity=demo:demo" "-Dtest.openstack-nova.credential=devstack" "-Dtest=org.jclouds.openstack.nova.v2_0.features.ServerApiLiveTest#testCreateWithNetworkOptions"
|
||||||
|
*/
|
||||||
|
@Test(enabled = false)
|
||||||
|
public void testCreateWithNetworkOptions() {
|
||||||
|
String serverId = null;
|
||||||
|
for (String zoneId : zones) {
|
||||||
|
ServerApi serverApi = api.getServerApiForZone(zoneId);
|
||||||
|
try {
|
||||||
|
CreateServerOptions options = CreateServerOptions.Builder.novaNetworks(
|
||||||
|
// This network UUID must match an existing network.
|
||||||
|
ImmutableSet.of(Network.builder().networkUuid("bc4cfa2b-2b27-4671-8e8f-73009623def0").fixedIp("192.168.55.56").build())
|
||||||
|
);
|
||||||
|
ServerCreated server = serverApi.create(hostName, imageIdForZone(zoneId), "1", options);
|
||||||
|
serverId = server.getId();
|
||||||
|
|
||||||
|
blockUntilServerInState(server.getId(), serverApi, Server.Status.ACTIVE);
|
||||||
|
Server serverCheck = serverApi.get(serverId);
|
||||||
|
assertEquals(serverCheck.getStatus(), Server.Status.ACTIVE);
|
||||||
|
} finally {
|
||||||
|
if (serverId != null) {
|
||||||
|
serverApi.delete(serverId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCreateInWrongAvailabilityZone() {
|
public void testCreateInWrongAvailabilityZone() {
|
||||||
String serverId = null;
|
String serverId = null;
|
||||||
for (String zoneId : zones) {
|
for (String zoneId : zones) {
|
||||||
ServerApi serverApi = api.getServerApiForZone(zoneId);
|
ServerApi serverApi = api.getServerApiForZone(zoneId);
|
||||||
try {
|
try {
|
||||||
serverId = createServer(zoneId, "err", Server.Status.ERROR).getId();
|
serverId = createServer(zoneId, "err", Server.Status.ERROR).getId();
|
||||||
Server server = serverApi.get(serverId);
|
Server server = serverApi.get(serverId);
|
||||||
assertEquals(server.getStatus(), Server.Status.ERROR);
|
assertEquals(server.getStatus(), Server.Status.ERROR);
|
||||||
} finally {
|
} finally {
|
||||||
serverApi.delete(serverId);
|
serverApi.delete(serverId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRebuildServer() {
|
public void testRebuildServer() {
|
||||||
|
|
||||||
String serverId = null;
|
String serverId = null;
|
||||||
|
|
||||||
for (String zoneId : zones) {
|
for (String zoneId : zones) {
|
||||||
ServerApi serverApi = api.getServerApiForZone(zoneId);
|
ServerApi serverApi = api.getServerApiForZone(zoneId);
|
||||||
try {
|
try {
|
||||||
serverId = createServer(zoneId, Server.Status.ACTIVE).getId();
|
serverId = createServer(zoneId, Server.Status.ACTIVE).getId();
|
||||||
|
|
||||||
Server server = serverApi.get(serverId);
|
Server server = serverApi.get(serverId);
|
||||||
|
|
||||||
assertEquals(server.getStatus(), Server.Status.ACTIVE);
|
assertEquals(server.getStatus(), Server.Status.ACTIVE);
|
||||||
|
|
||||||
RebuildServerOptions options = new RebuildServerOptions().
|
RebuildServerOptions options = new RebuildServerOptions().
|
||||||
withImage(server.getImage().getId()).
|
withImage(server.getImage().getId()).
|
||||||
name("newName").
|
name("newName").
|
||||||
adminPass("password").
|
adminPass("password").
|
||||||
ipv4Address("1.1.1.1").
|
ipv4Address("1.1.1.1").
|
||||||
ipv6Address("fe80::100");
|
ipv6Address("fe80::100");
|
||||||
|
|
||||||
serverApi.rebuild(serverId, options);
|
serverApi.rebuild(serverId, options);
|
||||||
|
|
||||||
Server rebuiltServer = serverApi.get(serverId);
|
Server rebuiltServer = serverApi.get(serverId);
|
||||||
|
|
||||||
assertEquals("newName", rebuiltServer.getName());
|
assertEquals("newName", rebuiltServer.getName());
|
||||||
assertEquals("1.1.1.1", rebuiltServer.getAccessIPv4());
|
assertEquals("1.1.1.1", rebuiltServer.getAccessIPv4());
|
||||||
assertEquals("fe80::100", rebuiltServer.getAccessIPv6());
|
assertEquals("fe80::100", rebuiltServer.getAccessIPv6());
|
||||||
|
|
||||||
} finally {
|
} finally {
|
||||||
serverApi.delete(serverId);
|
serverApi.delete(serverId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Server createServer(String regionId, Server.Status serverStatus) {
|
private Server createServer(String regionId, Server.Status serverStatus) {
|
||||||
ServerApi serverApi = api.getServerApiForZone(regionId);
|
ServerApi serverApi = api.getServerApiForZone(regionId);
|
||||||
CreateServerOptions options = new CreateServerOptions();
|
CreateServerOptions options = new CreateServerOptions();
|
||||||
ServerCreated server = serverApi.create(hostName, imageIdForZone(regionId), flavorRefForZone(regionId), options);
|
ServerCreated server = serverApi.create(hostName, imageIdForZone(regionId), flavorRefForZone(regionId), options);
|
||||||
|
|
||||||
blockUntilServerInState(server.getId(), serverApi, serverStatus);
|
blockUntilServerInState(server.getId(), serverApi, serverStatus);
|
||||||
|
|
||||||
return serverApi.get(server.getId());
|
return serverApi.get(server.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
private Server createServer(String regionId, String availabilityZoneId, Server.Status serverStatus) {
|
private Server createServer(String regionId, String availabilityZoneId, Server.Status serverStatus) {
|
||||||
ServerApi serverApi = api.getServerApiForZone(regionId);
|
ServerApi serverApi = api.getServerApiForZone(regionId);
|
||||||
CreateServerOptions options = new CreateServerOptions();
|
CreateServerOptions options = new CreateServerOptions();
|
||||||
options = options.availabilityZone(availabilityZoneId);
|
options = options.availabilityZone(availabilityZoneId);
|
||||||
ServerCreated server = serverApi.create(hostName, imageIdForZone(regionId), flavorRefForZone(regionId), options);
|
ServerCreated server = serverApi.create(hostName, imageIdForZone(regionId), flavorRefForZone(regionId), options);
|
||||||
blockUntilServerInState(server.getId(), serverApi, serverStatus);
|
blockUntilServerInState(server.getId(), serverApi, serverStatus);
|
||||||
return serverApi.get(server.getId());
|
return serverApi.get(server.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkResource(Resource resource) {
|
private void checkResource(Resource resource) {
|
||||||
assertNotNull(resource.getId());
|
assertNotNull(resource.getId());
|
||||||
assertNotNull(resource.getName());
|
assertNotNull(resource.getName());
|
||||||
assertNotNull(resource.getLinks());
|
assertNotNull(resource.getLinks());
|
||||||
assertTrue(Iterables.any(resource.getLinks(), LinkPredicates.relationEquals(Relation.SELF)));
|
assertTrue(Iterables.any(resource.getLinks(), LinkPredicates.relationEquals(Relation.SELF)));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkServer(Server server) {
|
private void checkServer(Server server) {
|
||||||
checkResource(server);
|
checkResource(server);
|
||||||
assertFalse(server.getAddresses().isEmpty());
|
assertFalse(server.getAddresses().isEmpty());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
{
|
||||||
|
"server": {
|
||||||
|
"status": "BUILD(scheduling)",
|
||||||
|
"updated": "2012-03-19T06:21:13Z",
|
||||||
|
"hostId": "",
|
||||||
|
"user_id": "54297837463082",
|
||||||
|
"name": "test-e92",
|
||||||
|
"links": [{
|
||||||
|
"href": "https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/37936628937291/servers/71752",
|
||||||
|
"rel": "self"
|
||||||
|
}, {
|
||||||
|
"href": "https://az-1.region-a.geo-1.compute.hpcloudsvc.com/37936628937291/servers/71752",
|
||||||
|
"rel": "bookmark"
|
||||||
|
}],
|
||||||
|
"addresses": {},
|
||||||
|
"tenant_id": "37936628937291",
|
||||||
|
"image": {
|
||||||
|
"id": "1241",
|
||||||
|
"links": [{
|
||||||
|
"href": "https://az-1.region-a.geo-1.compute.hpcloudsvc.com/37936628937291/images/1241",
|
||||||
|
"rel": "bookmark"
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
"created": "2012-03-19T06:21:13Z",
|
||||||
|
"uuid": "47491020-6a78-4f63-9475-23195ac4515c",
|
||||||
|
"accessIPv4": "",
|
||||||
|
"accessIPv6": "",
|
||||||
|
"key_name": null,
|
||||||
|
"adminPass": "ZWuHcmTMQ7eXoHeM",
|
||||||
|
"flavor": {
|
||||||
|
"id": "100",
|
||||||
|
"links": [{
|
||||||
|
"href": "https://az-1.region-a.geo-1.compute.hpcloudsvc.com/37936628937291/flavors/100",
|
||||||
|
"rel": "bookmark"
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
"id": 71752,
|
||||||
|
"metadata": {},
|
||||||
|
"OS-DCF:diskConfig": "AUTO"
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue