diff --git a/core-test/src/main/java/org/openstack4j/api/storage/VolumeTypeTests.java b/core-test/src/main/java/org/openstack4j/api/storage/VolumeTypeTests.java new file mode 100644 index 000000000..bfb1ff7b5 --- /dev/null +++ b/core-test/src/main/java/org/openstack4j/api/storage/VolumeTypeTests.java @@ -0,0 +1,46 @@ +package org.openstack4j.api.storage; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertTrue; + +import java.io.IOException; + +import org.openstack4j.api.AbstractTest; +import org.openstack4j.api.Builders; +import org.openstack4j.model.common.ActionResponse; +import org.openstack4j.model.storage.block.VolumeType; +import org.testng.annotations.Test; + +@Test(suiteName = "Block Storage Tests") +public class VolumeTypeTests extends AbstractTest { + + @Override + protected Service service() { + return Service.BLOCK_STORAGE; + } + + @Test + public void createVolumeType() throws Exception { + respondWith("/storage/v2/createVolumeTypeResponse.json"); + final String volumeTypeName = "testVolume"; + VolumeType volumeType = Builders.volumeType().name(volumeTypeName).build(); + volumeType = osv3().blockStorage().volumes().createVolumeType(volumeType); + assertEquals(volumeType.getName(), volumeTypeName); + assertEquals(volumeType.getExtraSpecs().get("capabilities"), "gpu"); + } + + @Test + public void deleteVolumeType() throws IOException, Exception { + respondWith(200); + String volumeTypeId = "volumeTypeToBeDeleted"; + osv3().blockStorage().volumes().deleteVolumeType(volumeTypeId); + } + + @Test + public void extendVolume() throws Exception { + respondWith(200); + String volumeId = "volumeTestId"; + ActionResponse response = osv3().blockStorage().volumes().extend(volumeId, 30); + assertTrue(response.isSuccess(), "The http response was not successful"); + } +} diff --git a/core-test/src/main/resources/storage/v2/createVolumeTypeResponse.json b/core-test/src/main/resources/storage/v2/createVolumeTypeResponse.json new file mode 100644 index 000000000..9148cda03 --- /dev/null +++ b/core-test/src/main/resources/storage/v2/createVolumeTypeResponse.json @@ -0,0 +1,9 @@ +{ + "volume_type": { + "id": "6685584b-1eac-4da6-b5c3-555430cf68ff", + "name": "testVolume", + "extra_specs": { + "capabilities": "gpu" + } + } +} \ No newline at end of file diff --git a/core/src/main/java/org/openstack4j/api/Builders.java b/core/src/main/java/org/openstack4j/api/Builders.java index 6d0e1f7c6..2205fd183 100644 --- a/core/src/main/java/org/openstack4j/api/Builders.java +++ b/core/src/main/java/org/openstack4j/api/Builders.java @@ -8,6 +8,7 @@ import org.openstack4j.model.gbp.builder.L2PolicyBuilder; import org.openstack4j.model.gbp.builder.L3PolicyBuilder; import org.openstack4j.model.gbp.builder.NatPoolBuilder; +import org.openstack4j.model.gbp.builder.NetworkServicePolicyBuilder; import org.openstack4j.model.gbp.builder.PolicyActionCreateBuilder; import org.openstack4j.model.gbp.builder.PolicyActionUpdateBuilder; import org.openstack4j.model.gbp.builder.PolicyClassifierBuilder; @@ -16,7 +17,6 @@ import org.openstack4j.model.gbp.builder.PolicyRuleSetBuilder; import org.openstack4j.model.gbp.builder.PolicyTargetBuilder; import org.openstack4j.model.gbp.builder.PolicyTargetGroupBuilder; -import org.openstack4j.model.gbp.builder.NetworkServicePolicyBuilder; import org.openstack4j.model.heat.SoftwareConfig; import org.openstack4j.model.heat.StackCreate; import org.openstack4j.model.heat.StackUpdate; @@ -33,19 +33,20 @@ import org.openstack4j.model.storage.block.builder.StorageBuilders; import org.openstack4j.model.storage.block.builder.VolumeBuilder; import org.openstack4j.model.storage.block.builder.VolumeSnapshotBuilder; +import org.openstack4j.model.storage.block.builder.VolumeTypeBuilder; import org.openstack4j.model.telemetry.builder.AlarmBuilder; import org.openstack4j.model.telemetry.builder.TelemetryBuilders; import org.openstack4j.openstack.common.GenericLink; import org.openstack4j.openstack.compute.builder.NovaBuilders; import org.openstack4j.openstack.compute.domain.*; import org.openstack4j.openstack.compute.domain.NovaSecGroupExtension.SecurityGroupRule; -import org.openstack4j.openstack.compute.domain.NovaServerCreate; import org.openstack4j.openstack.gbp.domain.GbpExternalPolicyCreate; import org.openstack4j.openstack.gbp.domain.GbpExternalRoutes; import org.openstack4j.openstack.gbp.domain.GbpExternalSegment; import org.openstack4j.openstack.gbp.domain.GbpL2Policy; import org.openstack4j.openstack.gbp.domain.GbpL3Policy; import org.openstack4j.openstack.gbp.domain.GbpNatPool; +import org.openstack4j.openstack.gbp.domain.GbpNetworkServicePolicy; import org.openstack4j.openstack.gbp.domain.GbpPolicyAction; import org.openstack4j.openstack.gbp.domain.GbpPolicyActionUpdate; import org.openstack4j.openstack.gbp.domain.GbpPolicyClassifier; @@ -54,7 +55,6 @@ import org.openstack4j.openstack.gbp.domain.GbpPolicyRuleSet; import org.openstack4j.openstack.gbp.domain.GbpPolicyTarget; import org.openstack4j.openstack.gbp.domain.GbpPolicyTargetGroupCreate; -import org.openstack4j.openstack.gbp.domain.GbpNetworkServicePolicy; import org.openstack4j.openstack.heat.builder.HeatBuilders; import org.openstack4j.openstack.heat.domain.HeatSoftwareConfig; import org.openstack4j.openstack.heat.domain.HeatStackCreate; @@ -75,6 +75,7 @@ import org.openstack4j.openstack.storage.block.domain.CinderBlockQuotaSet; import org.openstack4j.openstack.storage.block.domain.CinderVolume; import org.openstack4j.openstack.storage.block.domain.CinderVolumeSnapshot; +import org.openstack4j.openstack.storage.block.domain.CinderVolumeType; import org.openstack4j.openstack.telemetry.builder.CeilometerBuilders; import org.openstack4j.openstack.telemetry.domain.CeilometerAlarm; @@ -174,6 +175,15 @@ public static VolumeBuilder volume() { return CinderVolume.builder(); } + /** + * The builder to create a Volume Type + * + * @return the volume type builder + */ + public static VolumeTypeBuilder volumeType() { + return CinderVolumeType.builder(); + } + /** * The builder to create a Block Volume Snapshot * diff --git a/core/src/main/java/org/openstack4j/api/storage/BlockVolumeService.java b/core/src/main/java/org/openstack4j/api/storage/BlockVolumeService.java index 4783c7057..b0ba70553 100644 --- a/core/src/main/java/org/openstack4j/api/storage/BlockVolumeService.java +++ b/core/src/main/java/org/openstack4j/api/storage/BlockVolumeService.java @@ -24,6 +24,23 @@ public interface BlockVolumeService extends RestService { */ List listVolumeTypes(); + /** + * Deletes the specified VolumeType + * + * @param volumeTypeId + * the volume type identifier + */ + void deleteVolumeType(String volumeTypeId); + + /** + * Creates a new volume type with the specified name + * + * @param volumeType + * the volumeType for create + * @return the created volume type + */ + VolumeType createVolumeType(VolumeType volumeType); + /** * Lists summary information for all Block Storage volumes that the tenant who submits the request can access. * diff --git a/core/src/main/java/org/openstack4j/model/storage/block/VolumeType.java b/core/src/main/java/org/openstack4j/model/storage/block/VolumeType.java index 3ded43843..8a609c44f 100644 --- a/core/src/main/java/org/openstack4j/model/storage/block/VolumeType.java +++ b/core/src/main/java/org/openstack4j/model/storage/block/VolumeType.java @@ -2,7 +2,9 @@ import java.util.Map; +import org.openstack4j.common.Buildable; import org.openstack4j.model.ModelEntity; +import org.openstack4j.model.storage.block.builder.VolumeTypeBuilder; /** * The volume type defines the characteristics of a volume. It usually maps to a set of capabilities @@ -11,7 +13,7 @@ * * @author Jeremy Unruh */ -public interface VolumeType extends ModelEntity { +public interface VolumeType extends ModelEntity, Buildable { /** * @return the identifier for the volume type diff --git a/core/src/main/java/org/openstack4j/model/storage/block/builder/VolumeTypeBuilder.java b/core/src/main/java/org/openstack4j/model/storage/block/builder/VolumeTypeBuilder.java new file mode 100644 index 000000000..76641358e --- /dev/null +++ b/core/src/main/java/org/openstack4j/model/storage/block/builder/VolumeTypeBuilder.java @@ -0,0 +1,25 @@ +package org.openstack4j.model.storage.block.builder; + +import java.util.Map; + +import org.openstack4j.common.Buildable.Builder; +import org.openstack4j.model.storage.block.VolumeType; + +public interface VolumeTypeBuilder extends Builder { + + /** + * See {@link VolumeType#getName()} + * + * @param name the name of the volume type + * @return VolumeTypeBuilder + */ + VolumeTypeBuilder name(String name); + + /** + * See {@link VolumeType#getExtraSpecs()} Optional + * + * @param extraSpecs Defining extra specs for the volume type as a key-value map. + * @return VolumeTypeBuilder + */ + VolumeTypeBuilder extraSpecs(Map extraSpecs); +} diff --git a/core/src/main/java/org/openstack4j/openstack/storage/block/domain/CinderVolumeType.java b/core/src/main/java/org/openstack4j/openstack/storage/block/domain/CinderVolumeType.java index 799c96ece..d45161f1c 100644 --- a/core/src/main/java/org/openstack4j/openstack/storage/block/domain/CinderVolumeType.java +++ b/core/src/main/java/org/openstack4j/openstack/storage/block/domain/CinderVolumeType.java @@ -4,6 +4,7 @@ import java.util.Map; import org.openstack4j.model.storage.block.VolumeType; +import org.openstack4j.model.storage.block.builder.VolumeTypeBuilder; import org.openstack4j.openstack.common.ListResult; import com.fasterxml.jackson.annotation.JsonProperty; @@ -51,6 +52,18 @@ public String getName() { public Map getExtraSpecs() { return extraSpecs; } + + @Override + public VolumeTypeBuilder toBuilder() { + return new ConcreteVolumeTypeBuilder(this); + } + + /** + * @return the Volume Type Builder + */ + public static VolumeTypeBuilder builder() { + return new ConcreteVolumeTypeBuilder(); + } /** * {@inheritDoc} @@ -75,5 +88,41 @@ protected List value() { } } - + + public static class ConcreteVolumeTypeBuilder implements VolumeTypeBuilder { + + private CinderVolumeType m; + + ConcreteVolumeTypeBuilder() { + this(new CinderVolumeType()); + } + + ConcreteVolumeTypeBuilder(CinderVolumeType volumeType) { + this.m = volumeType; + } + + @Override + public VolumeType build() { + return m; + } + + @Override + public VolumeTypeBuilder from(VolumeType in) { + m = (CinderVolumeType) in; + return this; + } + + @Override + public VolumeTypeBuilder name(String name) { + m.name = name; + return this; + } + + @Override + public VolumeTypeBuilder extraSpecs(Map extraSpecs) { + m.extraSpecs = extraSpecs; + return this; + } + } + } diff --git a/core/src/main/java/org/openstack4j/openstack/storage/block/internal/BlockVolumeServiceImpl.java b/core/src/main/java/org/openstack4j/openstack/storage/block/internal/BlockVolumeServiceImpl.java index edc393357..c2560bcd1 100644 --- a/core/src/main/java/org/openstack4j/openstack/storage/block/internal/BlockVolumeServiceImpl.java +++ b/core/src/main/java/org/openstack4j/openstack/storage/block/internal/BlockVolumeServiceImpl.java @@ -18,10 +18,11 @@ import org.openstack4j.openstack.storage.block.domain.CinderVolume; import org.openstack4j.openstack.storage.block.domain.CinderVolume.Volumes; import org.openstack4j.openstack.storage.block.domain.CinderVolumeMigration; +import org.openstack4j.openstack.storage.block.domain.CinderVolumeType; import org.openstack4j.openstack.storage.block.domain.CinderVolumeType.VolumeTypes; +import org.openstack4j.openstack.storage.block.domain.CinderVolumeUploadImage; import org.openstack4j.openstack.storage.block.domain.ExtendAction; import org.openstack4j.openstack.storage.block.domain.ForceDeleteAction; -import org.openstack4j.openstack.storage.block.domain.CinderVolumeUploadImage; import org.openstack4j.openstack.storage.block.domain.ResetStatusAction; import org.openstack4j.openstack.storage.block.domain.UpdateReadOnlyFlagAction; @@ -133,6 +134,25 @@ public ActionResponse update(String volumeId, String name, String description) { .execute(); } + /** + * {@inheritDoc} + */ + @Override + public void deleteVolumeType(String volumeTypeId) { + checkNotNull(volumeTypeId); + delete(Void.class, uri("/types/%s", volumeTypeId)).execute(); + + } + + /** + * {@inheritDoc} + */ + @Override + public VolumeType createVolumeType(VolumeType volumeType) { + checkNotNull(volumeType); + return post(CinderVolumeType.class, uri("/types")).entity(volumeType).execute(); + } + @Override public ActionResponse migrate(String volumeId, String hostService, boolean forceHostCopy) { CinderVolumeMigration migration = new CinderVolumeMigration(hostService, forceHostCopy);