Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Mike Arnold 2012-03-12 13:10:24 -05:00
commit a01d123a78
24 changed files with 850 additions and 49 deletions

View File

@ -26,6 +26,7 @@ import org.jclouds.vcloud.director.v1_5.domain.Media;
import org.jclouds.vcloud.director.v1_5.domain.Org; import org.jclouds.vcloud.director.v1_5.domain.Org;
import org.jclouds.vcloud.director.v1_5.domain.Session; import org.jclouds.vcloud.director.v1_5.domain.Session;
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.User;
import org.jclouds.vcloud.director.v1_5.domain.Vdc; import org.jclouds.vcloud.director.v1_5.domain.Vdc;
import org.jclouds.vcloud.director.v1_5.domain.ovf.Network; import org.jclouds.vcloud.director.v1_5.domain.ovf.Network;
import org.jclouds.vcloud.director.v1_5.features.AdminCatalogAsyncClient; import org.jclouds.vcloud.director.v1_5.features.AdminCatalogAsyncClient;
@ -37,6 +38,7 @@ import org.jclouds.vcloud.director.v1_5.features.OrgAsyncClient;
import org.jclouds.vcloud.director.v1_5.features.QueryAsyncClient; import org.jclouds.vcloud.director.v1_5.features.QueryAsyncClient;
import org.jclouds.vcloud.director.v1_5.features.TaskAsyncClient; import org.jclouds.vcloud.director.v1_5.features.TaskAsyncClient;
import org.jclouds.vcloud.director.v1_5.features.UploadAsyncClient; import org.jclouds.vcloud.director.v1_5.features.UploadAsyncClient;
import org.jclouds.vcloud.director.v1_5.features.UserAsyncClient;
import org.jclouds.vcloud.director.v1_5.features.VAppTemplateAsyncClient; import org.jclouds.vcloud.director.v1_5.features.VAppTemplateAsyncClient;
import org.jclouds.vcloud.director.v1_5.features.VdcAsyncClient; import org.jclouds.vcloud.director.v1_5.features.VdcAsyncClient;
@ -128,4 +130,10 @@ public interface VCloudDirectorAsyncClient {
*/ */
@Delegate @Delegate
AdminOrgAsyncClient getAdminOrgClient(); AdminOrgAsyncClient getAdminOrgClient();
/**
* @return asynchronous access to {@link User} features
*/
@Delegate
UserAsyncClient getUserClient();
} }

View File

@ -29,6 +29,7 @@ import org.jclouds.vcloud.director.v1_5.domain.Media;
import org.jclouds.vcloud.director.v1_5.domain.Org; import org.jclouds.vcloud.director.v1_5.domain.Org;
import org.jclouds.vcloud.director.v1_5.domain.Session; import org.jclouds.vcloud.director.v1_5.domain.Session;
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.User;
import org.jclouds.vcloud.director.v1_5.domain.Vdc; import org.jclouds.vcloud.director.v1_5.domain.Vdc;
import org.jclouds.vcloud.director.v1_5.domain.ovf.Network; import org.jclouds.vcloud.director.v1_5.domain.ovf.Network;
import org.jclouds.vcloud.director.v1_5.features.AdminCatalogClient; import org.jclouds.vcloud.director.v1_5.features.AdminCatalogClient;
@ -41,6 +42,7 @@ import org.jclouds.vcloud.director.v1_5.features.OrgClient;
import org.jclouds.vcloud.director.v1_5.features.QueryClient; import org.jclouds.vcloud.director.v1_5.features.QueryClient;
import org.jclouds.vcloud.director.v1_5.features.TaskClient; import org.jclouds.vcloud.director.v1_5.features.TaskClient;
import org.jclouds.vcloud.director.v1_5.features.UploadClient; import org.jclouds.vcloud.director.v1_5.features.UploadClient;
import org.jclouds.vcloud.director.v1_5.features.UserClient;
import org.jclouds.vcloud.director.v1_5.features.VAppTemplateClient; import org.jclouds.vcloud.director.v1_5.features.VAppTemplateClient;
import org.jclouds.vcloud.director.v1_5.features.VdcClient; import org.jclouds.vcloud.director.v1_5.features.VdcClient;
@ -131,4 +133,10 @@ public interface VCloudDirectorClient {
*/ */
@Delegate @Delegate
AdminOrgClient getAdminOrgClient(); AdminOrgClient getAdminOrgClient();
/**
* @return synchronous access to {@link User} features
*/
@Delegate
UserClient getUserClient();
} }

View File

@ -153,6 +153,10 @@ public class VCloudDirectorMediaType {
public static final String ADMIN_ORG_NETWORK = "application/vnd.vmware.admin.orgNetwork+xml"; public static final String ADMIN_ORG_NETWORK = "application/vnd.vmware.admin.orgNetwork+xml";
public static final String USER = "application/vnd.vmware.admin.user+xml";
public static final String ROLE = "application/vnd.vmware.admin.role+xml";
/** /**
* All acceptable media types. * All acceptable media types.
* *
@ -173,6 +177,6 @@ public class VCloudDirectorMediaType {
PUBLISH_CATALOG_PARAMS, GROUP, ORG_VAPP_TEMPLATE_LEASE_SETTINGS, PUBLISH_CATALOG_PARAMS, GROUP, ORG_VAPP_TEMPLATE_LEASE_SETTINGS,
ORG_LEASE_SETTINGS, ORG_PASSWORD_POLICY_SETTINGS, ORG_LDAP_SETTINGS, ORG_LEASE_SETTINGS, ORG_PASSWORD_POLICY_SETTINGS, ORG_LDAP_SETTINGS,
ORG_GENERAL_SETTINGS, ORG_EMAIL_SETTINGS, ORG_SETTINGS, ADMIN_NETWORK, ORG_GENERAL_SETTINGS, ORG_EMAIL_SETTINGS, ORG_SETTINGS, ADMIN_NETWORK,
ADMIN_ORG_NETWORK ADMIN_ORG_NETWORK, USER, ROLE
); );
} }

View File

@ -64,6 +64,8 @@ import org.jclouds.vcloud.director.v1_5.features.TaskAsyncClient;
import org.jclouds.vcloud.director.v1_5.features.TaskClient; import org.jclouds.vcloud.director.v1_5.features.TaskClient;
import org.jclouds.vcloud.director.v1_5.features.UploadAsyncClient; import org.jclouds.vcloud.director.v1_5.features.UploadAsyncClient;
import org.jclouds.vcloud.director.v1_5.features.UploadClient; import org.jclouds.vcloud.director.v1_5.features.UploadClient;
import org.jclouds.vcloud.director.v1_5.features.UserAsyncClient;
import org.jclouds.vcloud.director.v1_5.features.UserClient;
import org.jclouds.vcloud.director.v1_5.features.VAppTemplateAsyncClient; import org.jclouds.vcloud.director.v1_5.features.VAppTemplateAsyncClient;
import org.jclouds.vcloud.director.v1_5.features.VAppTemplateClient; import org.jclouds.vcloud.director.v1_5.features.VAppTemplateClient;
import org.jclouds.vcloud.director.v1_5.features.VdcAsyncClient; import org.jclouds.vcloud.director.v1_5.features.VdcAsyncClient;
@ -109,6 +111,7 @@ public class VCloudDirectorRestClientModule extends RestClientModule<VCloudDirec
.put(AdminCatalogClient.class, AdminCatalogAsyncClient.class) .put(AdminCatalogClient.class, AdminCatalogAsyncClient.class)
.put(AdminOrgClient.class, AdminOrgAsyncClient.class) .put(AdminOrgClient.class, AdminOrgAsyncClient.class)
.put(GroupClient.class, GroupAsyncClient.class) .put(GroupClient.class, GroupAsyncClient.class)
.put(UserClient.class, UserAsyncClient.class)
.build(); .build();
public VCloudDirectorRestClientModule() { public VCloudDirectorRestClientModule() {

View File

@ -22,13 +22,17 @@ import static com.google.common.base.Objects.equal;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import java.net.URI; import java.net.URI;
import java.util.List;
import java.util.Set; import java.util.Set;
import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType; import javax.xml.bind.annotation.XmlType;
import com.google.common.base.Objects; import com.google.common.base.Objects;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
/** /**
@ -88,7 +92,7 @@ import com.google.common.collect.Sets;
"deployedVmQuota", "deployedVmQuota",
"role", "role",
"password", "password",
"groupReferences" "groups"
}) })
public class User public class User
extends EntityType<User> extends EntityType<User>
@ -122,7 +126,7 @@ public class User
private Integer deployedVmQuota; private Integer deployedVmQuota;
private Reference role; private Reference role;
private String password; private String password;
private Object /* GroupsList */ groupReferences; private List<Reference> groups = Lists.newArrayList();
/** /**
* @see User#getFullName() * @see User#getFullName()
@ -261,22 +265,37 @@ public class User
} }
/** /**
* @see User#getGroupReferences() * @see User#getGroups()
*/ */
public Builder groupReferences(Object /* GroupsList */ groupReferences) { public Builder groups(List<Reference> groups) {
this.groupReferences = groupReferences; this.groups = groups == null ? null : ImmutableList.copyOf(groups);
return this; return this;
} }
/**
* @see User#getGroups()
*/
public Builder group(Reference group) {
this.groups.add(checkNotNull(group, "group"));
return this;
}
public User build() { public User build() {
return new User(href, type, links, description, tasks, id, return new User(href, type, links, description, tasks, id,
name, fullName, emailAddress, telephone, isEnabled, isLocked, name, fullName, emailAddress, telephone, isEnabled, isLocked,
im, nameInSource, isAlertEnabled, alertEmailPrefix, alertEmail, im, nameInSource, isAlertEnabled, alertEmailPrefix, alertEmail,
isExternal, isDefaultCached, isGroupRole, storedVmQuota, deployedVmQuota, isExternal, isDefaultCached, isGroupRole, storedVmQuota, deployedVmQuota,
role, password, groupReferences); role, password, groups);
} }
/**
* @see EntityType#getName()
*/
@Override
public Builder name(String name) {
this.name = name;
return this;
}
/** /**
* @see EntityType#getId() * @see EntityType#getId()
@ -357,7 +376,7 @@ public class User
.deployedVmQuota(in.getDeployedVmQuota()) .deployedVmQuota(in.getDeployedVmQuota())
.role(in.getRole()) .role(in.getRole())
.password(in.getPassword()) .password(in.getPassword())
.groupReferences(in.getGroupReferences()); .groups(in.getGroups());
} }
} }
@ -395,14 +414,14 @@ public class User
protected Reference role; protected Reference role;
@XmlElement(name = "Password") @XmlElement(name = "Password")
protected String password; protected String password;
@XmlElement(name = "GroupReferences") @XmlElementWrapper(name = "GroupReferences")
protected Object /* GroupsList */ groupReferences; protected List<Reference> groups;
public User(URI href, String type, Set<Link> links, String description, Set<Task> tasks, String id, public User(URI href, String type, Set<Link> links, String description, Set<Task> tasks, String id,
String name, String fullName, String emailAddress, String telephone, Boolean enabled, Boolean locked, String name, String fullName, String emailAddress, String telephone, Boolean enabled, Boolean locked,
String im, String nameInSource, Boolean alertEnabled, String alertEmailPrefix, String alertEmail, String im, String nameInSource, Boolean alertEnabled, String alertEmailPrefix, String alertEmail,
Boolean external, Boolean defaultCached, Boolean groupRole, Integer storedVmQuota, Integer deployedVmQuota, Boolean external, Boolean defaultCached, Boolean groupRole, Integer storedVmQuota, Integer deployedVmQuota,
Reference role, String password, Object groupReferences) { Reference role, String password, List<Reference> groups) {
super(href, type, links, description, tasks, id, name); super(href, type, links, description, tasks, id, name);
this.fullName = fullName; this.fullName = fullName;
this.emailAddress = emailAddress; this.emailAddress = emailAddress;
@ -421,7 +440,7 @@ public class User
this.deployedVmQuota = deployedVmQuota; this.deployedVmQuota = deployedVmQuota;
this.role = role; this.role = role;
this.password = password; this.password = password;
this.groupReferences = groupReferences; this.groups = groups;
} }
private User() { private User() {
@ -605,8 +624,8 @@ public class User
* @return possible object is * @return possible object is
* {@link GroupsListType } * {@link GroupsListType }
*/ */
public Object /* GroupsList */ getGroupReferences() { public List<Reference> getGroups() {
return groupReferences; return groups == null ? Lists.<Reference>newArrayList() : groups;
} }
@Override @Override
@ -633,7 +652,7 @@ public class User
equal(deployedVmQuota, that.deployedVmQuota) && equal(deployedVmQuota, that.deployedVmQuota) &&
equal(role, that.role) && equal(role, that.role) &&
equal(password, that.password) && equal(password, that.password) &&
equal(groupReferences, that.groupReferences); equal(groups, that.groups);
} }
@Override @Override
@ -655,7 +674,7 @@ public class User
deployedVmQuota, deployedVmQuota,
role, role,
password, password,
groupReferences); groups);
} }
@Override @Override
@ -678,7 +697,6 @@ public class User
.add("deployedVmQuota", deployedVmQuota) .add("deployedVmQuota", deployedVmQuota)
.add("role", role) .add("role", role)
.add("password", password) .add("password", password)
.add("groupReferences", groupReferences).toString(); .add("groups", groups).toString();
} }
} }

View File

@ -0,0 +1,100 @@
/**
* 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.features;
import java.net.URI;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import org.jclouds.rest.annotations.BinderParam;
import org.jclouds.rest.annotations.EndpointParam;
import org.jclouds.rest.annotations.ExceptionParser;
import org.jclouds.rest.annotations.JAXBResponseParser;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.binders.BindToXMLPayload;
import org.jclouds.vcloud.director.v1_5.VCloudDirectorMediaType;
import org.jclouds.vcloud.director.v1_5.domain.User;
import org.jclouds.vcloud.director.v1_5.filters.AddVCloudAuthorizationToRequest;
import org.jclouds.vcloud.director.v1_5.functions.ThrowVCloudErrorOn4xx;
import com.google.common.util.concurrent.ListenableFuture;
/**
* @see GroupClient
* @author danikov
*/
@RequestFilters(AddVCloudAuthorizationToRequest.class)
public interface UserAsyncClient {
/**
* @see UserClient#createUser(URI, User)
*/
@POST
@Path("/users")
@Consumes(VCloudDirectorMediaType.USER)
@Produces(VCloudDirectorMediaType.USER)
@JAXBResponseParser
@ExceptionParser(ThrowVCloudErrorOn4xx.class)
ListenableFuture<User> createUser(@EndpointParam URI userRef,
@BinderParam(BindToXMLPayload.class) User user);
/**
* @see UserClient#getUser(URI)
*/
@GET
@Consumes
@JAXBResponseParser
@ExceptionParser(ThrowVCloudErrorOn4xx.class)
ListenableFuture<User> getUser(@EndpointParam URI userRef);
/**
* @see UserClient#updateUser(URI, User)
*/
@PUT
@Consumes(VCloudDirectorMediaType.USER)
@Produces(VCloudDirectorMediaType.USER)
@JAXBResponseParser
@ExceptionParser(ThrowVCloudErrorOn4xx.class)
ListenableFuture<User> updateUser(@EndpointParam URI userRef,
@BinderParam(BindToXMLPayload.class) User user);
/**
* @see UserClient#deleteUser(URI)
*/
@DELETE
@Consumes
@JAXBResponseParser
@ExceptionParser(ThrowVCloudErrorOn4xx.class)
ListenableFuture<Void> deleteUser(@EndpointParam URI userRef);
/**
* @see UserClient#unlockUser(URI)
*/
@POST
@Path("/action/unlock")
@Consumes
@JAXBResponseParser
@ExceptionParser(ThrowVCloudErrorOn4xx.class)
ListenableFuture<Void> unlockUser(@EndpointParam URI userRef);
}

View File

@ -0,0 +1,90 @@
/**
* 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.features;
import java.net.URI;
import java.util.concurrent.TimeUnit;
import org.jclouds.concurrent.Timeout;
import org.jclouds.vcloud.director.v1_5.domain.Group;
import org.jclouds.vcloud.director.v1_5.domain.User;
/**
* Provides synchronous access to {@link Group} objects.
*
* @see GroupAsyncClient
* @author danikov
*/
@Timeout(duration = 180, timeUnit = TimeUnit.SECONDS)
public interface UserClient {
/**
* Creates or imports a user in an organization. The user could be enabled or disabled.
*
* <pre>
* POST /admin/org/{id}/users
* </pre>
*
* @param orgRef the reference for the org
* @return the created user
*/
User createUser(URI orgRef, User user);
/**
* Retrieves a user. This entity could be enabled or disabled.
*
* <pre>
* GET /admin/user/{id}
* </pre>
*
* @param userRef the reference for the user
* @return a user
*/
User getUser(URI userRef);
/**
* Modifies a user. The user object could be enabled or disabled.
* Note: the lock status cannot be changed using this call: use unlockUser.
*
* <pre>
* PUT /admin/user/{id}
* </pre>
*
* @param userRef the reference for the user
* @return the modified user
*/
User updateUser(URI userRef, User user);
/**
* Deletes a user. Enabled and disabled users could be deleted.
*
* <pre>
* DELETE /admin/catalog/{id}
* </pre>
*/
void deleteUser(URI userRef);
/**
* Unlocks a user.
*
* <pre>
* POST /admin/user/{id}/action/unlock
* </pre>
*/
void unlockUser(URI userRef);
}

View File

@ -748,4 +748,52 @@ public class Checks {
// parent type // parent type
checkResourceType(settings); checkResourceType(settings);
} }
public static void checkUser(User user) {
// Check optional fields
// NOTE fullName cannot be checked
// NOTE isEnabled cannot be checked
// NOTE isLocked cannot be checked
// NOTE im cannot be checked
// NOTE nameInSource cannot be checked
// NOTE isAlertEnabled cannot be checked
// NOTE alterEmailPrefix cannot be checked
// NOTE isExternal cannot be checked
// NOTE isDefaultCached cannot be checked
// NOTE isGroupRole cannot be checked
// NOTE password cannot be checked
if (user.getEmailAddress() != null) {
checkEmailAddress(user.getEmailAddress());
}
if (user.getTelephone() != null) {
checkTelephone(user.getTelephone());
}
if (user.getAlertEmail() != null) {
checkEmailAddress(user.getAlertEmail());
}
if (user.getStoredVmQuota() != null) {
assertTrue(user.getStoredVmQuota() >= 0, String.format(OBJ_FIELD_GTE_0,
"User", "storedVmQuota", user.getStoredVmQuota()));
}
if (user.getDeployedVmQuota() != null) {
assertTrue(user.getDeployedVmQuota() >= 0, String.format(OBJ_FIELD_GTE_0,
"User", "deployedVmQuota", user.getDeployedVmQuota()));
}
if (user.getRole() != null) {
checkReferenceType(user.getRole());
}
if (user.getGroups() != null) {
for (Reference group : user.getGroups()) {
checkReferenceType(group);
}
}
// parent type
checkEntityType(user);
}
public static void checkTelephone(String number) {
// TODO: regex validate telephone
}
} }

View File

@ -0,0 +1,189 @@
/*
* 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.features;
import static org.testng.Assert.assertEquals;
import java.net.URI;
import java.util.Collections;
import org.jclouds.vcloud.director.v1_5.VCloudDirectorClient;
import org.jclouds.vcloud.director.v1_5.VCloudDirectorMediaType;
import org.jclouds.vcloud.director.v1_5.domain.Link;
import org.jclouds.vcloud.director.v1_5.domain.Reference;
import org.jclouds.vcloud.director.v1_5.domain.User;
import org.jclouds.vcloud.director.v1_5.internal.BaseVCloudDirectorRestClientExpectTest;
import org.testng.annotations.Test;
/**
* Test the {@link GroupClient} by observing its side effects.
*
* @author danikov
*/
@Test(groups = { "unit", "admin", "adminUser"}, singleThreaded = true, testName = "UserClientExpectTest")
public class UserClientExpectTest extends BaseVCloudDirectorRestClientExpectTest {
private Reference orgRef = Reference.builder()
.href(URI.create(endpoint + "/admin/org/6f312e42-cd2b-488d-a2bb-97519cd57ed0"))
.build();
private Reference userRef = Reference.builder()
.href(URI.create(endpoint + "/admin/user/b37223f3-8792-477a-820f-334998f61cd6"))
.build();
@Test
public void testCreateUser() {
VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse,
new VcloudHttpRequestPrimer()
.apiCommand("POST", "/admin/org/6f312e42-cd2b-488d-a2bb-97519cd57ed0/catalogs")
.xmlFilePayload("/user/createUserSource.xml", VCloudDirectorMediaType.USER)
.acceptMedia(VCloudDirectorMediaType.USER)
.httpRequestBuilder().build(),
new VcloudHttpResponsePrimer()
.xmlFilePayload("/user/createUser.xml", VCloudDirectorMediaType.USER)
.httpResponseBuilder().build());
User source = createUserSource();
User expected = createUser();
assertEquals(client.getUserClient().createUser(orgRef.getHref(), source), expected);
}
public static final User createUserSource() {
return User.builder()
.name("test")
.fullName("testFullName")
.emailAddress("test@test.com")
.telephone("555-1234")
.isEnabled(false)
.im("testIM")
.isAlertEnabled(false)
.alertEmailPrefix("testPrefix")
.alertEmail("testAlert@test.com")
.isExternal(false)
.isGroupRole(false)
.role(Reference.builder()
.type("application/vnd.vmware.admin.role+xml")
.name("vApp User")
.href(URI.create("https://vcloudbeta.bluelock.com/api/admin/role/ff1e0c91-1288-3664-82b7-a6fa303af4d1"))
.build())
.password("password")
.groups(Collections.<Reference>emptyList())
.build();
}
public static final User createUser() {
return createUserSource().toBuilder()
.id("urn:vcloud:user:b37223f3-8792-477a-820f-334998f61cd6")
.type("application/vnd.vmware.admin.user+xml")
.href(URI.create("https://vcloudbeta.bluelock.com/api/admin/user/b37223f3-8792-477a-820f-334998f61cd6"))
.link(Link.builder()
.rel("edit")
.type("application/vnd.vmware.admin.user+xml")
.href(URI.create("https://vcloudbeta.bluelock.com/api/admin/user/b37223f3-8792-477a-820f-334998f61cd6"))
.build())
.link(Link.builder()
.rel("remove")
.href(URI.create("https://vcloudbeta.bluelock.com/api/admin/user/b37223f3-8792-477a-820f-334998f61cd6"))
.build())
.isLocked(false)
.isDefaultCached(false)
.storedVmQuota(0)
.deployedVmQuota(0)
.password(null)
.build();
}
@Test
public void testGetUser() {
VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse,
new VcloudHttpRequestPrimer()
.apiCommand("GET", "/admin/user/b37223f3-8792-477a-820f-334998f61cd6")
.acceptAnyMedia()
.httpRequestBuilder().build(),
new VcloudHttpResponsePrimer()
.xmlFilePayload("/user/user.xml", VCloudDirectorMediaType.USER)
.httpResponseBuilder().build());
User expected = user();
assertEquals(client.getUserClient().getUser(userRef.getHref()), expected);
}
public static final User user() {
return createUser().toBuilder()
.nameInSource("test")
.build();
}
@Test
public void testUpdateUser() {
VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse,
new VcloudHttpRequestPrimer()
.apiCommand("PUT", "/admin/user/b37223f3-8792-477a-820f-334998f61cd6")
.xmlFilePayload("/user/updateUserSource.xml", VCloudDirectorMediaType.USER)
.acceptMedia(VCloudDirectorMediaType.USER)
.httpRequestBuilder().build(),
new VcloudHttpResponsePrimer()
.xmlFilePayload("/user/updateUser.xml", VCloudDirectorMediaType.USER)
.httpResponseBuilder().build());
User source = updateUserSource();
User expected = updateUser();
assertEquals(client.getUserClient().updateUser(userRef.getHref(), source), expected);
}
public static final User updateUserSource() {
return user().toBuilder()
.fullName("new"+user().getFullName())
.emailAddress("new"+user().getEmailAddress())
.telephone("1-"+user().getTelephone())
.isEnabled(true)
.im("new"+user().getIM())
.isAlertEnabled(true)
.alertEmailPrefix("new"+user().getAlertEmailPrefix())
.alertEmail("new"+user().getAlertEmail())
.storedVmQuota(1)
.deployedVmQuota(1)
.password("newPassword")
.build();
}
public static final User updateUser() {
return updateUserSource().toBuilder()
.password(null)
.build();
}
// POST /admin/user/{id}/action/unlock
@Test
public void testDeleteUser() {
VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse,
new VcloudHttpRequestPrimer()
.apiCommand("DELETE", "/admin/user/b37223f3-8792-477a-820f-334998f61cd6")
.acceptAnyMedia()
.httpRequestBuilder().build(),
new VcloudHttpResponsePrimer()
.httpResponseBuilder().statusCode(204).build());
client.getUserClient().deleteUser(userRef.getHref());
}
}

View File

@ -0,0 +1,204 @@
/*
* 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.features;
import static com.google.common.base.Objects.equal;
import static org.jclouds.vcloud.director.v1_5.VCloudDirectorLiveTestConstants.OBJ_DEL;
import static org.jclouds.vcloud.director.v1_5.VCloudDirectorLiveTestConstants.OBJ_FIELD_UPDATABLE;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNull;
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.fail;
import java.net.URI;
import org.jclouds.vcloud.director.v1_5.VCloudDirectorException;
import org.jclouds.vcloud.director.v1_5.domain.Checks;
import org.jclouds.vcloud.director.v1_5.domain.Error;
import org.jclouds.vcloud.director.v1_5.domain.Owner;
import org.jclouds.vcloud.director.v1_5.domain.Reference;
import org.jclouds.vcloud.director.v1_5.domain.ReferenceType;
import org.jclouds.vcloud.director.v1_5.domain.User;
import org.jclouds.vcloud.director.v1_5.internal.BaseVCloudDirectorClientLiveTest;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import com.google.common.collect.Iterables;
/**
* Tests live behavior of {@link AdminGroupClient}.
*
* @author danikov
*/
@Test(groups = { "live", "admin", "adminUser" }, singleThreaded = true, testName = "UserClientLiveTest")
public class UserClientLiveTest extends BaseVCloudDirectorClientLiveTest {
public static final String USER = "admin user";
/*
* Convenience references to API clients.
*/
UserClient userClient;
/*
* Shared state between dependant tests.
*/
private ReferenceType<?> orgRef;
private User user;
@Override
@BeforeClass(inheritGroups = true)
public void setupRequiredClients() {
userClient = context.getApi().getUserClient();
orgRef = Iterables.getFirst(context.getApi().getOrgClient().getOrgList().getOrgs(), null).toAdminReference(endpoint);
}
@Test(testName = "POST /admin/org/{id}/users")
public void testCreateUser() {
User newUser = User.builder()
.name("test")
.fullName("testFullName")
.emailAddress("test@test.com")
.telephone("555-1234")
.isEnabled(false)
.im("testIM")
.isAlertEnabled(false)
.alertEmailPrefix("testPrefix")
.alertEmail("testAlert@test.com")
.isExternal(false)
.isGroupRole(false)
.role(Reference.builder() // FIXME: auto-fetch a role? or inject
.name("vApp User")
.href(URI.create("https://vcloudbeta.bluelock.com/api/admin/role/ff1e0c91-1288-3664-82b7-a6fa303af4d1"))
.build())
.password("password")
// .group()
.build();
user = userClient.createUser(orgRef.getHref(), newUser);
Checks.checkUser(user);
}
@Test(testName = "GET /admin/user/{id}",
dependsOnMethods = { "testCreateUser" })
public void testGetUser() {
user = userClient.getUser(user.getHref());
Checks.checkUser(user);
}
@Test(testName = "PUT /admin/user/{id}",
dependsOnMethods = { "testGetUser" })
public void testUpdateUser() {
User oldUser = user.toBuilder().build();
User newUser = user.toBuilder()
// .name("new"+oldUser.getName())
.fullName("new"+oldUser.getFullName())
.emailAddress("new"+oldUser.getEmailAddress())
.telephone("1-"+oldUser.getTelephone())
.isEnabled(true)
.im("new"+oldUser.getIM())
.isAlertEnabled(true)
.alertEmailPrefix("new"+oldUser.getAlertEmailPrefix())
.alertEmail("new"+oldUser.getAlertEmail())
// .role(Reference.builder() // FIXME: auto-fetch a role? or inject
// .name("vApp Author")
// .href(URI.create("https://vcloudbeta.bluelock.com/api/admin/role/1bf4457f-a253-3cf1-b163-f319f1a31802"))
// .build())
.storedVmQuota(1)
.deployedVmQuota(1)
.password("newPassword")
.build();
try {
userClient.updateUser(user.getHref(), newUser);
user = userClient.getUser(user.getHref());
Checks.checkUser(user);
// assertTrue(equal(user.getName(), newUser.getName()),
// String.format(OBJ_FIELD_UPDATABLE, USER, "name"));
assertTrue(equal(user.getFullName(), newUser.getFullName()),
String.format(OBJ_FIELD_UPDATABLE, USER, "fullName"));
assertTrue(equal(user.getEmailAddress(), newUser.getEmailAddress()),
String.format(OBJ_FIELD_UPDATABLE, USER, "emailAddress"));
assertTrue(equal(user.getTelephone(), newUser.getTelephone()),
String.format(OBJ_FIELD_UPDATABLE, USER, "telephone"));
assertTrue(equal(user.isEnabled(), newUser.isEnabled()),
String.format(OBJ_FIELD_UPDATABLE, USER, "isEnabled"));
assertTrue(equal(user.getIM(), newUser.getIM()),
String.format(OBJ_FIELD_UPDATABLE, USER, "im"));
assertTrue(equal(user.isAlertEnabled(), newUser.isAlertEnabled()),
String.format(OBJ_FIELD_UPDATABLE, USER, "isAlertEnabled"));
assertTrue(equal(user.getAlertEmailPrefix(), newUser.getAlertEmailPrefix()),
String.format(OBJ_FIELD_UPDATABLE, USER, "alertEmailPrefix"));
assertTrue(equal(user.getAlertEmail(), newUser.getAlertEmail()),
String.format(OBJ_FIELD_UPDATABLE, USER, "alertEmail"));
// assertTrue(equal(user.getRole(), newUser.getRole()),
// String.format(OBJ_FIELD_UPDATABLE, USER, "role"));
assertTrue(equal(user.getStoredVmQuota(), newUser.getStoredVmQuota()),
String.format(OBJ_FIELD_UPDATABLE, USER, "storedVmQuota"));
assertTrue(equal(user.getDeployedVmQuota(), newUser.getDeployedVmQuota()),
String.format(OBJ_FIELD_UPDATABLE, USER, "deployedVmQuota"));
// FIXME: assert password is changed with session client?
} finally {
userClient.updateUser(user.getHref(), oldUser);
user = userClient.getUser(user.getHref());
}
}
//
@Test(testName = "POST /admin/user/{id}/action/unlock",
dependsOnMethods = { "testUpdateUser" } )
public void testUnlockUser() {
//TODO: check previous tests a) enabled lockout, b) set password
//TODO: attempt too many times with the wrong password
//TODO: verify access is denied
//TODO: unlock user
//TODO: verify access is renewed
}
@Test(testName = "DELETE /admin/user/{id}",
dependsOnMethods = { "testUnlockUser" } )
public void testDeleteUser() {
userClient.deleteUser(user.getHref());
Error expected = Error.builder()
.message("No access to entity \"(com.vmware.vcloud.entity.user:"+
user.getId().substring("urn:vcloud:user:".length())+")\".")
.majorErrorCode(403)
.minorErrorCode("ACCESS_TO_RESOURCE_IS_FORBIDDEN")
.build();
try {
user = userClient.getUser(user.getHref());
fail("Should give HTTP 403 error");
} catch (VCloudDirectorException vde) {
assertEquals(vde.getError(), expected);
user = null;
} catch (Exception e) {
fail("Should have thrown a VCloudDirectorException");
}
if (user != null) { // guard against NPE on the .toStrings
assertNull(user, String.format(OBJ_DEL, USER, user.toString()));
}
}
}

View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<User xmlns="http://www.vmware.com/vcloud/v1.5" name="test" id="urn:vcloud:user:b37223f3-8792-477a-820f-334998f61cd6" type="application/vnd.vmware.admin.user+xml" href="https://vcloudbeta.bluelock.com/api/admin/user/b37223f3-8792-477a-820f-334998f61cd6" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.vmware.com/vcloud/v1.5 http://vcloudbeta.bluelock.com/api/v1.5/schema/master.xsd">
<Link rel="edit" type="application/vnd.vmware.admin.user+xml" href="https://vcloudbeta.bluelock.com/api/admin/user/b37223f3-8792-477a-820f-334998f61cd6"/>
<Link rel="remove" href="https://vcloudbeta.bluelock.com/api/admin/user/b37223f3-8792-477a-820f-334998f61cd6"/>
<FullName>testFullName</FullName>
<EmailAddress>test@test.com</EmailAddress>
<Telephone>555-1234</Telephone>
<IsEnabled>false</IsEnabled>
<IsLocked>false</IsLocked>
<IM>testIM</IM>
<IsAlertEnabled>false</IsAlertEnabled>
<AlertEmailPrefix>testPrefix</AlertEmailPrefix>
<AlertEmail>testAlert@test.com</AlertEmail>
<IsExternal>false</IsExternal>
<IsDefaultCached>false</IsDefaultCached>
<IsGroupRole>false</IsGroupRole>
<StoredVmQuota>0</StoredVmQuota>
<DeployedVmQuota>0</DeployedVmQuota>
<Role type="application/vnd.vmware.admin.role+xml" name="vApp User" href="https://vcloudbeta.bluelock.com/api/admin/role/ff1e0c91-1288-3664-82b7-a6fa303af4d1"/>
<GroupReferences/>
</User>

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<User name="test" xmlns="http://www.vmware.com/vcloud/v1.5">
<FullName>testFullName</FullName>
<EmailAddress>test@test.com</EmailAddress>
<Telephone>555-1234</Telephone>
<IsEnabled>false</IsEnabled>
<IM>testIM</IM>
<IsAlertEnabled>false</IsAlertEnabled>
<AlertEmailPrefix>testPrefix</AlertEmailPrefix>
<AlertEmail>testAlert@test.com</AlertEmail>
<IsExternal>false</IsExternal>
<IsGroupRole>false</IsGroupRole>
<Role type="application/vnd.vmware.admin.role+xml" name="vApp User" href="https://vcloudbeta.bluelock.com/api/admin/role/ff1e0c91-1288-3664-82b7-a6fa303af4d1"/>
<Password>password</Password>
<GroupReferences/>
</User>

View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<User xmlns="http://www.vmware.com/vcloud/v1.5" name="test" id="urn:vcloud:user:b37223f3-8792-477a-820f-334998f61cd6" type="application/vnd.vmware.admin.user+xml" href="https://vcloudbeta.bluelock.com/api/admin/user/5fc76423-0380-4a6d-9f52-dffb4ffaa46a" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.vmware.com/vcloud/v1.5 http://vcloudbeta.bluelock.com/api/v1.5/schema/master.xsd">
<Link rel="edit" type="application/vnd.vmware.admin.user+xml" href="https://vcloudbeta.bluelock.com/api/admin/user/b37223f3-8792-477a-820f-334998f61cd6"/>
<FullName>newtestFullName</FullName>
<EmailAddress>newtest@test.com</EmailAddress>
<Telephone>1-555-1234</Telephone>
<IsEnabled>true</IsEnabled>
<IsLocked>false</IsLocked>
<IM>newtestIM</IM>
<NameInSource>test</NameInSource>
<IsAlertEnabled>true</IsAlertEnabled>
<AlertEmailPrefix>newtestPrefix</AlertEmailPrefix>
<AlertEmail>newtestAlert@test.com</AlertEmail>
<IsExternal>false</IsExternal>
<IsDefaultCached>false</IsDefaultCached>
<IsGroupRole>false</IsGroupRole>
<StoredVmQuota>1</StoredVmQuota>
<DeployedVmQuota>1</DeployedVmQuota>
<Role type="application/vnd.vmware.admin.role+xml" name="vApp User" href="https://vcloudbeta.bluelock.com/api/admin/role/ff1e0c91-1288-3664-82b7-a6fa303af4d1"/>
<GroupReferences/>
</User>

View File

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<User name="test" id="urn:vcloud:user:b37223f3-8792-477a-820f-334998f61cd6" type="application/vnd.vmware.admin.user+xml" href="https://vcloudbeta.bluelock.com/api/admin/user/b37223f3-8792-477a-820f-334998f61cd6" xmlns="http://www.vmware.com/vcloud/v1.5">
<Link rel="edit" type="application/vnd.vmware.admin.user+xml" href="https://vcloudbeta.bluelock.com/api/admin/user/b37223f3-8792-477a-820f-334998f61cd6"/>
<Link rel="remove" href="https://vcloudbeta.bluelock.com/api/admin/user/b37223f3-8792-477a-820f-334998f61cd6"/>
<FullName>newtestFullName</FullName>
<EmailAddress>newtest@test.com</EmailAddress>
<Telephone>1-555-1234</Telephone>
<IsEnabled>true</IsEnabled>
<IsLocked>false</IsLocked>
<IM>newtestIM</IM>
<NameInSource>test</NameInSource>
<IsAlertEnabled>true</IsAlertEnabled>
<AlertEmailPrefix>newtestPrefix</AlertEmailPrefix>
<AlertEmail>newtestAlert@test.com</AlertEmail>
<IsExternal>false</IsExternal>
<IsDefaultCached>false</IsDefaultCached>
<IsGroupRole>false</IsGroupRole>
<StoredVmQuota>1</StoredVmQuota>
<DeployedVmQuota>1</DeployedVmQuota>
<Role type="application/vnd.vmware.admin.role+xml" name="vApp User" href="https://vcloudbeta.bluelock.com/api/admin/role/ff1e0c91-1288-3664-82b7-a6fa303af4d1"/>
<Password>newPassword</Password>
<GroupReferences/>
</User>

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<User xmlns="http://www.vmware.com/vcloud/v1.5" name="test" id="urn:vcloud:user:b37223f3-8792-477a-820f-334998f61cd6" type="application/vnd.vmware.admin.user+xml" href="https://vcloudbeta.bluelock.com/api/admin/user/b37223f3-8792-477a-820f-334998f61cd6" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.vmware.com/vcloud/v1.5 http://vcloudbeta.bluelock.com/api/v1.5/schema/master.xsd">
<Link rel="edit" type="application/vnd.vmware.admin.user+xml" href="https://vcloudbeta.bluelock.com/api/admin/user/b37223f3-8792-477a-820f-334998f61cd6"/>
<Link rel="remove" href="https://vcloudbeta.bluelock.com/api/admin/user/b37223f3-8792-477a-820f-334998f61cd6"/>
<FullName>testFullName</FullName>
<EmailAddress>test@test.com</EmailAddress>
<Telephone>555-1234</Telephone>
<IsEnabled>false</IsEnabled>
<IsLocked>false</IsLocked>
<IM>testIM</IM>
<NameInSource>test</NameInSource>
<IsAlertEnabled>false</IsAlertEnabled>
<AlertEmailPrefix>testPrefix</AlertEmailPrefix>
<AlertEmail>testAlert@test.com</AlertEmail>
<IsExternal>false</IsExternal>
<IsDefaultCached>false</IsDefaultCached>
<IsGroupRole>false</IsGroupRole>
<StoredVmQuota>0</StoredVmQuota>
<DeployedVmQuota>0</DeployedVmQuota>
<Role type="application/vnd.vmware.admin.role+xml" name="vApp User" href="https://vcloudbeta.bluelock.com/api/admin/role/ff1e0c91-1288-3664-82b7-a6fa303af4d1"/>
<GroupReferences/>
</User>

View File

@ -27,8 +27,6 @@ import org.jclouds.byon.Node;
import org.jclouds.byon.config.CacheNodeStoreModule; import org.jclouds.byon.config.CacheNodeStoreModule;
import org.jclouds.compute.StandaloneComputeServiceContextBuilder; import org.jclouds.compute.StandaloneComputeServiceContextBuilder;
import org.jclouds.compute.domain.OsFamily; import org.jclouds.compute.domain.OsFamily;
import org.jclouds.concurrent.MoreExecutors;
import org.jclouds.concurrent.config.ExecutorServiceModule;
import org.jclouds.virtualbox.config.VirtualBoxComputeServiceContextModule; import org.jclouds.virtualbox.config.VirtualBoxComputeServiceContextModule;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;

View File

@ -150,7 +150,7 @@ public class VirtualBoxComputeServiceAdapter implements ComputeServiceAdapter<IM
} }
@Override @Override
public void destroyNode(String vmName) { public synchronized void destroyNode(String vmName) {
IMachine machine = manager.get().getVBox().findMachine(vmName); IMachine machine = manager.get().getVBox().findMachine(vmName);
powerDownMachine(machine); powerDownMachine(machine);
new UnregisterMachineIfExistsAndForceDeleteItsMedia().apply(machine); new UnregisterMachineIfExistsAndForceDeleteItsMedia().apply(machine);
@ -198,10 +198,10 @@ public class VirtualBoxComputeServiceAdapter implements ComputeServiceAdapter<IM
private void powerDownMachine(IMachine machine) { private void powerDownMachine(IMachine machine) {
try { try {
if (machine.getState() == MachineState.PoweredOff){ if (machine.getState() == MachineState.PoweredOff){
logger.debug("vm was already powered down: ", machine.getName()); logger.debug("vm was already powered down: ", machine.getId());
return; return;
} }
logger.debug("powering down vm: ", machine.getName()); logger.debug("powering down vm: ", machine.getId());
ISession machineSession = manager.get().openMachineSession(machine); ISession machineSession = manager.get().openMachineSession(machine);
IProgress progress = machineSession.getConsole().powerDown(); IProgress progress = machineSession.getConsole().powerDown();
progress.waitForCompletion(-1); progress.waitForCompletion(-1);

View File

@ -24,8 +24,8 @@ import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_PRECO
import java.io.File; import java.io.File;
import java.io.InputStream; import java.io.InputStream;
import java.net.URI; import java.net.URI;
import java.util.Collections;
import java.util.Map; import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import javax.inject.Named; import javax.inject.Named;
@ -33,7 +33,6 @@ import javax.inject.Singleton;
import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.Server;
import org.jclouds.byon.Node; import org.jclouds.byon.Node;
import org.jclouds.byon.config.CacheNodeStoreModule;
import org.jclouds.byon.functions.NodeToNodeMetadata; import org.jclouds.byon.functions.NodeToNodeMetadata;
import org.jclouds.byon.suppliers.SupplyFromProviderURIOrNodesProperty; import org.jclouds.byon.suppliers.SupplyFromProviderURIOrNodesProperty;
import org.jclouds.compute.ComputeServiceAdapter; import org.jclouds.compute.ComputeServiceAdapter;
@ -49,7 +48,6 @@ import org.jclouds.compute.domain.NodeState;
import org.jclouds.compute.domain.OsFamily; import org.jclouds.compute.domain.OsFamily;
import org.jclouds.compute.domain.TemplateBuilder; import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.compute.reference.ComputeServiceConstants.Timeouts; import org.jclouds.compute.reference.ComputeServiceConstants.Timeouts;
import org.jclouds.concurrent.SingleThreaded;
import org.jclouds.domain.Location; import org.jclouds.domain.Location;
import org.jclouds.functions.IdentityFunction; import org.jclouds.functions.IdentityFunction;
import org.jclouds.logging.slf4j.config.SLF4JLoggingModule; import org.jclouds.logging.slf4j.config.SLF4JLoggingModule;
@ -80,6 +78,7 @@ import org.jclouds.virtualbox.functions.admin.ImagesToYamlImagesFromYamlDescript
import org.jclouds.virtualbox.functions.admin.StartJettyIfNotAlreadyRunning; import org.jclouds.virtualbox.functions.admin.StartJettyIfNotAlreadyRunning;
import org.jclouds.virtualbox.functions.admin.StartVBoxIfNotAlreadyRunning; import org.jclouds.virtualbox.functions.admin.StartVBoxIfNotAlreadyRunning;
import org.jclouds.virtualbox.predicates.SshResponds; import org.jclouds.virtualbox.predicates.SshResponds;
import org.testng.internal.annotations.Sets;
import org.virtualbox_4_1.IMachine; import org.virtualbox_4_1.IMachine;
import org.virtualbox_4_1.LockType; import org.virtualbox_4_1.LockType;
import org.virtualbox_4_1.MachineState; import org.virtualbox_4_1.MachineState;
@ -105,7 +104,6 @@ import com.google.inject.TypeLiteral;
* @author Mattias Holmqvist, Andrea Turli * @author Mattias Holmqvist, Andrea Turli
*/ */
@SuppressWarnings({ "unchecked", "rawtypes" }) @SuppressWarnings({ "unchecked", "rawtypes" })
@SingleThreaded
public class VirtualBoxComputeServiceContextModule extends public class VirtualBoxComputeServiceContextModule extends
ComputeServiceAdapterContextModule<Supplier, Supplier, IMachine, IMachine, Image, Location> { ComputeServiceAdapterContextModule<Supplier, Supplier, IMachine, IMachine, Image, Location> {
@ -221,7 +219,13 @@ public class VirtualBoxComputeServiceContextModule extends
@Override @Override
protected Supplier provideHardware(ComputeServiceAdapter<IMachine, IMachine, Image, Location> adapter, protected Supplier provideHardware(ComputeServiceAdapter<IMachine, IMachine, Image, Location> adapter,
Function<IMachine, Hardware> transformer) { Function<IMachine, Hardware> transformer) {
return Suppliers.ofInstance(Collections.singleton(new HardwareBuilder().id("").build())); // since no vms might be available we need to list images
Iterable<Image> images = adapter.listImages();
Set<Hardware> hardware = Sets.newHashSet();
for (Image image : images) {
hardware.add(new HardwareBuilder().ids(image.getId()).hypervisor("VirtualBox").name(image.getName()).build());
}
return Suppliers.ofInstance(hardware);
} }
@Override @Override

View File

@ -24,6 +24,7 @@ import java.util.List;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.inject.Named; import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.compute.reference.ComputeServiceConstants; import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
@ -47,7 +48,7 @@ import com.google.inject.Inject;
/** /**
* CloneAndRegisterMachineFromIMachineIfNotAlreadyExists will take care of the followings: - cloning * CloneAndRegisterMachineFromIMachineIfNotAlreadyExists will take care of the followings: - cloning
* the master - register the clone machine - * the master - register the clone machine.
* *
* @author Andrea Turli * @author Andrea Turli
*/ */

View File

@ -25,6 +25,7 @@ import org.jclouds.compute.domain.Hardware;
import org.jclouds.compute.domain.HardwareBuilder; import org.jclouds.compute.domain.HardwareBuilder;
import org.jclouds.compute.predicates.ImagePredicates; import org.jclouds.compute.predicates.ImagePredicates;
import org.jclouds.javax.annotation.Nullable; import org.jclouds.javax.annotation.Nullable;
import org.jclouds.virtualbox.config.VirtualBoxConstants;
import org.virtualbox_4_1.IGuestOSType; import org.virtualbox_4_1.IGuestOSType;
import org.virtualbox_4_1.IMachine; import org.virtualbox_4_1.IMachine;
import org.virtualbox_4_1.VirtualBoxManager; import org.virtualbox_4_1.VirtualBoxManager;
@ -44,14 +45,14 @@ public class IMachineToHardware implements Function<IMachine, Hardware> {
@Override @Override
public Hardware apply(@Nullable IMachine vm) { public Hardware apply(@Nullable IMachine vm) {
String osTypeId = vm.getOSTypeId(); String osTypeId = vm.getOSTypeId();
String vmNameWithoutPrefix = vm.getName().replace(VirtualBoxConstants.VIRTUALBOX_IMAGE_PREFIX, "");
IGuestOSType guestOSType = virtualBoxManager.get().getVBox().getGuestOSType(osTypeId); IGuestOSType guestOSType = virtualBoxManager.get().getVBox().getGuestOSType(osTypeId);
Boolean is64Bit = guestOSType.getIs64Bit(); Boolean is64Bit = guestOSType.getIs64Bit();
HardwareBuilder hardwareBuilder = new HardwareBuilder(); HardwareBuilder hardwareBuilder = new HardwareBuilder();
hardwareBuilder.ids(vm.getId()); hardwareBuilder.ids(vmNameWithoutPrefix);
hardwareBuilder.supportsImage(ImagePredicates.idEquals(vm.getId()));
hardwareBuilder.is64Bit(is64Bit); hardwareBuilder.is64Bit(is64Bit);
hardwareBuilder.supportsImage(ImagePredicates.idEquals(vm.getId())); hardwareBuilder.supportsImage(ImagePredicates.idEquals(vmNameWithoutPrefix));
hardwareBuilder.hypervisor("VirtualBox"); hardwareBuilder.hypervisor("VirtualBox");
return hardwareBuilder.build(); return hardwareBuilder.build();
} }

View File

@ -84,8 +84,13 @@ public class NodeCreator implements Function<NodeSpec, NodeAndInitialCredentials
this.imachineToNodeMetadata = imachineToNodeMetadata; this.imachineToNodeMetadata = imachineToNodeMetadata;
} }
/**
* Creates a clone based on the {@link NodeSpec}. It is synchronized because it needs sole access
* to the master. Could be improved by locking on a master basis (would allow concurrent cloning
* as long as form different masters."
*/
@Override @Override
public NodeAndInitialCredentials<IMachine> apply(NodeSpec nodeSpec) { public synchronized NodeAndInitialCredentials<IMachine> apply(NodeSpec nodeSpec) {
checkNotNull(nodeSpec, "NodeSpec"); checkNotNull(nodeSpec, "NodeSpec");
@ -102,6 +107,7 @@ public class NodeCreator implements Function<NodeSpec, NodeAndInitialCredentials
session.getConsole().deleteSnapshot(master.getMachine().getCurrentSnapshot().getId()); session.getConsole().deleteSnapshot(master.getMachine().getCurrentSnapshot().getId());
session.unlockMachine(); session.unlockMachine();
} }
String masterNameWithoutPrefix = master.getSpec().getVmSpec().getVmName().replace(VIRTUALBOX_IMAGE_PREFIX, ""); String masterNameWithoutPrefix = master.getSpec().getVmSpec().getVmName().replace(VIRTUALBOX_IMAGE_PREFIX, "");
String cloneName = VIRTUALBOX_NODE_PREFIX + masterNameWithoutPrefix + "-" + nodeSpec.getTag() + "-" String cloneName = VIRTUALBOX_NODE_PREFIX + masterNameWithoutPrefix + "-" + nodeSpec.getTag() + "-"

View File

@ -70,7 +70,7 @@ public class StartVBoxIfNotAlreadyRunning implements Supplier<VirtualBoxManager>
@Provider Supplier<URI> providerSupplier, @Identity String identity, @Credential String credential) { @Provider Supplier<URI> providerSupplier, @Identity String identity, @Credential String credential) {
this.runScriptOnNodeFactory = checkNotNull(runScriptOnNodeFactory, "runScriptOnNodeFactory"); this.runScriptOnNodeFactory = checkNotNull(runScriptOnNodeFactory, "runScriptOnNodeFactory");
this.socketTester = checkNotNull(socketTester, "socketTester"); this.socketTester = checkNotNull(socketTester, "socketTester");
this.socketTester.seconds(1L); this.socketTester.seconds(3L);
this.host = checkNotNull(host, "host"); this.host = checkNotNull(host, "host");
this.providerSupplier = checkNotNull(providerSupplier, "endpoint to virtualbox websrvd is needed"); this.providerSupplier = checkNotNull(providerSupplier, "endpoint to virtualbox websrvd is needed");
this.identity = checkNotNull(identity, "identity"); this.identity = checkNotNull(identity, "identity");
@ -93,6 +93,10 @@ public class StartVBoxIfNotAlreadyRunning implements Supplier<VirtualBoxManager>
runScriptOnNodeFactory.create(host.get(), Statements.exec(vboxwebsrv), runScriptOnNodeFactory.create(host.get(), Statements.exec(vboxwebsrv),
runAsRoot(false).wrapInInitScript(false).blockOnComplete(false).nameTask("vboxwebsrv")).init().call(); runAsRoot(false).wrapInInitScript(false).blockOnComplete(false).nameTask("vboxwebsrv")).init().call();
if (!socketTester.apply(new IPSocket(provider.getHost(), provider.getPort()))){
throw new RuntimeException("could not connect to virtualbox");
}
} }
manager = managerForNode.apply(host); manager = managerForNode.apply(host);
manager.connect(provider.toASCIIString(), identity, credential); manager.connect(provider.toASCIIString(), identity, credential);

View File

@ -26,35 +26,47 @@ import java.util.Set;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.inject.Named; import javax.inject.Named;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.ComputeServiceContextFactory;
import org.jclouds.compute.RunNodesException; import org.jclouds.compute.RunNodesException;
import org.jclouds.compute.domain.ExecResponse; import org.jclouds.compute.domain.ExecResponse;
import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.reference.ComputeServiceConstants; import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import org.jclouds.logging.slf4j.config.SLF4JLoggingModule;
import org.jclouds.ssh.SshClient; import org.jclouds.ssh.SshClient;
import org.jclouds.virtualbox.BaseVirtualBoxClientLiveTest; import org.jclouds.sshj.config.SshjSshClientModule;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableSet;
import com.google.inject.Module;
/** /**
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
@Test(groups = "live", singleThreaded = true, testName = "VirtualBoxExperimentLiveTest") @Test(groups = "live", singleThreaded = true, testName = "VirtualBoxExperimentLiveTest")
public class VirtualBoxExperimentLiveTest extends BaseVirtualBoxClientLiveTest { public class VirtualBoxExperimentLiveTest {
@Resource @Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER) @Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL; protected Logger logger = Logger.NULL;
ComputeServiceContext context;
@BeforeClass
public void setUp() {
context = new ComputeServiceContextFactory().createContext("virtualbox", "toor", "password",
ImmutableSet.<Module> of(new SLF4JLoggingModule(), new SshjSshClientModule()));
}
@Test @Test
public void testLaunchCluster() throws RunNodesException { public void testLaunchCluster() throws RunNodesException {
int numNodes = 4; int numNodes = 4;
final String clusterName = "test-launch-cluster"; final String clusterName = "test-launch-cluster";
Set<? extends NodeMetadata> nodes = context.getComputeService().createNodesInGroup(clusterName, Set<? extends NodeMetadata> nodes = context.getComputeService().createNodesInGroup(clusterName, numNodes);
numNodes);
assertEquals(numNodes, nodes.size(), "wrong number of nodes"); assertEquals(numNodes, nodes.size(), "wrong number of nodes");
for (NodeMetadata node : nodes) { for (NodeMetadata node : nodes) {
logger.debug("Created Node: %s", node); logger.debug("Created Node: %s", node);

View File

@ -46,10 +46,10 @@ public class IMachineToHardwareTest {
IGuestOSType guestOsType = createNiceMock(IGuestOSType.class); IGuestOSType guestOsType = createNiceMock(IGuestOSType.class);
String linuxDescription = "Ubuntu Linux 10.04"; String linuxDescription = "Ubuntu Linux 10.04";
String machineId = "hw-machineId"; String machineName = "hw-machineId";
expect(vm.getOSTypeId()).andReturn("os-type").anyTimes(); expect(vm.getOSTypeId()).andReturn("os-type").anyTimes();
expect(vm.getId()).andReturn(machineId).anyTimes(); expect(vm.getName()).andReturn(machineName).anyTimes();
expect(vm.getDescription()).andReturn(linuxDescription).anyTimes(); expect(vm.getDescription()).andReturn(linuxDescription).anyTimes();
@ -61,11 +61,11 @@ public class IMachineToHardwareTest {
Hardware hardware = new IMachineToHardware(Suppliers.ofInstance(vbm)).apply(vm); Hardware hardware = new IMachineToHardware(Suppliers.ofInstance(vbm)).apply(vm);
assertEquals(hardware.getId(), machineId); assertEquals(hardware.getId(), machineName);
assertEquals(hardware.getProviderId(), machineId); assertEquals(hardware.getProviderId(), machineName);
// for starters assume 1-to-1 relationship hardware to image (which // for starters assume 1-to-1 relationship hardware to image (which
// correlate to a single source IMachine) // correlate to a single source IMachine)
assertEquals(hardware.supportsImage().toString(), ImagePredicates.idEquals(machineId).toString()); assertEquals(hardware.supportsImage().toString(), ImagePredicates.idEquals(machineName).toString());
} }