Merge pull request #373 from danikov/vclouds-director-bugfixes

Issue 830: vCloud director common changes
This commit is contained in:
Andrei Savu 2012-02-16 14:27:09 -08:00
commit 6c7c69899a
11 changed files with 230 additions and 86 deletions

View File

@ -68,11 +68,15 @@ public class VCloudDirectorMediaType {
public static final String MEDIA = "application/vnd.vmware.vcloud.media+xml"; public static final String MEDIA = "application/vnd.vmware.vcloud.media+xml";
public static final String OWNER = "application/vnd.vmware.vcloud.owner+xml"; public static final String OWNER = "application/vnd.vmware.vcloud.owner+xml";
public static final String VDC = "application/vnd.vmware.vcloud.vdc+xml";
public static final String ADMIN_USER = "application/vnd.vmware.admin.user+xml";
public static final List<String> ALL = Arrays.asList( public static final List<String> ALL = Arrays.asList(
SESSION, ERROR, ORG_LIST, METADATA, METADATA_ENTRY, SESSION, ERROR, ORG_LIST, METADATA, METADATA_ENTRY,
METADATA_VALUE, ORG, TASKS_LIST, TASK, ORG_NETWORK, METADATA_VALUE, ORG, TASKS_LIST, TASK, ORG_NETWORK,
CATALOG, CATALOG_ITEM, CATALOG_ITEMS, CATALOGS_LIST, PROPERTY, CATALOG, CATALOG_ITEM, CATALOG_ITEMS, CATALOGS_LIST, PROPERTY,
MEDIA, OWNER MEDIA, OWNER, VDC, ADMIN_USER
); );
} }

View File

@ -47,10 +47,13 @@ public class Link extends ReferenceType<Link> {
public static final String DOWN = "down"; public static final String DOWN = "down";
public static final String EDIT = "edit"; public static final String EDIT = "edit";
public static final String DELETE = "delete"; public static final String DELETE = "delete";
public static final String ADD = "add";
public static final String REMOVE = "remove";
public static final String CATALOG_ITEM = "catalogItem";
public static final String TASK_CANCEL = "task:cancel"; public static final String TASK_CANCEL = "task:cancel";
public static final List<String> ALL = Arrays.asList( public static final List<String> ALL = Arrays.asList(
UP, DOWN, EDIT, DELETE, TASK_CANCEL UP, DOWN, EDIT, DELETE, ADD, REMOVE, CATALOG_ITEM, TASK_CANCEL
); );
} }

View File

@ -147,6 +147,13 @@ public class Task extends EntityType<Task> {
this.status = status; this.status = status;
return this; return this;
} }
/**
* @see Task#getStatus()
*/
public Builder status(TaskStatus status) {
return this.status(status.toString());
}
/** /**
* @see Task#getOperation() * @see Task#getOperation()
@ -411,8 +418,12 @@ public class Task extends EntityType<Task> {
* <li>aborted - The task was aborted by an administrative action. * <li>aborted - The task was aborted by an administrative action.
* </ul> * </ul>
*/ */
public String getStatus() { public TaskStatus getStatus() {
return status; return TaskStatus.fromValue(status);
}
public void setStatus(TaskStatus status) {
this.setStatus(status.toString());
} }
public void setStatus(String status) { public void setStatus(String status) {

View File

@ -0,0 +1,41 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds 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.vcloud.director.v1_5.domain;
/**
*
* @author Adrian Cole
*
*/
public class TaskInErrorStateException extends RuntimeException {
private static final long serialVersionUID = 1L;
private final Task task;
public TaskInErrorStateException(Task task) {
super("error on task: " + task + " error: " + task.getError());
this.task = task;
}
public Task getTask() {
return task;
}
}

View File

@ -0,0 +1,73 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds 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.vcloud.director.v1_5.domain;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* @author Adrian Cole
*/
public enum TaskStatus {
/**
* The task has completed and returned a value indicating success.
*/
SUCCESS,
/**
* The task is running.
*/
RUNNING,
/**
* The task has been queued for execution.
*/
QUEUED,
/**
* The task has completed and returned a value indicating an error.
*/
ERROR,
/**
* not an official status, temporarily in.
*/
CANCELLED, UNRECOGNIZED;
public String value() {
return name().toLowerCase();
}
@Override
public String toString() {
return value();
}
public static TaskStatus fromValue(String status) {
if ("CANCELED".equals(status.toUpperCase())) {
// TODO: ecloud hack
status = "CANCELLED";
} else if ("FAILED".equals(status.toUpperCase())) {
status = "ERROR";
} else if ("COMPLETED".equals(status.toUpperCase())) {
status = "SUCCESS";
}
try {
return valueOf(checkNotNull(status, "status").toUpperCase());
} catch (IllegalArgumentException e) {
return UNRECOGNIZED;
}
}
}

View File

@ -29,12 +29,11 @@ import org.jclouds.rest.annotations.EndpointParam;
import org.jclouds.rest.annotations.ExceptionParser; import org.jclouds.rest.annotations.ExceptionParser;
import org.jclouds.rest.annotations.JAXBResponseParser; import org.jclouds.rest.annotations.JAXBResponseParser;
import org.jclouds.rest.annotations.RequestFilters; import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.vcloud.director.v1_5.domain.ReferenceType; import org.jclouds.vcloud.director.v1_5.domain.Reference;
import org.jclouds.vcloud.director.v1_5.domain.Task; import org.jclouds.vcloud.director.v1_5.domain.Task;
import org.jclouds.vcloud.director.v1_5.domain.TasksList; import org.jclouds.vcloud.director.v1_5.domain.TasksList;
import org.jclouds.vcloud.director.v1_5.filters.AddVCloudAuthorizationToRequest; import org.jclouds.vcloud.director.v1_5.filters.AddVCloudAuthorizationToRequest;
import org.jclouds.vcloud.director.v1_5.functions.OrgReferenceToTaskListEndpoint; import org.jclouds.vcloud.director.v1_5.functions.OrgReferenceToTaskListEndpoint;
import org.jclouds.vcloud.director.v1_5.functions.ReferenceToEndpoint;
import org.jclouds.vcloud.director.v1_5.functions.ThrowVCloudErrorOn4xx; import org.jclouds.vcloud.director.v1_5.functions.ThrowVCloudErrorOn4xx;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;
@ -53,7 +52,7 @@ public interface TaskAsyncClient {
@Consumes @Consumes
@JAXBResponseParser @JAXBResponseParser
@ExceptionParser(ThrowVCloudErrorOn4xx.class) @ExceptionParser(ThrowVCloudErrorOn4xx.class)
ListenableFuture<TasksList> getTaskList(@EndpointParam(parser = OrgReferenceToTaskListEndpoint.class) ReferenceType<?> orgRef); ListenableFuture<TasksList> getTaskList(@EndpointParam(parser = OrgReferenceToTaskListEndpoint.class) Reference orgRef);
/** /**
* @see TaskClient#getTask(URI) * @see TaskClient#getTask(URI)

View File

@ -22,7 +22,7 @@ import java.net.URI;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import org.jclouds.concurrent.Timeout; import org.jclouds.concurrent.Timeout;
import org.jclouds.vcloud.director.v1_5.domain.ReferenceType; import org.jclouds.vcloud.director.v1_5.domain.Reference;
import org.jclouds.vcloud.director.v1_5.domain.Task; import org.jclouds.vcloud.director.v1_5.domain.Task;
import org.jclouds.vcloud.director.v1_5.domain.TasksList; import org.jclouds.vcloud.director.v1_5.domain.TasksList;
@ -45,7 +45,7 @@ public interface TaskClient {
* @param orgId the unique id for the organization * @param orgId the unique id for the organization
* @return a list of tasks * @return a list of tasks
*/ */
TasksList getTaskList(ReferenceType<?> orgRef); TasksList getTaskList(Reference orgRef);
/** /**
* Retrieves a task. * Retrieves a task.

View File

@ -0,0 +1,70 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds 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.vcloud.director.v1_5.predicates;
import java.net.URI;
import javax.annotation.Resource;
import javax.inject.Singleton;
import org.jclouds.logging.Logger;
import org.jclouds.rest.RestContext;
import org.jclouds.vcloud.director.v1_5.VCloudDirectorAsyncClient;
import org.jclouds.vcloud.director.v1_5.VCloudDirectorClient;
import org.jclouds.vcloud.director.v1_5.domain.Task;
import org.jclouds.vcloud.director.v1_5.domain.TaskInErrorStateException;
import org.jclouds.vcloud.director.v1_5.domain.TaskStatus;
import org.jclouds.vcloud.director.v1_5.features.TaskClient;
import com.google.common.base.Predicate;
import com.google.inject.Inject;
/**
*
* Tests to see if a task succeeds.
*
* @author Adrian Cole
*/
@Singleton
public class TaskSuccess implements Predicate<URI> {
private final TaskClient taskClient;
@Resource
protected Logger logger = Logger.NULL;
@Inject
public TaskSuccess(RestContext<VCloudDirectorClient, VCloudDirectorAsyncClient> context) {
this.taskClient = context.getApi().getTaskClient();
}
public boolean apply(URI taskUri) {
logger.trace("looking for status on task %s", taskUri);
Task task = taskClient.getTask(taskUri);
// perhaps task isn't available, yet
if (task == null)
return false;
logger.trace("%s: looking for status %s: currently: %s", task, TaskStatus.SUCCESS, task.getStatus());
if (task.getStatus() == TaskStatus.ERROR)
throw new TaskInErrorStateException(task);
return task.getStatus() == TaskStatus.SUCCESS;
}
}

View File

@ -18,7 +18,10 @@
*/ */
package org.jclouds.vcloud.director.v1_5.domain; package org.jclouds.vcloud.director.v1_5.domain;
import static org.testng.Assert.*; import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.fail;
import java.net.URI; import java.net.URI;
import java.util.Set; import java.util.Set;
@ -87,7 +90,9 @@ public class Checks {
} }
public static void checkType(String type) { public static void checkType(String type) {
assertTrue(VCloudDirectorMediaType.ALL.contains(type), "The Type must be a valid media type"); assertTrue(VCloudDirectorMediaType.ALL.contains(type),
String.format("The Type (%s) must be a valid media type - %s", type,
Iterables.toString(VCloudDirectorMediaType.ALL)));
} }
// NOTE this does not currently check anything // NOTE this does not currently check anything
@ -104,7 +109,9 @@ public class Checks {
public static void checkLink(Link link) { public static void checkLink(Link link) {
// Check required fields // Check required fields
assertNotNull(link.getRel(), "The Rel attribute of a Link must be set"); assertNotNull(link.getRel(), "The Rel attribute of a Link must be set");
assertTrue(Link.Rel.ALL.contains(link.getRel()), "The Rel attribute of a Link must be one of the allowed list"); assertTrue(Link.Rel.ALL.contains(link.getRel()),
String.format("The Rel attribute (%s) of a Link must be one of the allowed list - %s",
link.getRel(), Iterables.toString(Link.Rel.ALL)));
// Check parent type // Check parent type
checkReferenceType(link); checkReferenceType(link);
@ -113,7 +120,9 @@ public class Checks {
public static void checkTask(Task task) { public static void checkTask(Task task) {
// Check required fields // Check required fields
assertNotNull(task.getStatus(), "The Status attribute of a Task must be set"); assertNotNull(task.getStatus(), "The Status attribute of a Task must be set");
assertTrue(Task.Status.ALL.contains(task.getStatus()), "The Status of a Task must be one of the allowed list"); assertTrue(Task.Status.ALL.contains(task.getStatus().toString()),
String.format("The Status of a Task (%s) must be one of the allowed list - %s",
task.getStatus().toString(), Iterables.toString(Task.Status.ALL)));
// Check optional fields // Check optional fields
// NOTE operation cannot be checked // NOTE operation cannot be checked

View File

@ -18,14 +18,11 @@
*/ */
package org.jclouds.vcloud.director.v1_5.features; package org.jclouds.vcloud.director.v1_5.features;
import static org.jclouds.vcloud.director.v1_5.VCloudDirectorLiveTestConstants.*; import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkTask;
import static org.jclouds.vcloud.director.v1_5.domain.Checks.*; import static org.testng.Assert.assertFalse;
import static org.testng.Assert.*;
import java.net.URI; import java.net.URI;
import org.jclouds.vcloud.director.v1_5.domain.Metadata;
import org.jclouds.vcloud.director.v1_5.domain.MetadataEntry;
import org.jclouds.vcloud.director.v1_5.domain.OrgList; import org.jclouds.vcloud.director.v1_5.domain.OrgList;
import org.jclouds.vcloud.director.v1_5.domain.Reference; import org.jclouds.vcloud.director.v1_5.domain.Reference;
import org.jclouds.vcloud.director.v1_5.domain.Task; import org.jclouds.vcloud.director.v1_5.domain.Task;
@ -55,11 +52,11 @@ public class CatalogClientLiveTest extends BaseVCloudDirectorClientLiveTest {
@Test(testName = "GET /tasksList/{id}") @Test(testName = "GET /tasksList/{id}")
public void testGetTaskList() { public void testGetTaskList() {
orgList = getOrgList(); orgList = context.getApi().getOrgClient().getOrgList();
orgRef = Iterables.getFirst(orgList.getOrgs(), null); orgRef = Iterables.getFirst(orgList.getOrgs(), null);
// Call the method being tested // Call the method being tested
taskList = getTaskList(orgRef); taskList = context.getApi().getTaskClient().getTaskList(orgRef);
// NOTE The environment MUST have ... // NOTE The environment MUST have ...
@ -76,7 +73,7 @@ public class CatalogClientLiveTest extends BaseVCloudDirectorClientLiveTest {
taskUri = Iterables.getFirst(taskList.getTasks(), null).getHref(); taskUri = Iterables.getFirst(taskList.getTasks(), null).getHref();
// Call the method being tested // Call the method being tested
task = getTask(taskUri); task = context.getApi().getTaskClient().getTask(taskUri);
// Check required elements and attributes // Check required elements and attributes
checkTask(task); checkTask(task);
@ -85,6 +82,6 @@ public class CatalogClientLiveTest extends BaseVCloudDirectorClientLiveTest {
@Test(testName = "GET /task/{id}/metadata/", dependsOnMethods = { "testGetTask" }) @Test(testName = "GET /task/{id}/metadata/", dependsOnMethods = { "testGetTask" })
public void testCancelTask() { public void testCancelTask() {
// Call the method being tested // Call the method being tested
cancelTask(taskUri); context.getApi().getTaskClient().cancelTask(taskUri);
} }
} }

View File

@ -18,7 +18,6 @@
*/ */
package org.jclouds.vcloud.director.v1_5.internal; package org.jclouds.vcloud.director.v1_5.internal;
import java.net.URI;
import java.util.Properties; import java.util.Properties;
import org.jclouds.compute.BaseVersionedServiceLiveTest; import org.jclouds.compute.BaseVersionedServiceLiveTest;
@ -28,15 +27,6 @@ import org.jclouds.rest.RestContextFactory;
import org.jclouds.sshj.config.SshjSshClientModule; import org.jclouds.sshj.config.SshjSshClientModule;
import org.jclouds.vcloud.director.v1_5.VCloudDirectorAsyncClient; import org.jclouds.vcloud.director.v1_5.VCloudDirectorAsyncClient;
import org.jclouds.vcloud.director.v1_5.VCloudDirectorClient; import org.jclouds.vcloud.director.v1_5.VCloudDirectorClient;
import org.jclouds.vcloud.director.v1_5.domain.Metadata;
import org.jclouds.vcloud.director.v1_5.domain.MetadataEntry;
import org.jclouds.vcloud.director.v1_5.domain.Org;
import org.jclouds.vcloud.director.v1_5.domain.OrgList;
import org.jclouds.vcloud.director.v1_5.domain.ReferenceType;
import org.jclouds.vcloud.director.v1_5.domain.Task;
import org.jclouds.vcloud.director.v1_5.domain.TasksList;
import org.jclouds.vcloud.director.v1_5.features.OrgClient;
import org.jclouds.vcloud.director.v1_5.features.TaskClient;
import org.testng.annotations.AfterGroups; import org.testng.annotations.AfterGroups;
import org.testng.annotations.BeforeGroups; import org.testng.annotations.BeforeGroups;
import org.testng.annotations.Test; import org.testng.annotations.Test;
@ -50,7 +40,7 @@ import com.google.inject.Module;
* @author Adrian Cole * @author Adrian Cole
*/ */
@Test(groups = "live") @Test(groups = "live")
public class BaseVCloudDirectorClientLiveTest extends BaseVersionedServiceLiveTest implements OrgClient, TaskClient { public class BaseVCloudDirectorClientLiveTest extends BaseVersionedServiceLiveTest {
public BaseVCloudDirectorClientLiveTest() { public BaseVCloudDirectorClientLiveTest() {
provider = "vcloud-director"; provider = "vcloud-director";
} }
@ -71,57 +61,4 @@ public class BaseVCloudDirectorClientLiveTest extends BaseVersionedServiceLiveTe
context.close(); context.close();
} }
private final OrgClient orgClient = context.getApi().getOrgClient();
private final TaskClient taskClient = context.getApi().getTaskClient();
/*
* Proxying implementations of OrgClient.
*/
/** @see OrgClient#getOrgList() */
@Override
public OrgList getOrgList() {
return orgClient.getOrgList();
}
/** @see OrgClient#getOrg(ReferenceType) */
@Override
public Org getOrg(ReferenceType<?> orgRef) {
return orgClient.getOrg(orgRef);
}
/** @see OrgClient#getOrgMetadata(ReferenceType) */
@Override
public Metadata getOrgMetadata(ReferenceType<?> orgRef) {
return orgClient.getOrgMetadata(orgRef);
}
/** @see OrgClient#getOrgMetadataEntry(ReferenceType, String) */
@Override
public MetadataEntry getOrgMetadataEntry(ReferenceType<?> orgRef, String key) {
return orgClient.getOrgMetadataEntry(orgRef, key);
}
/*
* Proxying implementations of TaskClient.
*/
/** @see TaskClient#getTaskList(ReferenceType) */
@Override
public TasksList getTaskList(ReferenceType<?> orgRef) {
return taskClient.getTaskList(orgRef);
}
/** @see TaskClient#getTask(URI) */
@Override
public Task getTask(URI taskUri) {
return taskClient.getTask(taskUri);
}
/** @see TaskClient#cancelTask(URI */
@Override
public void cancelTask(URI taskUri) {
taskClient.cancelTask(taskUri);
}
} }