Issue 280: added guest customization parser, fixed delete in vcloud 0.9+ which now returns a task; parsed customization admin password by default

This commit is contained in:
Adrian Cole 2010-08-26 17:36:48 -07:00
parent 69bbd65c8d
commit 31fd2b5067
23 changed files with 727 additions and 141 deletions

View File

@ -25,8 +25,8 @@ import java.util.Properties;
import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule;
import org.jclouds.logging.jdk.config.JDKLoggingModule;
import org.jclouds.vcloud.VCloudContextBuilder;
import org.jclouds.vcloud.bluelock.compute.config.BlueLockVCloudDirectorComputeServiceContextModule;
import org.jclouds.vcloud.bluelock.config.BlueLockVCloudDirectorRestClientModule;
import org.jclouds.vcloud.compute.config.VCloudComputeServiceContextModule;
import com.google.inject.Injector;
import com.google.inject.Module;
@ -52,7 +52,7 @@ public class BlueLockVCloudDirectorContextBuilder extends VCloudContextBuilder {
@Override
protected void addContextModule(List<Module> modules) {
modules.add(new BlueLockVCloudDirectorComputeServiceContextModule());
modules.add(new VCloudComputeServiceContextModule());
}
@Override

View File

@ -1,62 +0,0 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.vcloud.bluelock.compute;
import java.net.URI;
import java.util.Map;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.compute.domain.NodeState;
import org.jclouds.compute.strategy.PopulateDefaultLoginCredentialsForImageStrategy;
import org.jclouds.domain.Credentials;
import org.jclouds.vcloud.VCloudClient;
import org.jclouds.vcloud.compute.internal.VCloudComputeClientImpl;
import org.jclouds.vcloud.domain.Status;
import org.jclouds.vcloud.domain.VApp;
import org.jclouds.vcloud.domain.VAppTemplate;
import com.google.common.base.Predicate;
/**
* @author Adrian Cole
*/
@Singleton
public class BlueLockVCloudDirectorComputeClient extends VCloudComputeClientImpl {
private final PopulateDefaultLoginCredentialsForImageStrategy credentialsProvider;
@Inject
protected BlueLockVCloudDirectorComputeClient(PopulateDefaultLoginCredentialsForImageStrategy credentialsProvider,
VCloudClient client, Predicate<URI> successTester, Map<Status, NodeState> vAppStatusToNodeState) {
super(client, successTester, vAppStatusToNodeState);
this.credentialsProvider = credentialsProvider;
}
@Override
protected Map<String, String> parseAndValidateResponse(VAppTemplate template, VApp vAppResponse) {
Credentials credentials = credentialsProvider.execute(template);
Map<String, String> toReturn = super.parseResponse(template, vAppResponse);
toReturn.put("username", credentials.identity);
toReturn.put("password", credentials.credential);
return toReturn;
}
}

View File

@ -1,41 +0,0 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.vcloud.bluelock.compute.config;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.vcloud.bluelock.compute.BlueLockVCloudDirectorComputeClient;
import org.jclouds.vcloud.compute.VCloudComputeClient;
import org.jclouds.vcloud.compute.config.VCloudComputeServiceContextModule;
/**
* Configures the {@link ComputeServiceContext}; requires
* {@link BlueLockVCloudDirectorComputeClient} bound.
*
* @author Adrian Cole
*/
public class BlueLockVCloudDirectorComputeServiceContextModule extends VCloudComputeServiceContextModule {
@Override
protected void configure() {
super.configure();
bind(VCloudComputeClient.class).to(BlueLockVCloudDirectorComputeClient.class);
}
}

View File

@ -31,7 +31,6 @@ import java.net.URI;
import javax.annotation.Nullable;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
@ -41,7 +40,6 @@ import org.jclouds.rest.annotations.ExceptionParser;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.XMLResponseParser;
import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404;
import org.jclouds.rest.functions.ReturnVoidOnNotFoundOr404;
import org.jclouds.vcloud.domain.Catalog;
import org.jclouds.vcloud.domain.CatalogItem;
import org.jclouds.vcloud.domain.Org;
@ -196,14 +194,6 @@ public interface CommonVCloudAsyncClient {
ListenableFuture<? extends TasksList> findTasksListInOrgNamed(
@Nullable @EndpointParam(parser = OrgNameToTasksListEndpoint.class) String orgName);
/**
* @see CommonVCloudClient#deleteVApp
*/
@DELETE
@ExceptionParser(ReturnVoidOnNotFoundOr404.class)
ListenableFuture<Void> deleteVApp(@EndpointParam URI vAppId);
/**
* @see CommonVCloudClient#getTask
*/

View File

@ -126,6 +126,4 @@ public interface CommonVCloudClient {
void cancelTask(URI taskId);
void deleteVApp(URI vAppId);
}

View File

@ -30,6 +30,7 @@ import java.net.URI;
import javax.annotation.Nullable;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
@ -46,6 +47,7 @@ import org.jclouds.rest.annotations.ParamValidators;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.XMLResponseParser;
import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404;
import org.jclouds.rest.functions.ReturnVoidOnNotFoundOr404;
import org.jclouds.vcloud.binders.BindCloneVAppParamsToXmlPayload;
import org.jclouds.vcloud.binders.BindDeployVAppParamsToXmlPayload;
import org.jclouds.vcloud.binders.BindInstantiateVAppTemplateParamsToXmlPayload;
@ -262,4 +264,12 @@ public interface VCloudAsyncClient extends CommonVCloudAsyncClient {
@XMLResponseParser(TaskHandler.class)
ListenableFuture<? extends Task> suspendVAppOrVm(@EndpointParam URI vAppOrVmId);
/**
* @see CommonVCloudClient#deleteVApp
*/
@DELETE
@ExceptionParser(ReturnVoidOnNotFoundOr404.class)
@XMLResponseParser(TaskHandler.class)
ListenableFuture<? extends Task> deleteVApp(@EndpointParam URI vAppId);
}

View File

@ -169,4 +169,7 @@ public interface VCloudClient extends CommonVCloudClient {
* A suspend request to a virtual machine URL suspends the specified virtual machine.
*/
Task suspendVAppOrVm(URI vAppOrVmId);
Task deleteVApp(URI vAppId);
}

View File

@ -28,6 +28,7 @@ import java.net.URI;
import javax.annotation.Nullable;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
@ -42,6 +43,7 @@ import org.jclouds.rest.annotations.ParamValidators;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.XMLResponseParser;
import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404;
import org.jclouds.rest.functions.ReturnVoidOnNotFoundOr404;
import org.jclouds.vcloud.binders.BindCloneVAppParamsToXmlPayload;
import org.jclouds.vcloud.binders.BindInstantiateVCloudExpressVAppTemplateParamsToXmlPayload;
import org.jclouds.vcloud.domain.Task;
@ -222,4 +224,12 @@ public interface VCloudExpressAsyncClient extends CommonVCloudAsyncClient {
@Path("/power/action/suspend")
@XMLResponseParser(TaskHandler.class)
ListenableFuture<? extends Task> suspendVApp(@EndpointParam URI vAppId);
/**
* @see CommonVCloudClient#deleteVApp
*/
@DELETE
@ExceptionParser(ReturnVoidOnNotFoundOr404.class)
ListenableFuture<Void> deleteVApp(@EndpointParam URI vAppId);
}

View File

@ -101,4 +101,7 @@ public interface VCloudExpressClient extends CommonVCloudClient {
* This call suspends the vApp.
*/
Task suspendVApp(URI vAppId);
void deleteVApp(URI vAppId);
}

View File

@ -100,6 +100,15 @@ public interface VCloudMediaType {
*/
public final static MediaType VIRTUALHARDWARESECTION_XML_TYPE = new MediaType("application",
"vnd.vmware.vcloud.virtualHardwareSection+xml");
/**
* "application/vnd.vmware.vcloud.guestCustomizationSection+xml"
*/
public final static String GUESTCUSTOMIZATIONSECTION_XML = "application/vnd.vmware.vcloud.guestCustomizationSection+xml";
/**
* "application/vnd.vmware.vcloud.guestCustomizationSection+xml"
*/
public final static MediaType GUESTCUSTOMIZATIONSECTION_XML_TYPE = new MediaType("application",
"vnd.vmware.vcloud.guestCustomizationSection+xml");
/**
* "application/vnd.vmware.vcloud.networkSection+xml"

View File

@ -98,12 +98,9 @@ public abstract class CommonVCloudComputeClientImpl<T, A extends ReferenceType>
deleteVApp(vApp);
logger.debug("<< deleted vApp(%s)", vApp.getName());
}
private void deleteVApp(A vApp) {
logger.debug(">> deleting vApp(%s)", vApp.getName());
client.deleteVApp(vApp.getHref());
}
protected abstract void deleteVApp(A vApp);
private A undeployVAppIfDeployed(A vApp) {
if (getStatus(vApp).compareTo(Status.RESOLVED) > 0) {
logger.debug(">> undeploying vApp(%s), current status: %s", vApp.getName(), getStatus(vApp));

View File

@ -46,6 +46,7 @@ import org.jclouds.vcloud.options.InstantiateVAppTemplateOptions;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
import com.google.inject.Inject;
import com.google.inject.internal.util.Sets;
@ -85,6 +86,26 @@ public class VCloudComputeClientImpl extends CommonVCloudComputeClientImpl<VAppT
return parseAndValidateResponse(null, vAppResponse);
}
@Override
protected void deleteVApp(VApp vApp) {
logger.debug(">> deleting vApp(%s)", vApp.getName());
Task task = VCloudClient.class.cast(client).deleteVApp(vApp.getHref());
if (!taskTester.apply(task.getHref())) {
throw new RuntimeException(String.format("failed to %s %s: %s", "delete", vApp.getName(), task));
}
logger.debug("<< ready vApp(%s)", vApp.getName());
}
@Override
protected Map<String, String> parseResponse(VAppTemplate template, VApp vAppResponse) {
vAppResponse = VCloudClient.class.cast(client).getVApp(vAppResponse.getHref());
Map<String, String> config = Maps.newLinkedHashMap();// Allows nulls
config.put("id", vAppResponse.getHref().toASCIIString());
config.put("username", "root");
config.put("password", Iterables.get(vAppResponse.getChildren(), 0).getGuestCustomization().getAdminPassword());
return config;
}
@Override
public Set<String> getPrivateAddresses(URI id) {
return ImmutableSet.of();

View File

@ -59,6 +59,12 @@ public class VCloudExpressComputeClientImpl extends
this.vAppStatusToNodeState = vAppStatusToNodeState;
}
@Override
protected void deleteVApp(VCloudExpressVApp vApp) {
logger.debug(">> deleting vApp(%s)", vApp.getName());
VCloudExpressClient.class.cast(client).deleteVApp(vApp.getHref());
}
@Override
public Map<String, String> start(@Nullable URI VDC, URI templateId, String name,
InstantiateVAppTemplateOptions options, int... portsToOpen) {

View File

@ -0,0 +1,350 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.vcloud.domain;
import java.net.URI;
/**
* The GuestCustomization of a Vm contains customization parameters for the guest
* operating system of the virtual machine.
*/
public class GuestCustomization {
protected final String type;
protected final URI href;
protected final String info;
protected final Boolean enabled;
protected final Boolean changeSid;
protected final String virtualMachineId;
protected final Boolean joinDomainEnabled;
protected final Boolean useOrgSettings;
protected final String domainName;
protected final String domainUserName;
protected final String domainUserPassword;
protected final Boolean adminPasswordEnabled;
protected final Boolean adminPasswordAuto;
protected final String adminPassword;
protected final Boolean resetPasswordRequired;
protected final String customizationScript;
protected final String computerName;
protected final ReferenceType edit;
public GuestCustomization(String type, URI href, String info, Boolean enabled, Boolean changeSid,
String virtualMachineId, Boolean joinDomainEnabled, Boolean useOrgSettings, String domainName,
String domainUserName, String domainUserPassword, Boolean adminPasswordEnabled, Boolean adminPasswordAuto,
String adminPassword, Boolean resetPasswordRequired, String customizationScript, String computerName,
ReferenceType edit) {
this.type = type;
this.href = href;
this.info = info;
this.enabled = enabled;
this.changeSid = changeSid;
this.virtualMachineId = virtualMachineId;
this.joinDomainEnabled = joinDomainEnabled;
this.useOrgSettings = useOrgSettings;
this.domainName = domainName;
this.domainUserName = domainUserName;
this.domainUserPassword = domainUserPassword;
this.adminPasswordEnabled = adminPasswordEnabled;
this.adminPasswordAuto = adminPasswordAuto;
this.adminPassword = adminPassword;
this.resetPasswordRequired = resetPasswordRequired;
this.customizationScript = customizationScript;
this.computerName = computerName;
this.edit = edit;
}
/**
*
* @return media type of this section
*/
public String getType() {
return type;
}
/**
*
* @return URL to access this section
*/
public URI getHref() {
return href;
}
/**
*
* @return
*/
public String getInfo() {
return info;
}
/**
*
* @return if true, to enable guest customization at power on
*/
public Boolean isEnabled() {
return enabled;
}
/**
*
* @return if true, customization will run sysprep to change the Windows SID for this virtual
* machine
*/
public Boolean shouldChangeSid() {
return changeSid;
}
/**
*
* @return unique identifier for this virtual machine
*/
public String getVirtualMachineId() {
return virtualMachineId;
}
/**
*
* @return if true, this virtual machine can join a Windows domain
*/
public Boolean isJoinDomainEnabled() {
return joinDomainEnabled;
}
/**
*
* @return if true, this virtual machine uses the containing organizations default values for
* Windows domain name, domain user name, and domain user password
*/
public Boolean useOrgSettings() {
return useOrgSettings;
}
/**
*
* @return if UseOrgSettings is false, specifies the Windows domain to join
*/
public String getDomainName() {
return domainName;
}
/**
*
* @return if UseOrgSettings is false, specifies the Windows domain user name
*/
public String getDomainUserName() {
return domainUserName;
}
/**
*
* @return if UseOrgSettings is false, specifies the Windows domain users password
*/
public String getDomainUserPassword() {
return domainUserPassword;
}
/**
*
* @return true if the guest OS allows use of a local administrator password
*/
public Boolean isAdminPasswordEnabled() {
return adminPasswordEnabled;
}
/**
*
* @return true if the local administrator password should be automatically generated
*/
public Boolean isAdminPasswordAuto() {
return adminPasswordAuto;
}
/**
*
* @return local administrator password for this virtual machine
*/
public String getAdminPassword() {
return adminPassword;
}
/**
*
* @return if true, the local administrator must reset his password on first use
*/
public Boolean isResetPasswordRequired() {
return resetPasswordRequired;
}
/**
*
* @return the customization script to run
*/
public String getCustomizationScript() {
return customizationScript;
}
/**
*
* @return name of this virtual machine in DNS or Windows domain
*/
public String getComputerName() {
return computerName;
}
/**
*
* @return edit link
*/
public ReferenceType getEdit() {
return edit;
}
@Override
public String toString() {
return "[href=" + getHref() + ", type=" + getType() + ", info=" + getInfo() + ", enabled=" + isEnabled() + "]";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((adminPassword == null) ? 0 : adminPassword.hashCode());
result = prime * result + ((adminPasswordAuto == null) ? 0 : adminPasswordAuto.hashCode());
result = prime * result + ((adminPasswordEnabled == null) ? 0 : adminPasswordEnabled.hashCode());
result = prime * result + ((changeSid == null) ? 0 : changeSid.hashCode());
result = prime * result + ((computerName == null) ? 0 : computerName.hashCode());
result = prime * result + ((customizationScript == null) ? 0 : customizationScript.hashCode());
result = prime * result + ((domainName == null) ? 0 : domainName.hashCode());
result = prime * result + ((domainUserName == null) ? 0 : domainUserName.hashCode());
result = prime * result + ((domainUserPassword == null) ? 0 : domainUserPassword.hashCode());
result = prime * result + ((edit == null) ? 0 : edit.hashCode());
result = prime * result + ((enabled == null) ? 0 : enabled.hashCode());
result = prime * result + ((href == null) ? 0 : href.hashCode());
result = prime * result + ((info == null) ? 0 : info.hashCode());
result = prime * result + ((joinDomainEnabled == null) ? 0 : joinDomainEnabled.hashCode());
result = prime * result + ((resetPasswordRequired == null) ? 0 : resetPasswordRequired.hashCode());
result = prime * result + ((type == null) ? 0 : type.hashCode());
result = prime * result + ((useOrgSettings == null) ? 0 : useOrgSettings.hashCode());
result = prime * result + ((virtualMachineId == null) ? 0 : virtualMachineId.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
GuestCustomization other = (GuestCustomization) obj;
if (adminPassword == null) {
if (other.adminPassword != null)
return false;
} else if (!adminPassword.equals(other.adminPassword))
return false;
if (adminPasswordAuto == null) {
if (other.adminPasswordAuto != null)
return false;
} else if (!adminPasswordAuto.equals(other.adminPasswordAuto))
return false;
if (adminPasswordEnabled == null) {
if (other.adminPasswordEnabled != null)
return false;
} else if (!adminPasswordEnabled.equals(other.adminPasswordEnabled))
return false;
if (changeSid == null) {
if (other.changeSid != null)
return false;
} else if (!changeSid.equals(other.changeSid))
return false;
if (computerName == null) {
if (other.computerName != null)
return false;
} else if (!computerName.equals(other.computerName))
return false;
if (customizationScript == null) {
if (other.customizationScript != null)
return false;
} else if (!customizationScript.equals(other.customizationScript))
return false;
if (domainName == null) {
if (other.domainName != null)
return false;
} else if (!domainName.equals(other.domainName))
return false;
if (domainUserName == null) {
if (other.domainUserName != null)
return false;
} else if (!domainUserName.equals(other.domainUserName))
return false;
if (domainUserPassword == null) {
if (other.domainUserPassword != null)
return false;
} else if (!domainUserPassword.equals(other.domainUserPassword))
return false;
if (edit == null) {
if (other.edit != null)
return false;
} else if (!edit.equals(other.edit))
return false;
if (enabled == null) {
if (other.enabled != null)
return false;
} else if (!enabled.equals(other.enabled))
return false;
if (href == null) {
if (other.href != null)
return false;
} else if (!href.equals(other.href))
return false;
if (info == null) {
if (other.info != null)
return false;
} else if (!info.equals(other.info))
return false;
if (joinDomainEnabled == null) {
if (other.joinDomainEnabled != null)
return false;
} else if (!joinDomainEnabled.equals(other.joinDomainEnabled))
return false;
if (resetPasswordRequired == null) {
if (other.resetPasswordRequired != null)
return false;
} else if (!resetPasswordRequired.equals(other.resetPasswordRequired))
return false;
if (type == null) {
if (other.type != null)
return false;
} else if (!type.equals(other.type))
return false;
if (useOrgSettings == null) {
if (other.useOrgSettings != null)
return false;
} else if (!useOrgSettings.equals(other.useOrgSettings))
return false;
if (virtualMachineId == null) {
if (other.virtualMachineId != null)
return false;
} else if (!virtualMachineId.equals(other.virtualMachineId))
return false;
return true;
}
}

View File

@ -77,7 +77,7 @@ public interface Vm extends ReferenceType {
*/
@Nullable
VCloudVirtualHardware getHardware();
/**
* @return operating system on this VM, or null, if part of a vApp template
*
@ -86,6 +86,14 @@ public interface Vm extends ReferenceType {
@Nullable
VCloudOperatingSystem getOperatingSystem();
/**
* @return guest customization section for this VM, or null if it doesn't exist
*
* @since vcloud api 1.0
*/
@Nullable
GuestCustomization getGuestCustomization();
/**
* read-only identifier created on import
*

View File

@ -26,6 +26,7 @@ import java.util.List;
import javax.annotation.Nullable;
import org.jclouds.vcloud.domain.GuestCustomization;
import org.jclouds.vcloud.domain.ReferenceType;
import org.jclouds.vcloud.domain.Status;
import org.jclouds.vcloud.domain.Task;
@ -54,10 +55,13 @@ public class VmImpl extends ReferenceTypeImpl implements Vm {
private final VCloudVirtualHardware hardware;
private final String vAppScopedLocalId;
private final VCloudOperatingSystem os;
@Nullable
private final GuestCustomization guestCustomization;
public VmImpl(String name, String type, URI id, @Nullable Status status, ReferenceType vApp,
@Nullable String description, Iterable<Task> tasks, @Nullable VCloudVirtualHardware hardware,
@Nullable VCloudOperatingSystem os, @Nullable String vAppScopedLocalId) {
@Nullable VCloudOperatingSystem os, @Nullable GuestCustomization guestCustomization,
@Nullable String vAppScopedLocalId) {
super(name, type, id);
this.status = status;
this.vApp = vApp;// TODO: once <1.0 is killed check not null
@ -65,6 +69,7 @@ public class VmImpl extends ReferenceTypeImpl implements Vm {
Iterables.addAll(this.tasks, checkNotNull(tasks, "tasks"));
this.hardware = hardware;
this.os = os;
this.guestCustomization = guestCustomization;
this.vAppScopedLocalId = vAppScopedLocalId;
}
@ -117,6 +122,14 @@ public class VmImpl extends ReferenceTypeImpl implements Vm {
return os;
}
/**
* {@inheritDoc}
*/
@Override
public GuestCustomization getGuestCustomization() {
return guestCustomization;
}
/**
* {@inheritDoc}
*/
@ -130,10 +143,9 @@ public class VmImpl extends ReferenceTypeImpl implements Vm {
final int prime = 31;
int result = super.hashCode();
result = prime * result + ((description == null) ? 0 : description.hashCode());
result = prime * result + ((guestCustomization == null) ? 0 : guestCustomization.hashCode());
result = prime * result + ((hardware == null) ? 0 : hardware.hashCode());
result = prime * result + ((os == null) ? 0 : os.hashCode());
result = prime * result + ((status == null) ? 0 : status.hashCode());
result = prime * result + ((tasks == null) ? 0 : tasks.hashCode());
result = prime * result + ((vApp == null) ? 0 : vApp.hashCode());
result = prime * result + ((vAppScopedLocalId == null) ? 0 : vAppScopedLocalId.hashCode());
return result;
@ -153,6 +165,11 @@ public class VmImpl extends ReferenceTypeImpl implements Vm {
return false;
} else if (!description.equals(other.description))
return false;
if (guestCustomization == null) {
if (other.guestCustomization != null)
return false;
} else if (!guestCustomization.equals(other.guestCustomization))
return false;
if (hardware == null) {
if (other.hardware != null)
return false;
@ -163,16 +180,6 @@ public class VmImpl extends ReferenceTypeImpl implements Vm {
return false;
} else if (!os.equals(other.os))
return false;
if (status == null) {
if (other.status != null)
return false;
} else if (!status.equals(other.status))
return false;
if (tasks == null) {
if (other.tasks != null)
return false;
} else if (!tasks.equals(other.tasks))
return false;
if (vApp == null) {
if (other.vApp != null)
return false;

View File

@ -0,0 +1,137 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.vcloud.xml;
import static org.jclouds.vcloud.util.Utils.cleanseAttributes;
import static org.jclouds.vcloud.util.Utils.newReferenceType;
import java.util.Map;
import org.jclouds.http.functions.ParseSax;
import org.jclouds.vcloud.domain.GuestCustomization;
import org.jclouds.vcloud.domain.ReferenceType;
import org.xml.sax.Attributes;
/**
* @author Adrian Cole
*/
public class GuestCustomizationHandler extends ParseSax.HandlerWithResult<GuestCustomization> {
protected StringBuilder currentText = new StringBuilder();
private ReferenceType guest;
private ReferenceType edit;
protected String info;
protected String name;
protected Boolean enabled;
protected Boolean changeSid;
protected String virtualMachineId;
protected Boolean joinDomainEnabled;
protected Boolean useOrgSettings;
protected String domainName;
protected String domainUserName;
protected String domainUserPassword;
protected Boolean adminPasswordEnabled;
protected Boolean adminPasswordAuto;
protected String adminPassword;
protected Boolean resetPasswordRequired;
protected String customizationScript;
protected String computerName;
public GuestCustomization getResult() {
GuestCustomization system = new GuestCustomization(guest.getType(), guest.getHref(), info, enabled,
changeSid, virtualMachineId, joinDomainEnabled, useOrgSettings, domainName, domainUserName,
domainUserPassword, adminPasswordEnabled, adminPasswordAuto, adminPassword, resetPasswordRequired,
customizationScript, computerName, edit);
this.guest = null;
this.info = null;
this.edit = null;
this.enabled = null;
this.changeSid = null;
this.virtualMachineId = null;
this.joinDomainEnabled = null;
this.useOrgSettings = null;
this.domainName = null;
this.domainUserName = null;
this.domainUserPassword = null;
this.adminPasswordEnabled = null;
this.adminPasswordAuto = null;
this.adminPassword = null;
this.resetPasswordRequired = null;
this.customizationScript = null;
this.computerName = null;
return system;
}
public void startElement(String uri, String localName, String qName, Attributes attrs) {
Map<String, String> attributes = cleanseAttributes(attrs);
if (qName.endsWith("GuestCustomizationSection")) {
guest = newReferenceType(attributes);
} else if (qName.endsWith("Link") && "edit".equals(attributes.get("rel"))) {
edit = newReferenceType(attributes);
}
}
@Override
public void endElement(String uri, String localName, String qName) {
if (qName.endsWith("Info")) {
this.info = currentOrNull();
} else if (qName.endsWith("AdminPasswordEnabled")) {
this.adminPasswordEnabled = Boolean.parseBoolean(currentOrNull());
} else if (qName.endsWith("JoinDomainEnabled")) {
this.joinDomainEnabled = Boolean.parseBoolean(currentOrNull());
} else if (qName.endsWith("Enabled")) {
this.enabled = Boolean.parseBoolean(currentOrNull());
} else if (qName.endsWith("ChangeSid")) {
this.changeSid = Boolean.parseBoolean(currentOrNull());
} else if (qName.endsWith("VirtualMachineId")) {
this.virtualMachineId = currentOrNull();
} else if (qName.endsWith("UseOrgSettings")) {
this.useOrgSettings = Boolean.parseBoolean(currentOrNull());
} else if (qName.endsWith("DomainName")) {
this.domainName = currentOrNull();
} else if (qName.endsWith("DomainUserName")) {
this.domainUserName = currentOrNull();
} else if (qName.endsWith("DomainUserPassword")) {
this.domainUserPassword = currentOrNull();
} else if (qName.endsWith("AdminPasswordAuto")) {
this.adminPasswordAuto = Boolean.parseBoolean(currentOrNull());
} else if (qName.endsWith("AdminPassword")) {
this.adminPassword = currentOrNull();
} else if (qName.endsWith("ResetPasswordRequired")) {
this.resetPasswordRequired = Boolean.parseBoolean(currentOrNull());
} else if (qName.endsWith("CustomizationScript")) {
this.customizationScript = currentOrNull();
} else if (qName.endsWith("ComputerName")) {
this.computerName = currentOrNull();
} else if (qName.endsWith("Name")) {
this.name = currentOrNull();
}
currentText = new StringBuilder();
}
public void characters(char ch[], int start, int length) {
currentText.append(ch, start, length);
}
protected String currentOrNull() {
String returnVal = currentText.toString().trim();
return returnVal.equals("") ? null : returnVal;
}
}

View File

@ -28,6 +28,7 @@ import java.util.Map;
import javax.inject.Inject;
import org.jclouds.http.functions.ParseSax;
import org.jclouds.vcloud.domain.GuestCustomization;
import org.jclouds.vcloud.domain.ReferenceType;
import org.jclouds.vcloud.domain.Status;
import org.jclouds.vcloud.domain.Task;
@ -49,13 +50,15 @@ public class VmHandler extends ParseSax.HandlerWithResult<Vm> {
protected final TaskHandler taskHandler;
protected final VCloudVirtualHardwareHandler virtualHardwareHandler;
protected final VCloudOperatingSystemHandler operatingSystemHandler;
protected final GuestCustomizationHandler guestCustomizationHandler;
@Inject
public VmHandler(TaskHandler taskHandler, VCloudVirtualHardwareHandler virtualHardwareHandler,
VCloudOperatingSystemHandler operatingSystemHandler) {
VCloudOperatingSystemHandler operatingSystemHandler, GuestCustomizationHandler guestCustomizationHandler) {
this.taskHandler = taskHandler;
this.virtualHardwareHandler = virtualHardwareHandler;
this.operatingSystemHandler = operatingSystemHandler;
this.guestCustomizationHandler = guestCustomizationHandler;
}
protected StringBuilder currentText = new StringBuilder();
@ -67,15 +70,17 @@ public class VmHandler extends ParseSax.HandlerWithResult<Vm> {
protected List<Task> tasks = Lists.newArrayList();
protected VCloudVirtualHardware hardware;
protected VCloudOperatingSystem os;
protected GuestCustomization guestCustomization;
protected String vAppScopedLocalId;
private boolean inTasks;
private boolean inHardware;
private boolean inOs;
private boolean inGuestCustomization;
public Vm getResult() {
return new VmImpl(vm.getName(), vm.getType(), vm.getHref(), status, vdc, description, tasks, hardware, os,
vAppScopedLocalId);
guestCustomization, vAppScopedLocalId);
}
@Override
@ -85,6 +90,8 @@ public class VmHandler extends ParseSax.HandlerWithResult<Vm> {
inHardware = true;
} else if (qName.endsWith("OperatingSystemSection")) {
inOs = true;
} else if (qName.endsWith("GuestCustomizationSection")) {
inGuestCustomization = true;
} else if (qName.endsWith("Tasks")) {
inTasks = true;
}
@ -92,6 +99,8 @@ public class VmHandler extends ParseSax.HandlerWithResult<Vm> {
virtualHardwareHandler.startElement(uri, localName, qName, attrs);
} else if (inOs) {
operatingSystemHandler.startElement(uri, localName, qName, attrs);
} else if (inGuestCustomization) {
guestCustomizationHandler.startElement(uri, localName, qName, attrs);
} else if (inTasks) {
taskHandler.startElement(uri, localName, qName, attrs);
} else if (qName.equals("Vm")) {
@ -111,6 +120,9 @@ public class VmHandler extends ParseSax.HandlerWithResult<Vm> {
} else if (qName.endsWith("OperatingSystemSection")) {
inOs = false;
os = operatingSystemHandler.getResult();
} else if (qName.endsWith("GuestCustomizationSection")) {
inGuestCustomization = false;
guestCustomization = guestCustomizationHandler.getResult();
} else if (qName.endsWith("Tasks")) {
inTasks = false;
this.tasks.add(taskHandler.getResult());
@ -119,6 +131,8 @@ public class VmHandler extends ParseSax.HandlerWithResult<Vm> {
virtualHardwareHandler.endElement(uri, name, qName);
} else if (inOs) {
operatingSystemHandler.endElement(uri, name, qName);
} else if (inGuestCustomization) {
guestCustomizationHandler.endElement(uri, name, qName);
} else if (inTasks) {
taskHandler.endElement(uri, name, qName);
} else if (qName.equals("Description")) {
@ -136,6 +150,8 @@ public class VmHandler extends ParseSax.HandlerWithResult<Vm> {
virtualHardwareHandler.characters(ch, start, length);
if (inOs)
operatingSystemHandler.characters(ch, start, length);
if (inGuestCustomization)
guestCustomizationHandler.characters(ch, start, length);
currentText.append(ch, start, length);
}

View File

@ -565,8 +565,8 @@ public class VCloudAsyncClientTest extends RestClientTest<VCloudAsyncClient> {
assertNonPayloadHeadersEqual(request, "");
assertPayloadEquals(request, null, null, false);
assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
assertSaxResponseParserClassEquals(method, null);
assertResponseParserClassEquals(method, request, ParseSax.class);
assertSaxResponseParserClassEquals(method, TaskHandler.class);
assertExceptionParserClassEquals(method, ReturnVoidOnNotFoundOr404.class);
checkFilters(request);

View File

@ -0,0 +1,76 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.vcloud.xml;
import static org.testng.Assert.assertEquals;
import java.io.InputStream;
import java.net.URI;
import java.net.UnknownHostException;
import org.jclouds.http.functions.BaseHandlerTest;
import org.jclouds.vcloud.VCloudMediaType;
import org.jclouds.vcloud.domain.GuestCustomization;
import org.jclouds.vcloud.domain.internal.ReferenceTypeImpl;
import org.testng.annotations.Test;
/**
* Tests behavior of {@code GuestCustomizationSectionHandler}
*
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "vcloud.GuestCustomizationSectionHandlerTest")
public class GuestCustomizationHandlerTest extends BaseHandlerTest {
public void testDefault() throws UnknownHostException {
InputStream is = getClass().getResourceAsStream("/guestCustomization.xml");
GuestCustomization result = factory.create(injector.getInstance(GuestCustomizationHandler.class)).parse(is);
checkGuestCustomization(result);
}
@Test(enabled = false)
public static void checkGuestCustomization(GuestCustomization result) {
assertEquals(result.getType(), VCloudMediaType.GUESTCUSTOMIZATIONSECTION_XML);
assertEquals(result.getHref(), URI
.create("https://vcenterprise.bluelock.com/api/v1.0/vApp/vm-2087535248/guestCustomizationSection/"));
assertEquals(result.getInfo(), "Specifies Guest OS Customization Settings");
assertEquals(result.isEnabled(), new Boolean(true));
assertEquals(result.shouldChangeSid(), new Boolean(false));
assertEquals(result.getVirtualMachineId(), "2087535248");
assertEquals(result.isJoinDomainEnabled(), new Boolean(false));
assertEquals(result.useOrgSettings(), new Boolean(false));
assertEquals(result.getDomainName(), null);
assertEquals(result.getDomainUserName(), null);
assertEquals(result.getDomainUserPassword(), null);
assertEquals(result.isAdminPasswordEnabled(), new Boolean(true));
assertEquals(result.isAdminPasswordAuto(), new Boolean(true));
assertEquals(result.getAdminPassword(), null);
assertEquals(result.isResetPasswordRequired(), new Boolean(false));
assertEquals(
result.getCustomizationScript(),
"#!/bin/bash if [[ $1 == \"postcustomization\" ]]; then echo \"post customization\" touch /root/.postcustomization ping www.redhat.com -c 1 sleep 30 # register with RHN /usr/sbin/rhnreg_ks --profilename vic_`hostname`_`dmidecode -s system-uuid` --activationkey=XXXXXXXXXXXX --force echo \"rhn registered\" # make hostname fully qualified to speed up sendmail start perl -i -pe \"s/`hostname`/`hostname`.victory.blk/g\" /etc/sysconfig/network rm /etc/ssh/*_key* service sshd restart echo \"completed\" fi");
assertEquals(result.getComputerName(), "RHEL5");
assertEquals(result.getEdit(), new ReferenceTypeImpl(null, VCloudMediaType.GUESTCUSTOMIZATIONSECTION_XML, URI
.create("https://vcenterprise.bluelock.com/api/v1.0/vApp/vm-2087535248/guestCustomizationSection/")));
}
}

View File

@ -28,6 +28,7 @@ import org.jclouds.http.functions.ParseSax;
import org.jclouds.http.functions.ParseSax.Factory;
import org.jclouds.http.functions.config.SaxParserModule;
import org.jclouds.vcloud.VCloudMediaType;
import org.jclouds.vcloud.domain.GuestCustomization;
import org.jclouds.vcloud.domain.Status;
import org.jclouds.vcloud.domain.VAppTemplate;
import org.jclouds.vcloud.domain.Vm;
@ -77,6 +78,32 @@ public class VAppTemplateHandlerTest {
assertEquals(vm.getTasks(), ImmutableList.of());
assertEquals(vm.getVAppScopedLocalId(), "02_ubuntu_template");
GuestCustomization guestC = vm.getGuestCustomization();
assertEquals(guestC.getType(), VCloudMediaType.GUESTCUSTOMIZATIONSECTION_XML);
assertEquals(
guestC.getHref(),
URI
.create("https://vcenterprise.bluelock.com/api/v1.0/vAppTemplate/vm-172837194/guestCustomizationSection/"));
assertEquals(guestC.getInfo(), "Specifies Guest OS Customization Settings");
assertEquals(guestC.isEnabled(), new Boolean(true));
assertEquals(guestC.shouldChangeSid(), new Boolean(false));
assertEquals(guestC.getVirtualMachineId(), "172837194");
assertEquals(guestC.isJoinDomainEnabled(), new Boolean(false));
assertEquals(guestC.useOrgSettings(), new Boolean(false));
assertEquals(guestC.getDomainName(), null);
assertEquals(guestC.getDomainUserName(), null);
assertEquals(guestC.getDomainUserPassword(), null);
assertEquals(guestC.isAdminPasswordEnabled(), new Boolean(true));
assertEquals(guestC.isAdminPasswordAuto(), new Boolean(true));
assertEquals(guestC.getAdminPassword(), "%3eD%gmF");
assertEquals(guestC.isResetPasswordRequired(), new Boolean(false));
assertEquals(
guestC.getCustomizationScript(),
"#!/bin/bash if [ \"$1\" = \"postcustomization\" ]; then echo \"post customization\" touch /root/.postcustomization sleep 30 #regenerate keys /bin/rm /etc/ssh/ssh_host_* /usr/sbin/dpkg-reconfigure openssh-server echo \"completed\" fi");
assertEquals(guestC.getComputerName(), "Ubuntu1004");
assertEquals(guestC.getEdit(), null);
VCloudNetworkSection network = result.getNetworkSection();
assertEquals(
network.getHref(),

View File

@ -66,6 +66,7 @@ public class VmHandlerTest {
assertEquals(result.getVAppScopedLocalId(), "10_rhel_template");
VCloudVirtualHardwareHandlerTest.checkHardware(result.getHardware());
VCloudOperatingSystemHandlerTest.checkOs(result.getOperatingSystem());
GuestCustomizationHandlerTest.checkGuestCustomization(result.getGuestCustomization());
}
}

View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<GuestCustomizationSection
type="application/vnd.vmware.vcloud.guestCustomizationSection+xml"
href="https://vcenterprise.bluelock.com/api/v1.0/vApp/vm-2087535248/guestCustomizationSection/"
ovf:required="false">
<ovf:Info>Specifies Guest OS Customization Settings</ovf:Info>
<Enabled>true</Enabled>
<ChangeSid>false</ChangeSid>
<VirtualMachineId>2087535248</VirtualMachineId>
<JoinDomainEnabled>false</JoinDomainEnabled>
<UseOrgSettings>false</UseOrgSettings>
<AdminPasswordEnabled>true</AdminPasswordEnabled>
<AdminPasswordAuto>true</AdminPasswordAuto>
<ResetPasswordRequired>false</ResetPasswordRequired>
<CustomizationScript>#!/bin/bash if [[ $1 == "postcustomization" ]]; then echo "post customization" touch /root/.postcustomization ping www.redhat.com -c 1 sleep 30 # register with RHN /usr/sbin/rhnreg_ks --profilename vic_`hostname`_`dmidecode -s system-uuid` --activationkey=XXXXXXXXXXXX --force echo "rhn registered" # make hostname fully qualified to speed up sendmail start perl -i -pe "s/`hostname`/`hostname`.victory.blk/g" /etc/sysconfig/network rm /etc/ssh/*_key* service sshd restart echo "completed" fi</CustomizationScript>
<ComputerName>RHEL5</ComputerName>
<Link rel="edit"
type="application/vnd.vmware.vcloud.guestCustomizationSection+xml"
href="https://vcenterprise.bluelock.com/api/v1.0/vApp/vm-2087535248/guestCustomizationSection/" />
</GuestCustomizationSection>