Issue 695: Added Layout Client+domain object (needed for creating a virtual machine) and tests

This commit is contained in:
Jason King 2011-12-15 15:34:39 +00:00
parent bbb3342f30
commit 6dca8b62c9
16 changed files with 1677 additions and 9 deletions

View File

@ -33,6 +33,12 @@ import org.jclouds.tmrk.enterprisecloud.features.*;
*/
public interface TerremarkEnterpriseCloudAsyncClient {
/**
* Provides asynchronous access to Layout features.
*/
@Delegate
LayoutAsyncClient getLayoutClient();
/**
* Provides asynchronous access to Location features.
*/

View File

@ -37,6 +37,12 @@ import org.jclouds.tmrk.enterprisecloud.features.*;
@Timeout(duration = 180, timeUnit = TimeUnit.SECONDS)
public interface TerremarkEnterpriseCloudClient {
/**
* Provides synchronous access to Layout features.
*/
@Delegate
LayoutClient getLayoutClient();
/**
* Provides synchronous access to Location features.
*/

View File

@ -18,10 +18,7 @@
*/
package org.jclouds.tmrk.enterprisecloud.config;
import java.io.IOException;
import java.util.Map;
import com.google.inject.Provides;
import com.google.common.collect.ImmutableMap;
import org.jclouds.http.HttpErrorHandler;
import org.jclouds.http.HttpRetryHandler;
import org.jclouds.http.RequiresHttp;
@ -36,11 +33,7 @@ import org.jclouds.tmrk.enterprisecloud.TerremarkEnterpriseCloudClient;
import org.jclouds.tmrk.enterprisecloud.features.*;
import org.jclouds.tmrk.enterprisecloud.handlers.TerremarkEnterpriseCloudErrorHandler;
import com.google.common.collect.ImmutableMap;
import org.jclouds.util.Strings2;
import javax.inject.Named;
import javax.inject.Singleton;
import java.util.Map;
/**
* Configures the TerremarkEnterpriseCloud connection.
@ -53,6 +46,7 @@ public class TerremarkEnterpriseCloudRestClientModule extends
RestClientModule<TerremarkEnterpriseCloudClient, TerremarkEnterpriseCloudAsyncClient> {
public static final Map<Class<?>, Class<?>> DELEGATE_MAP = ImmutableMap.<Class<?>, Class<?>> builder()
.put(LayoutClient.class, LayoutAsyncClient.class)
.put(LocationClient.class, LocationAsyncClient.class)
.put(NetworkClient.class, NetworkAsyncClient.class)
.put(ResourceClient.class, ResourceAsyncClient.class)

View File

@ -0,0 +1,183 @@
/**
* 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.tmrk.enterprisecloud.domain.layout;
import com.google.common.collect.Sets;
import org.jclouds.tmrk.enterprisecloud.domain.Action;
import org.jclouds.tmrk.enterprisecloud.domain.Link;
import org.jclouds.tmrk.enterprisecloud.domain.internal.BaseResource;
import org.jclouds.tmrk.enterprisecloud.domain.internal.Resource;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import java.net.URI;
import java.util.Map;
import java.util.Set;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* DeviceLayout is more than a simple wrapper as it extends Resource.
* <xs:complexType name="DeviceLayoutType">
* @author Jason King
*
*/
@XmlRootElement(name = "DeviceLayout")
public class DeviceLayout extends Resource<DeviceLayout> {
@SuppressWarnings("unchecked")
public static Builder builder() {
return new Builder();
}
/**
* {@inheritDoc}
*/
@Override
public Builder toBuilder() {
return new Builder().fromTemplates(this);
}
public static class Builder extends Resource.Builder<DeviceLayout> {
private Set<LayoutRow> rows = Sets.newLinkedHashSet();
/**
* @see DeviceLayout#getRows
*/
public Builder rows(Set<LayoutRow> rows) {
this.rows =(checkNotNull(rows,"rows"));
return this;
}
@Override
public DeviceLayout build() {
return new DeviceLayout(href, type, name, links, actions, rows);
}
public Builder fromTemplates(DeviceLayout in) {
return fromResource(in).rows(in.getRows());
}
/**
* {@inheritDoc}
*/
@Override
public Builder fromBaseResource(BaseResource<DeviceLayout> in) {
return Builder.class.cast(super.fromBaseResource(in));
}
/**
* {@inheritDoc}
*/
@Override
public Builder fromResource(Resource<DeviceLayout> in) {
return Builder.class.cast(super.fromResource(in));
}
/**
* {@inheritDoc}
*/
@Override
public Builder type(String type) {
return Builder.class.cast(super.type(type));
}
/**
* {@inheritDoc}
*/
@Override
public Builder href(URI href) {
return Builder.class.cast(super.href(href));
}
/**
* {@inheritDoc}
*/
@Override
public Builder name(String name) {
return Builder.class.cast(super.name(name));
}
/**
* {@inheritDoc}
*/
@Override
public Builder links(Set<Link> links) {
return Builder.class.cast(super.links(links));
}
/**
* {@inheritDoc}
*/
@Override
public Builder actions(Set<Action> actions) {
return Builder.class.cast(super.actions(actions));
}
/**
* {@inheritDoc}
*/
@Override
public Builder fromAttributes(Map<String, String> attributes) {
return Builder.class.cast(super.fromAttributes(attributes));
}
}
@XmlElement(name = "Rows", required = false)
private Rows rows = Rows.builder().build();
private DeviceLayout(URI href, String type, String name, Set<Link> links, Set<Action> actions, Set<LayoutRow> rows) {
super(href, type, name, links, actions);
this.rows = Rows.builder().rows(checkNotNull(rows,"rows")).build();
}
private DeviceLayout() {
//For JAXB
}
public Set<LayoutRow> getRows() {
return rows.getRows();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (!super.equals(o)) return false;
DeviceLayout that = (DeviceLayout) o;
if (!rows.equals(that.rows)) return false;
return true;
}
@Override
public int hashCode() {
int result = super.hashCode();
result = 31 * result + rows.hashCode();
return result;
}
@Override
public String string() {
return super.string()+", rows="+rows;
}
}

View File

@ -0,0 +1,106 @@
/**
* 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.tmrk.enterprisecloud.domain.layout;
import com.google.common.collect.Sets;
import javax.xml.bind.annotation.XmlElement;
import java.util.Collections;
import java.util.Set;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Wraps individual LayoutGroup elements.
* <xs:complexType name="GroupsType">
* @author Jason King
*/
public class Groups {
@SuppressWarnings("unchecked")
public static Builder builder() {
return new Builder();
}
public Builder toBuilder() {
return new Builder().fromGroups(this);
}
public static class Builder {
private Set<LayoutGroup> groups = Sets.newLinkedHashSet();
/**
* @see Groups#getGroups
*/
public Builder groups(Set<LayoutGroup> groups) {
this.groups = Sets.newLinkedHashSet(checkNotNull(groups, "groups"));
return this;
}
public Builder addGroup(LayoutGroup group) {
groups.add(checkNotNull(group, "group"));
return this;
}
public Groups build() {
return new Groups(groups);
}
public Builder fromGroups(Groups in) {
return groups(in.getGroups());
}
}
private Groups() {
//For JAXB and builder use
}
private Groups(Set<LayoutGroup> entries) {
this.groups = Sets.newLinkedHashSet(entries);
}
@XmlElement(name = "Group", required=false)
private Set<LayoutGroup> groups = Sets.newLinkedHashSet();
public Set<LayoutGroup> getGroups() {
return Collections.unmodifiableSet(groups);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Groups tasks1 = (Groups) o;
if (!groups.equals(tasks1.groups)) return false;
return true;
}
@Override
public int hashCode() {
return groups.hashCode();
}
public String toString() {
return "["+ groups.toString()+"]";
}
}

View File

@ -0,0 +1,206 @@
/**
* 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.tmrk.enterprisecloud.domain.layout;
import com.google.common.collect.Sets;
import org.jclouds.tmrk.enterprisecloud.domain.Action;
import org.jclouds.tmrk.enterprisecloud.domain.Link;
import org.jclouds.tmrk.enterprisecloud.domain.internal.BaseResource;
import org.jclouds.tmrk.enterprisecloud.domain.internal.Resource;
import org.jclouds.tmrk.enterprisecloud.domain.vm.VirtualMachineReference;
import org.jclouds.tmrk.enterprisecloud.domain.vm.VirtualMachineReferences;
import javax.xml.bind.annotation.XmlElement;
import java.net.URI;
import java.util.Map;
import java.util.Set;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* LayoutGroup is more than a simple wrapper as it extends Resource.
* <xs:complexType name="LayoutGroupType">
* @author Jason King
*
*/
public class LayoutGroup extends Resource<LayoutGroup> {
@SuppressWarnings("unchecked")
public static Builder builder() {
return new Builder();
}
/**
* {@inheritDoc}
*/
@Override
public Builder toBuilder() {
return new Builder().fromLayoutGroup(this);
}
public static class Builder extends Resource.Builder<LayoutGroup> {
private int index;
private Set<VirtualMachineReference> virtualMachineReferences = Sets.newLinkedHashSet();
/**
* @see org.jclouds.tmrk.enterprisecloud.domain.layout.LayoutGroup#getIndex
*/
public Builder index(int index) {
this.index = index;
return this;
}
/**
* @see org.jclouds.tmrk.enterprisecloud.domain.layout.LayoutGroup#getVirtualMachineReferences()
*/
public Builder virtualMachineReferences(Set<VirtualMachineReference> virtualMachineReferences) {
this.virtualMachineReferences = Sets.newLinkedHashSet(checkNotNull(virtualMachineReferences, "virtualMachineReferences"));
return this;
}
@Override
public LayoutGroup build() {
return new LayoutGroup(href, type, name, links, actions, index,virtualMachineReferences);
}
public Builder fromLayoutGroup(LayoutGroup in) {
return fromResource(in).index(in.getIndex());
}
/**
* {@inheritDoc}
*/
@Override
public Builder fromBaseResource(BaseResource<LayoutGroup> in) {
return Builder.class.cast(super.fromBaseResource(in));
}
/**
* {@inheritDoc}
*/
@Override
public Builder fromResource(Resource<LayoutGroup> in) {
return Builder.class.cast(super.fromResource(in));
}
/**
* {@inheritDoc}
*/
@Override
public Builder type(String type) {
return Builder.class.cast(super.type(type));
}
/**
* {@inheritDoc}
*/
@Override
public Builder href(URI href) {
return Builder.class.cast(super.href(href));
}
/**
* {@inheritDoc}
*/
@Override
public Builder name(String name) {
return Builder.class.cast(super.name(name));
}
/**
* {@inheritDoc}
*/
@Override
public Builder links(Set<Link> links) {
return Builder.class.cast(super.links(links));
}
/**
* {@inheritDoc}
*/
@Override
public Builder actions(Set<Action> actions) {
return Builder.class.cast(super.actions(actions));
}
/**
* {@inheritDoc}
*/
@Override
public Builder fromAttributes(Map<String, String> attributes) {
return Builder.class.cast(super.fromAttributes(attributes));
}
}
@XmlElement(name = "Index", required = false)
private int index;
@XmlElement(name = "VirtualMachines", required = false)
private VirtualMachineReferences virtualMachineReferences;
//TODO: PhysicalDevices
private LayoutGroup(URI href, String type, String name, Set<Link> links, Set<Action> actions,
int index, Set<VirtualMachineReference> virtualMachineReferences) {
super(href, type, name, links, actions);
this.index = index;
this.virtualMachineReferences = VirtualMachineReferences.builder().virtualMachineReferences(virtualMachineReferences).build();
}
private LayoutGroup() {
//For JAXB
}
public int getIndex() {
return index;
}
public Set<VirtualMachineReference> getVirtualMachineReferences() {
return virtualMachineReferences.getVirtualMachineReferences();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (!super.equals(o)) return false;
LayoutGroup that = (LayoutGroup) o;
if (index != that.index) return false;
if (!virtualMachineReferences.equals(that.virtualMachineReferences))
return false;
return true;
}
@Override
public int hashCode() {
int result = super.hashCode();
result = 31 * result + index;
result = 31 * result + virtualMachineReferences.hashCode();
return result;
}
@Override
public String string() {
return super.string()+", index="+index+", virtualMachineReferences="+virtualMachineReferences;
}
}

View File

@ -0,0 +1,200 @@
/**
* 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.tmrk.enterprisecloud.domain.layout;
import com.google.common.collect.Sets;
import org.jclouds.tmrk.enterprisecloud.domain.Action;
import org.jclouds.tmrk.enterprisecloud.domain.Link;
import org.jclouds.tmrk.enterprisecloud.domain.internal.BaseResource;
import org.jclouds.tmrk.enterprisecloud.domain.internal.Resource;
import javax.xml.bind.annotation.XmlElement;
import java.net.URI;
import java.util.Map;
import java.util.Set;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* LayoutRow is more than a simple wrapper as it extends Resource.
* <xs:complexType name="LayoutRowType">
* @author Jason King
*
*/
public class LayoutRow extends Resource<LayoutRow> {
@SuppressWarnings("unchecked")
public static Builder builder() {
return new Builder();
}
/**
* {@inheritDoc}
*/
@Override
public Builder toBuilder() {
return new Builder().fromLayoutRow(this);
}
public static class Builder extends Resource.Builder<LayoutRow> {
private int index;
private Set<LayoutGroup> groups = Sets.newLinkedHashSet();
/**
* @see org.jclouds.tmrk.enterprisecloud.domain.layout.LayoutRow#getIndex
*/
public Builder index(int index) {
this.index = index;
return this;
}
/**
* @see Groups#getGroups
*/
public Builder groups(Set<LayoutGroup> groups) {
this.groups = Sets.newLinkedHashSet(checkNotNull(groups, "groups"));
return this;
}
@Override
public LayoutRow build() {
return new LayoutRow(href, type, name, links, actions, index, groups);
}
public Builder fromLayoutRow(LayoutRow in) {
return fromResource(in).index(in.getIndex()).groups(in.getGroups());
}
/**
* {@inheritDoc}
*/
@Override
public Builder fromBaseResource(BaseResource<LayoutRow> in) {
return Builder.class.cast(super.fromBaseResource(in));
}
/**
* {@inheritDoc}
*/
@Override
public Builder fromResource(Resource<LayoutRow> in) {
return Builder.class.cast(super.fromResource(in));
}
/**
* {@inheritDoc}
*/
@Override
public Builder type(String type) {
return Builder.class.cast(super.type(type));
}
/**
* {@inheritDoc}
*/
@Override
public Builder href(URI href) {
return Builder.class.cast(super.href(href));
}
/**
* {@inheritDoc}
*/
@Override
public Builder name(String name) {
return Builder.class.cast(super.name(name));
}
/**
* {@inheritDoc}
*/
@Override
public Builder links(Set<Link> links) {
return Builder.class.cast(super.links(links));
}
/**
* {@inheritDoc}
*/
@Override
public Builder actions(Set<Action> actions) {
return Builder.class.cast(super.actions(actions));
}
/**
* {@inheritDoc}
*/
@Override
public Builder fromAttributes(Map<String, String> attributes) {
return Builder.class.cast(super.fromAttributes(attributes));
}
}
@XmlElement(name = "Index", required = false)
private int index;
@XmlElement(name = "Groups", required = false)
private Groups groups = Groups.builder().build();
private LayoutRow(URI href, String type, String name, Set<Link> links, Set<Action> actions, int index, Set<LayoutGroup> groups) {
super(href, type, name, links, actions);
this.index = index;
this.groups = Groups.builder().groups(groups).build();
}
private LayoutRow() {
//For JAXB
}
public int getIndex() {
return index;
}
public Set<LayoutGroup> getGroups() {
return groups.getGroups();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (!super.equals(o)) return false;
LayoutRow layoutRow = (LayoutRow) o;
if (index != layoutRow.index) return false;
if (!groups.equals(layoutRow.groups)) return false;
return true;
}
@Override
public int hashCode() {
int result = super.hashCode();
result = 31 * result + index;
result = 31 * result + groups.hashCode();
return result;
}
@Override
public String string() {
return super.string()+", index="+index+", groups="+groups;
}
}

View File

@ -0,0 +1,106 @@
/**
* 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.tmrk.enterprisecloud.domain.layout;
import com.google.common.collect.Sets;
import javax.xml.bind.annotation.XmlElement;
import java.util.Collections;
import java.util.Set;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Wraps individual LayoutRow elements.
* <xs:complexType name="RowsType">
* @author Jason King
*/
public class Rows {
@SuppressWarnings("unchecked")
public static Builder builder() {
return new Builder();
}
public Builder toBuilder() {
return new Builder().fromRows(this);
}
public static class Builder {
private Set<LayoutRow> rows = Sets.newLinkedHashSet();
/**
* @see Rows#getRows
*/
public Builder rows(Set<LayoutRow> rows) {
this.rows = Sets.newLinkedHashSet(checkNotNull(rows, "rows"));
return this;
}
public Builder addRow(LayoutRow row) {
rows.add(checkNotNull(row,"row"));
return this;
}
public Rows build() {
return new Rows(rows);
}
public Builder fromRows(Rows in) {
return rows(in.getRows());
}
}
private Rows() {
//For JAXB and builder use
}
private Rows(Set<LayoutRow> entries) {
this.rows = Sets.newLinkedHashSet(entries);
}
@XmlElement(name = "Row", required=false)
private Set<LayoutRow> rows = Sets.newLinkedHashSet();
public Set<LayoutRow> getRows() {
return Collections.unmodifiableSet(rows);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Rows tasks1 = (Rows) o;
if (!rows.equals(tasks1.rows)) return false;
return true;
}
@Override
public int hashCode() {
return rows.hashCode();
}
public String toString() {
return "["+ rows.toString()+"]";
}
}

View File

@ -0,0 +1,312 @@
/**
* 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.tmrk.enterprisecloud.domain.vm;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.tmrk.enterprisecloud.domain.Action;
import org.jclouds.tmrk.enterprisecloud.domain.Link;
import org.jclouds.tmrk.enterprisecloud.domain.NamedResource;
import org.jclouds.tmrk.enterprisecloud.domain.internal.BaseResource;
import org.jclouds.tmrk.enterprisecloud.domain.internal.Resource;
import org.jclouds.tmrk.enterprisecloud.domain.internal.ResourceCapacity;
import org.jclouds.tmrk.enterprisecloud.domain.software.ToolsStatus;
import javax.xml.bind.annotation.XmlElement;
import java.net.URI;
import java.util.Map;
import java.util.Set;
/**
* <xs:complexType name="VirtualMachineReferenceType">
* @author Jason King
*/
public class VirtualMachineReference extends Resource<VirtualMachineReference> {
@SuppressWarnings("unchecked")
public static Builder builder() {
return new Builder();
}
/**
* {@inheritDoc}
*/
@Override
public Builder toBuilder() {
return new Builder().fromVirtualMachineReference(this);
}
public static class Builder extends Resource.Builder<VirtualMachineReference> {
private VirtualMachine.VirtualMachineStatus status;
private int processorCount;
private ResourceCapacity memory;
private ResourceCapacity storage;
private NamedResource operatingSystem;
private boolean poweredOn;
private ToolsStatus toolsStatus;
/**
* @see org.jclouds.tmrk.enterprisecloud.domain.vm.VirtualMachineReference#getStatus()
*/
public Builder status(VirtualMachine.VirtualMachineStatus status) {
this.status = status;
return this;
}
/**
* @see org.jclouds.tmrk.enterprisecloud.domain.vm.VirtualMachineReference#getProcessorCount()
*/
public Builder processorCount(int processorCount) {
this.processorCount = processorCount;
return this;
}
/**
* @see org.jclouds.tmrk.enterprisecloud.domain.vm.VirtualMachineReference#getMemory()
*/
public Builder memory(ResourceCapacity memory) {
this.memory = memory;
return this;
}
/**
* @see org.jclouds.tmrk.enterprisecloud.domain.vm.VirtualMachineReference#getStorage()
*/
public Builder storage(ResourceCapacity storage) {
this.storage = storage;
return this;
}
/**
* @see org.jclouds.tmrk.enterprisecloud.domain.vm.VirtualMachineReference#getOperatingSystem()
*/
public Builder operatingSystem(NamedResource operatingSystem) {
this.operatingSystem = operatingSystem;
return this;
}
/**
* @see org.jclouds.tmrk.enterprisecloud.domain.vm.VirtualMachineReference#isPoweredOn()
*/
public Builder poweredOn(boolean poweredOn) {
this.poweredOn = poweredOn;
return this;
}
/**
* @see org.jclouds.tmrk.enterprisecloud.domain.vm.VirtualMachineReference#getToolsStatus()
*/
public Builder toolsStatus(ToolsStatus toolsStatus) {
this.toolsStatus = toolsStatus;
return this;
}
@Override
public VirtualMachineReference build() {
return new VirtualMachineReference(href, type, name, links, actions,
status,processorCount,memory,storage,operatingSystem,
poweredOn,toolsStatus);
}
public Builder fromVirtualMachineReference(VirtualMachineReference in) {
return fromResource(in).status(in.getStatus())
.processorCount(in.getProcessorCount())
.memory(in.getMemory())
.storage(in.getStorage())
.operatingSystem(in.getOperatingSystem())
.poweredOn(in.isPoweredOn())
.toolsStatus(in.getToolsStatus());
}
/**
* {@inheritDoc}
*/
@Override
public Builder fromBaseResource(BaseResource<VirtualMachineReference> in) {
return Builder.class.cast(super.fromBaseResource(in));
}
/**
* {@inheritDoc}
*/
@Override
public Builder fromResource(Resource<VirtualMachineReference> in) {
return Builder.class.cast(super.fromResource(in));
}
/**
* {@inheritDoc}
*/
@Override
public Builder type(String type) {
return Builder.class.cast(super.type(type));
}
/**
* {@inheritDoc}
*/
@Override
public Builder href(URI href) {
return Builder.class.cast(super.href(href));
}
/**
* {@inheritDoc}
*/
@Override
public Builder links(Set<Link> links) {
return Builder.class.cast(super.links(links));
}
/**
* {@inheritDoc}
*/
@Override
public Builder actions(Set<Action> actions) {
return Builder.class.cast(super.actions(actions));
}
/**
* {@inheritDoc}
*/
@Override
public Builder name(String name) {
return Builder.class.cast(super.name(name));
}
/**
* {@inheritDoc}
*/
@Override
public Builder fromAttributes(Map<String, String> attributes) {
super.fromAttributes(attributes);
return this;
}
}
@XmlElement(name = "Status", required = false)
private VirtualMachine.VirtualMachineStatus status;
@XmlElement(name = "ProcessorCount", required = false)
private int processorCount;
@XmlElement(name = "Memory", required = false)
private ResourceCapacity memory;
@XmlElement(name = "Storage", required = false)
private ResourceCapacity storage;
@XmlElement(name = "OperatingSystem", required = false)
private NamedResource operatingSystem;
@XmlElement(name = "PoweredOn", required = false)
private boolean poweredOn;
@XmlElement(name = "ToolsStatus", required = false)
private ToolsStatus toolsStatus;
private VirtualMachineReference(URI href, String type, String name, Set<Link> links, Set<Action> actions,
@Nullable VirtualMachine.VirtualMachineStatus status, int processorCount, @Nullable ResourceCapacity memory,
@Nullable ResourceCapacity storage, @Nullable NamedResource operatingSystem, boolean poweredOn,
@Nullable ToolsStatus toolsStatus) {
super(href, type, name, links, actions);
this.status = status;
this.processorCount = processorCount;
this.memory = memory;
this.storage = storage;
this.operatingSystem = operatingSystem;
this.poweredOn = poweredOn;
this.toolsStatus = toolsStatus;
}
private VirtualMachineReference() {
//For JAXB
}
public VirtualMachine.VirtualMachineStatus getStatus() {
return status;
}
public int getProcessorCount() {
return processorCount;
}
public ResourceCapacity getMemory() {
return memory;
}
public ResourceCapacity getStorage() {
return storage;
}
public NamedResource getOperatingSystem() {
return operatingSystem;
}
public boolean isPoweredOn() {
return poweredOn;
}
public ToolsStatus getToolsStatus() {
return toolsStatus;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (!super.equals(o)) return false;
VirtualMachineReference that = (VirtualMachineReference) o;
if (poweredOn != that.poweredOn) return false;
if (processorCount != that.processorCount) return false;
if (memory != null ? !memory.equals(that.memory) : that.memory != null)
return false;
if (operatingSystem != null ? !operatingSystem.equals(that.operatingSystem) : that.operatingSystem != null)
return false;
if (status != that.status) return false;
if (storage != null ? !storage.equals(that.storage) : that.storage != null)
return false;
if (toolsStatus != that.toolsStatus) return false;
return true;
}
@Override
public int hashCode() {
int result = super.hashCode();
result = 31 * result + (status != null ? status.hashCode() : 0);
result = 31 * result + processorCount;
result = 31 * result + (memory != null ? memory.hashCode() : 0);
result = 31 * result + (storage != null ? storage.hashCode() : 0);
result = 31 * result + (operatingSystem != null ? operatingSystem.hashCode() : 0);
result = 31 * result + (poweredOn ? 1 : 0);
result = 31 * result + (toolsStatus != null ? toolsStatus.hashCode() : 0);
return result;
}
@Override
public String string() {
return super.string()+", status="+status+", processorCount="+processorCount+", memory="+memory+
", storage="+storage+", operatingSystem="+operatingSystem+", poweredOn="+poweredOn+
", toolsStatus="+toolsStatus;
}
}

View File

@ -0,0 +1,108 @@
/**
* 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.tmrk.enterprisecloud.domain.vm;
import com.google.common.collect.Sets;
import javax.xml.bind.annotation.XmlElement;
import java.util.Collections;
import java.util.Set;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Wraps individual VirtualMachineReference elements.
* Needed because parsing is done with JAXB and it does not handle Generic collections
* <xs:complexType name="VirtualMachineReferencesType">
* @author Jason King
*/
public class VirtualMachineReferences {
@SuppressWarnings("unchecked")
public static Builder builder() {
return new Builder();
}
public Builder toBuilder() {
return new Builder().fromVirtualMachineReferencesReferences(this);
}
public static class Builder {
private Set<VirtualMachineReference> virtualMachineReferences = Sets.newLinkedHashSet();
/**
* @see org.jclouds.tmrk.enterprisecloud.domain.vm.VirtualMachineReferences#getVirtualMachineReferences
*/
public Builder virtualMachineReferences(Set<VirtualMachineReference> virtualMachineReferences) {
this.virtualMachineReferences = Sets.newLinkedHashSet(checkNotNull(virtualMachineReferences, "virtualMachineReferences"));
return this;
}
public Builder addVirtualMachineReference(VirtualMachineReference virtualMachineReference) {
virtualMachineReferences.add(checkNotNull(virtualMachineReference, "virtualMachineReference"));
return this;
}
public VirtualMachineReferences build() {
return new VirtualMachineReferences(virtualMachineReferences);
}
public Builder fromVirtualMachineReferencesReferences(VirtualMachineReferences in) {
return virtualMachineReferences(in.getVirtualMachineReferences());
}
}
private VirtualMachineReferences() {
//For JAXB and builder use
}
private VirtualMachineReferences(Set<VirtualMachineReference> virtualMachineReference) {
this.virtualMachineReferences = Sets.newLinkedHashSet(virtualMachineReference);
}
@XmlElement(name = "VirtualMachine")
private Set<VirtualMachineReference> virtualMachineReferences = Sets.newLinkedHashSet();
public Set<VirtualMachineReference> getVirtualMachineReferences() {
return Collections.unmodifiableSet(virtualMachineReferences);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
VirtualMachineReferences that = (VirtualMachineReferences) o;
if (virtualMachineReferences != null ? !virtualMachineReferences.equals(that.virtualMachineReferences) : that.virtualMachineReferences != null)
return false;
return true;
}
@Override
public int hashCode() {
return virtualMachineReferences != null ? virtualMachineReferences.hashCode() : 0;
}
public String toString() {
return "["+ virtualMachineReferences.toString()+"]";
}
}

View File

@ -0,0 +1,54 @@
/**
* 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.tmrk.enterprisecloud.features;
import com.google.common.util.concurrent.ListenableFuture;
import org.jclouds.http.filters.BasicAuthentication;
import org.jclouds.rest.annotations.*;
import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404;
import org.jclouds.tmrk.enterprisecloud.domain.layout.DeviceLayout;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import java.net.URI;
/**
* Provides asynchronous access to Layouts via their REST API.
* <p/>
*
* @see LayoutClient
* @see <a href=
* "http://support.theenterprisecloud.com/kb/default.asp?id=984&Lang=1&SID="
* />
* @author Jason King
*/
@RequestFilters(BasicAuthentication.class)
@Headers(keys = "x-tmrk-version", values = "{jclouds.api-version}")
public interface LayoutAsyncClient {
/**
* @see LayoutClient#getLayouts
*/
@GET
@Consumes("application/vnd.tmrk.cloud.deviceLayout")
@JAXBResponseParser
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
ListenableFuture<DeviceLayout> getLayouts(@EndpointParam URI uri);
}

View File

@ -0,0 +1,49 @@
/**
* 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.tmrk.enterprisecloud.features;
import org.jclouds.concurrent.Timeout;
import org.jclouds.tmrk.enterprisecloud.domain.layout.DeviceLayout;
import java.net.URI;
import java.util.concurrent.TimeUnit;
/**
* Provides synchronous access to Location.
* <p/>
*
* @see LayoutAsyncClient
* @see <a href=
* "http://support.theenterprisecloud.com/kb/default.asp?id=984&Lang=1&SID="
* />
* @author Jason King
*/
@Timeout(duration = 180, timeUnit = TimeUnit.SECONDS)
public interface LayoutClient {
/**
* The Get Layouts call returns information regarding the row and group of network hosts in an environment.
* Rows and groups allow aggregation of servers along logical boundaries defined by the organization.
* @param uri the uri based on the environment
* e.g. /cloudapi/ecloud/layout/environments/{id}
* @return the DeviceLayout
*/
DeviceLayout getLayouts(URI uri);
}

View File

@ -0,0 +1,62 @@
/**
* 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.tmrk.enterprisecloud.features;
import com.google.inject.TypeLiteral;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.functions.ParseXMLWithJAXB;
import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404;
import org.jclouds.rest.internal.RestAnnotationProcessor;
import org.testng.annotations.Test;
import java.io.IOException;
import java.lang.reflect.Method;
import java.net.URI;
import java.net.URISyntaxException;
/**
* Tests annotation parsing of {@code LayoutAsyncClient}
*
* @author Jason King
*/
@Test(groups = "unit", testName = "LayoutAsyncClientTest")
public class LayoutAsyncClientTest extends BaseTerremarkEnterpriseCloudAsyncClientTest<LayoutAsyncClient> {
public void testGetLayouts() throws SecurityException, NoSuchMethodException, IOException, URISyntaxException {
Method method = LayoutAsyncClient.class.getMethod("getLayouts", URI.class);
HttpRequest httpRequest = processor.createRequest(method, URI.create("/cloudapi/ecloud/layout/environments/77"));
assertRequestLineEquals(httpRequest, "GET https://services-beta.enterprisecloud.terremark.com/cloudapi/ecloud/layout/environments/77 HTTP/1.1");
assertNonPayloadHeadersEqual(httpRequest,
"Accept: application/vnd.tmrk.cloud.deviceLayout\nx-tmrk-version: 2011-07-01\n");
assertPayloadEquals(httpRequest, null, null, false);
assertResponseParserClassEquals(method, httpRequest, ParseXMLWithJAXB.class);
assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class);
checkFilters(httpRequest);
}
@Override
protected TypeLiteral<RestAnnotationProcessor<LayoutAsyncClient>> createTypeLiteral() {
return new TypeLiteral<RestAnnotationProcessor<LayoutAsyncClient>>() {
};
}
}

View File

@ -0,0 +1,53 @@
/**
* 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.tmrk.enterprisecloud.features;
import org.jclouds.tmrk.enterprisecloud.domain.layout.DeviceLayout;
import org.testng.annotations.BeforeGroups;
import org.testng.annotations.Test;
import java.net.URI;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertNull;
/**
* Tests behavior of {@code LayoutClient}
*
* @author Jason King
*/
@Test(groups = "live", testName = "LayoutClientLiveTest")
public class LayoutClientLiveTest extends BaseTerremarkEnterpriseCloudClientLiveTest {
@BeforeGroups(groups = { "live" })
public void setupClient() {
super.setupClient();
client = context.getApi().getLayoutClient();
}
private LayoutClient client;
public void testGetLayouts() throws Exception {
DeviceLayout layout = client.getLayouts(URI.create("/cloudapi/ecloud/layout/environments/77"));
assertNotNull(layout);
}
public void testGetMissingLayouts() {
assertNull(client.getLayouts(URI.create("/cloudapi/ecloud/layout/environments/-1")));
}
}

View File

@ -0,0 +1,134 @@
/**
* 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.tmrk.enterprisecloud.xml;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.inject.AbstractModule;
import com.google.inject.Module;
import com.google.inject.Provides;
import org.jclouds.crypto.Crypto;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.jclouds.http.functions.ParseSax;
import org.jclouds.http.functions.ParseXMLWithJAXB;
import org.jclouds.logging.config.NullLoggingModule;
import org.jclouds.rest.AuthorizationException;
import org.jclouds.rest.BaseRestClientTest;
import org.jclouds.rest.RestContextSpec;
import org.jclouds.rest.internal.RestAnnotationProcessor;
import org.jclouds.tmrk.enterprisecloud.domain.NamedResource;
import org.jclouds.tmrk.enterprisecloud.domain.internal.ResourceCapacity;
import org.jclouds.tmrk.enterprisecloud.domain.layout.DeviceLayout;
import org.jclouds.tmrk.enterprisecloud.domain.layout.LayoutGroup;
import org.jclouds.tmrk.enterprisecloud.domain.layout.LayoutRow;
import org.jclouds.tmrk.enterprisecloud.domain.vm.VirtualMachine;
import org.jclouds.tmrk.enterprisecloud.domain.vm.VirtualMachineReference;
import org.jclouds.tmrk.enterprisecloud.features.LayoutAsyncClient;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import javax.inject.Named;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.net.URI;
import java.util.Set;
import static org.jclouds.io.Payloads.newInputStreamPayload;
import static org.jclouds.rest.RestContextFactory.contextSpec;
import static org.jclouds.rest.RestContextFactory.createContextBuilder;
import static org.testng.Assert.assertEquals;
/**
* Tests behavior of JAXB parsing for DeviceLayout
*
* @author Jason King
*/
@Test(groups = "unit", testName = "DeviceLayoutJAXBParsingTest")
public class DeviceLayoutJAXBParsingTest extends BaseRestClientTest {
@BeforeClass
void setupFactory() {
RestContextSpec<String, Integer> contextSpec = contextSpec("test", "http://localhost:9999", "1", "", "userfoo",
"credentialFoo", String.class, Integer.class,
ImmutableSet.<Module> of(new MockModule(), new NullLoggingModule(), new AbstractModule() {
@Override
protected void configure() {}
@SuppressWarnings("unused")
@Provides
@Named("exception")
Set<String> exception() {
throw new AuthorizationException();
}
}));
injector = createContextBuilder(contextSpec).buildInjector();
parserFactory = injector.getInstance(ParseSax.Factory.class);
crypto = injector.getInstance(Crypto.class);
}
@Test
public void testParseDeviceLayoutWithJAXB() throws Exception {
Method method = LayoutAsyncClient.class.getMethod("getLayouts",URI.class);
HttpRequest request = factory(LayoutAsyncClient.class).createRequest(method, new URI("/1"));
assertResponseParserClassEquals(method, request, ParseXMLWithJAXB.class);
Function<HttpResponse, DeviceLayout> parser = (Function<HttpResponse, DeviceLayout>) RestAnnotationProcessor
.createResponseParser(parserFactory, injector, method, request);
InputStream is = getClass().getResourceAsStream("/deviceLayout.xml");
DeviceLayout location = parser.apply(new HttpResponse(200, "ok", newInputStreamPayload(is)));
assertRows(location.getRows());
}
private void assertRows(Set<LayoutRow> rows) {
assertEquals(rows.size(),1);
LayoutRow row = Iterables.getOnlyElement(rows);
assertEquals(row.getIndex(),1);
assertGroups(row.getGroups());
}
private void assertGroups(Set<LayoutGroup> groups) {
assertEquals(groups.size(),1);
LayoutGroup group = Iterables.getOnlyElement(groups);
assertEquals(group.getIndex(), 33);
assertVirtualMachineReferences(group.getVirtualMachineReferences());
}
private void assertVirtualMachineReferences(Set<VirtualMachineReference> virtualMachineReferences) {
assertEquals(virtualMachineReferences.size(), 1);
VirtualMachineReference vmReference = Iterables.getOnlyElement(virtualMachineReferences);
assertEquals(vmReference.getName(),"helloworld");
assertEquals(vmReference.getStatus(), VirtualMachine.VirtualMachineStatus.DEPLOYED);
assertEquals(vmReference.getProcessorCount(),1);
assertEquals(vmReference.getMemory(), ResourceCapacity.builder().value(384).unit("MB").build());
assertEquals(vmReference.getStorage(), ResourceCapacity.builder().value(10).unit("GB").build());
NamedResource expectedOs = NamedResource.builder().href(URI.create("/cloudapi/ecloud/operatingsystems/rhel5_64guest/computepools/89"))
.name("Red Hat Enterprise Linux 5 (64-bit)")
.type("application/vnd.tmrk.cloud.operatingSystem").build();
assertEquals(vmReference.getOperatingSystem(),expectedOs);
}
}

View File

@ -0,0 +1,89 @@
<DeviceLayout href="/cloudapi/ecloud/layout/environments/77"
type="application/vnd.tmrk.cloud.deviceLayout"
xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<Links>
<Link href="/cloudapi/ecloud/environments/77" name="Beta Environment 01"
type="application/vnd.tmrk.cloud.environment" rel="up"/>
</Links>
<Actions>
<Action href="/cloudapi/ecloud/layoutrows/environments/77/action/createlayoutrow"
name="createLayoutRow"
type="application/vnd.tmrk.cloud.createLayoutRow"/>
<Action href="/cloudapi/ecloud/layoutgroups/environments/77/action/createlayoutgroup"
name="createLayoutGroup"
type="application/vnd.tmrk.cloud.createLayoutGroup"/>
</Actions>
<Rows>
<Row href="/cloudapi/ecloud/layoutrows/285" name="test row"
type="application/vnd.tmrk.cloud.layoutRow">
<Links>
<Link href="/cloudapi/ecloud/layout/environments/77"
name="Beta Environment 01"
type="application/vnd.tmrk.cloud.deviceLayout" rel="up"/>
</Links>
<Actions>
<Action href="/cloudapi/ecloud/layoutgroups/environments/77/action/createlayoutgroup"
name="createLayoutGroup"
type="application/vnd.tmrk.cloud.createLayoutGroup"/>
<Action href="/cloudapi/ecloud/layoutrows/285" name="edit"
type="application/vnd.tmrk.cloud.layoutRow"/>
<Action href="/cloudapi/ecloud/layoutrows/285/action/moveup"
name="moveUp" actionDisabled="disabled"/>
<Action href="/cloudapi/ecloud/layoutrows/285/action/movedown"
name="moveDown" actionDisabled="disabled"/>
<Action href="/cloudapi/ecloud/layoutrows/285" name="remove"
actionDisabled="disabled"/>
</Actions>
<Index>1</Index>
<Groups>
<Group href="/cloudapi/ecloud/layoutgroups/308"
name="test group"
type="application/vnd.tmrk.cloud.layoutGroup">
<Links>
<Link href="/cloudapi/ecloud/layoutrows/285"
name="test row"
type="application/vnd.tmrk.cloud.layoutRow"
rel="up"/>
<Link href="/cloudapi/ecloud/layout/environments/77"
name="Beta Environment 01"
type="application/vnd.tmrk.cloud.deviceLayout"
rel="up"/>
</Links>
<Actions>
<Action href="/cloudapi/ecloud/layoutgroups/308"
name="edit"
type="application/vnd.tmrk.cloud.layoutGroup"/>
<Action href="/cloudapi/ecloud/layoutgroups/308/action/orderhigher"
name="orderHigher" actionDisabled="disabled"/>
<Action href="/cloudapi/ecloud/layoutgroups/308/action/orderlower"
name="orderLower" actionDisabled="disabled"/>
<Action href="/cloudapi/ecloud/layoutgroups/308"
name="remove" actionDisabled="disabled"/>
</Actions>
<Index>33</Index>
<VirtualMachines>
<VirtualMachine
href="/cloudapi/ecloud/virtualmachines/5504"
name="helloworld"
type="application/vnd.tmrk.cloud.virtualMachine">
<Status>Deployed</Status>
<ProcessorCount>1</ProcessorCount>
<Memory>
<Unit>MB</Unit>
<Value>384</Value>
</Memory>
<Storage>
<Unit>GB</Unit>
<Value>10</Value>
</Storage>
<OperatingSystem
href="/cloudapi/ecloud/operatingsystems/rhel5_64guest/computepools/89"
name="Red Hat Enterprise Linux 5 (64-bit)"
type="application/vnd.tmrk.cloud.operatingSystem"/>
</VirtualMachine>
</VirtualMachines>
</Group>
</Groups>
</Row>
</Rows>
</DeviceLayout>