From 90df0e56a17b32156bdc6b4f243d3c5008f86189 Mon Sep 17 00:00:00 2001 From: Marco Ziccardi Date: Fri, 22 Apr 2016 15:32:02 +0200 Subject: [PATCH] Add NetworkInterface, AccessConfig classes and related tests (#947) --- .../gcloud/compute/NetworkInterface.java | 505 ++++++++++++++++++ .../gcloud/compute/NetworkInterfaceTest.java | 179 +++++++ .../gcloud/compute/SerializationTest.java | 15 +- 3 files changed, 694 insertions(+), 5 deletions(-) create mode 100644 gcloud-java-compute/src/main/java/com/google/gcloud/compute/NetworkInterface.java create mode 100644 gcloud-java-compute/src/test/java/com/google/gcloud/compute/NetworkInterfaceTest.java diff --git a/gcloud-java-compute/src/main/java/com/google/gcloud/compute/NetworkInterface.java b/gcloud-java-compute/src/main/java/com/google/gcloud/compute/NetworkInterface.java new file mode 100644 index 000000000000..cf937de68ed6 --- /dev/null +++ b/gcloud-java-compute/src/main/java/com/google/gcloud/compute/NetworkInterface.java @@ -0,0 +1,505 @@ +/* + * Copyright 2016 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.gcloud.compute; + +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.common.base.Function; +import com.google.common.base.MoreObjects; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Lists; + +import java.io.Serializable; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; + +/** + * A network interface for a Google Compute Engine instance. Network interfaces specify how + * the instance is configured to interact with other network services, such as connecting to the + * internet. + * + * @see Configuring an + * Instance's IP Addresses + */ +public class NetworkInterface implements Serializable { + + static final Function + FROM_PB_FUNCTION = + new Function() { + @Override + public NetworkInterface apply( + com.google.api.services.compute.model.NetworkInterface pb) { + return NetworkInterface.fromPb(pb); + } + }; + static final Function + TO_PB_FUNCTION = + new Function() { + @Override + public com.google.api.services.compute.model.NetworkInterface apply( + NetworkInterface networkInterface) { + return networkInterface.toPb(); + } + }; + + private static final long serialVersionUID = 936741262053605581L; + + private final String name; + private final NetworkId network; + private final String networkIp; + private final SubnetworkId subnetwork; + private final List accessConfigurations; + + /** + * Access configuration for a Google Compute Engine instance's network interface. Objects of this + * class can be used to assign either a static or an ephemeral external IP address to Google + * Compute Engine instances. + * + * @see + * Static external IP addresses + * @see + * Ephemeral external IP addresses + */ + public static final class AccessConfig implements Serializable { + + static final Function + FROM_PB_FUNCTION = + new Function() { + @Override + public AccessConfig apply(com.google.api.services.compute.model.AccessConfig pb) { + return AccessConfig.fromPb(pb); + } + }; + static final Function + TO_PB_FUNCTION = + new Function() { + @Override + public com.google.api.services.compute.model.AccessConfig apply( + AccessConfig instance) { + return instance.toPb(); + } + }; + + private static final long serialVersionUID = -5438060668934041567L; + + private final String name; + private final String natIp; + private final Type type; + + /** + * The type of network access configuration. The only supported value is {@code ONE_TO_ONE_NAT}. + */ + public enum Type { + ONE_TO_ONE_NAT + } + + public static final class Builder { + + private String name; + private String natIp; + private Type type; + + private Builder() {} + + private Builder(AccessConfig accessConfig) { + this.name = accessConfig.name; + this.natIp = accessConfig.natIp; + this.type = accessConfig.type; + } + + /** + * Sets the name of the access configuration. + */ + public Builder name(String name) { + this.name = name; + return this; + } + + /** + * Sets an external IP address associated with this instance. Specify an unused static + * external IP address available to the project or leave this field undefined to use an IP + * from a shared ephemeral IP address pool. If you specify a static external IP address, it + * must live in the same region as the zone of the instance. + * + * @see + * Ephemeral external IP addresses + * @see + * Ephemeral external IP addresses + */ + public Builder natIp(String natIp) { + this.natIp = natIp; + return this; + } + + /** + * Sets the type of the access configuration. The only supported value is + * {@link Type#ONE_TO_ONE_NAT}. + */ + public Builder type(Type type) { + this.type = type; + return this; + } + + /** + * Creates an {@code AccessConfig} object. + */ + public AccessConfig build() { + return new AccessConfig(this); + } + } + + AccessConfig(Builder builder) { + this.name = builder.name; + this.natIp = builder.natIp; + this.type = builder.type; + } + + /** + * Returns the name of the access configuration. + */ + public String name() { + return name; + } + + /** + * Returns an external IP address associated with this instance. + */ + public String natIp() { + return natIp; + } + + /** + * Returns the type of network access configuration. The only supported value is + * {@link Type#ONE_TO_ONE_NAT}. + */ + public Type type() { + return type; + } + + /** + * Returns a builder for the current access configuration. + */ + public Builder toBuilder() { + return new Builder(this); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("name", name) + .add("natIp", natIp) + .add("type", type) + .toString(); + } + + @Override + public int hashCode() { + return Objects.hash(name, natIp, type); + } + + @Override + public boolean equals(Object obj) { + return obj == this + || obj instanceof AccessConfig + && Objects.equals(toPb(), ((AccessConfig) obj).toPb()); + } + + com.google.api.services.compute.model.AccessConfig toPb() { + com.google.api.services.compute.model.AccessConfig accessConfigPb = + new com.google.api.services.compute.model.AccessConfig(); + accessConfigPb.setName(name); + accessConfigPb.setNatIP(natIp); + if (type != null) { + accessConfigPb.setType(type.name()); + } + return accessConfigPb; + } + + /** + * Returns a builder for an {@code AccessConfig} object. + */ + public static Builder builder() { + return new Builder(); + } + + /** + * Returns an {@code AccessConfig} object given the static external IP address. + * + * @see + * Static external IP addresses + */ + public static AccessConfig of(String natIp) { + return builder().natIp(natIp).build(); + } + + /** + * Returns an {@code AccessConfig} object. IP address for this access configuration will be + * taken from a pool of ephemeral addresses. + * + * @see + * Ephemeral external IP addresses + */ + public static AccessConfig of() { + return builder().build(); + } + + static AccessConfig fromPb(com.google.api.services.compute.model.AccessConfig configPb) { + Builder builder = builder(); + builder.name(configPb.getName()); + if (configPb.getNatIP() != null) { + builder.natIp(configPb.getNatIP()); + } + if (configPb.getType() != null) { + builder.type(Type.valueOf(configPb.getType())); + } + return builder.build(); + } + } + + public static final class Builder { + + private String name; + private NetworkId network; + private String networkIp; + private SubnetworkId subnetwork; + private List accessConfigurations; + + private Builder(NetworkId network) { + this.network = checkNotNull(network); + } + + private Builder(NetworkInterface networkInterface) { + this.name = networkInterface.name; + this.network = networkInterface.network; + this.networkIp = networkInterface.networkIp; + this.subnetwork = networkInterface.subnetwork; + this.accessConfigurations = networkInterface.accessConfigurations; + } + + Builder name(String name) { + this.name = name; + return this; + } + + /** + * Sets the identity of the network this interface applies to. + */ + public Builder network(NetworkId network) { + this.network = checkNotNull(network); + return this; + } + + Builder networkIp(String networkIp) { + this.networkIp = networkIp; + return this; + } + + /** + * Sets the identity of the subnetwork this interface applies to. Setting the subnetwork is + * not necessary when the network is in "automatic subnet mode". + */ + public Builder subnetwork(SubnetworkId subnetwork) { + this.subnetwork = subnetwork; + return this; + } + + /** + * Sets a list of access configurations for the network interface. Access configurations can be + * used to assign either a static or an ephemeral external IP address to Google Compute Engine + * instances. At the moment, network interfaces only support one access configuration. + * + * @see + * Static external IP addresses + * @see + * Ephemeral external IP addresses + */ + public Builder accessConfigurations(List accessConfigurations) { + this.accessConfigurations = ImmutableList.copyOf(accessConfigurations); + return this; + } + + /** + * Sets a list of access configurations for the network interface. Access configurations can be + * used to assign either a static or an ephemeral external IP address to Google Compute Engine + * instances. At the moment, network interfaces only support one access configuration. + * + * @see + * Static external IP addresses + * @see + * Ephemeral external IP addresses + */ + public Builder accessConfigurations(AccessConfig... accessConfigurations) { + accessConfigurations(Arrays.asList(accessConfigurations)); + return this; + } + + /** + * Creates a {@code NetworkInterface} object. + */ + public NetworkInterface build() { + return new NetworkInterface(this); + } + } + + private NetworkInterface(Builder builder) { + this.name = builder.name; + this.network = builder.network; + this.networkIp = builder.networkIp; + this.subnetwork = builder.subnetwork; + this.accessConfigurations = builder.accessConfigurations != null + ? builder.accessConfigurations : ImmutableList.of(); + } + + /** + * Returns the name of the network interface, generated by the service. For network devices, + * these are {@code eth0}, {@code eth1}, etc. + */ + public String name() { + return name; + } + + /** + * Returns the identity of the network this interface applies to. + */ + public NetworkId network() { + return network; + } + + /** + * An optional IPv4 internal network address assigned by the service to the instance for this + * network interface. + */ + public String networkIp() { + return networkIp; + } + + /** + * Returns the identity of the subnetwork this interface applies to. + */ + public SubnetworkId subnetwork() { + return subnetwork; + } + + /** + * Returns a list of access configurations for the network interface. + */ + public List accessConfigurations() { + return accessConfigurations; + } + + /** + * Returns a builder for the current network interface. + */ + public Builder toBuilder() { + return new Builder(this); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("name", name) + .add("network", network) + .add("networkIp", networkIp) + .add("subnetwork", subnetwork) + .add("accessConfigurations", accessConfigurations) + .toString(); + } + + @Override + public final int hashCode() { + return Objects.hash(name, network, networkIp, subnetwork, accessConfigurations); + } + + @Override + public final boolean equals(Object obj) { + return obj == this + || obj != null + && obj.getClass().equals(NetworkInterface.class) + && Objects.equals(toPb(), ((NetworkInterface) obj).toPb()); + } + + com.google.api.services.compute.model.NetworkInterface toPb() { + com.google.api.services.compute.model.NetworkInterface interfacePb = + new com.google.api.services.compute.model.NetworkInterface(); + interfacePb.setName(name); + interfacePb.setNetwork(network.selfLink()); + if (subnetwork != null) { + interfacePb.setSubnetwork(subnetwork.selfLink()); + } + interfacePb.setNetworkIP(networkIp); + if (accessConfigurations != null) { + interfacePb.setAccessConfigs( + Lists.transform(accessConfigurations, AccessConfig.TO_PB_FUNCTION)); + } + return interfacePb; + } + + NetworkInterface setProjectId(String projectId) { + Builder builder = toBuilder(); + builder.network(network.setProjectId(projectId)); + if (subnetwork != null) { + builder.subnetwork(subnetwork.setProjectId(projectId)); + } + return builder.build(); + } + + /** + * Returns a builder for a {@code NetworkInterface} object given the network's identity. + */ + public static Builder builder(NetworkId networkId) { + return new Builder(networkId); + } + + /** + * Returns a builder for a {@code NetworkInterface} object given the network's name. + */ + public static Builder builder(String network) { + return builder(NetworkId.of(network)); + } + + /** + * Returns a {@code NetworkInterface} object given the network's identity. + */ + public static NetworkInterface of(NetworkId networkId) { + return builder(networkId).build(); + } + + /** + * Returns a {@code NetworkInterface} object given the network's name. + */ + public static NetworkInterface of(String network) { + return builder(network).build(); + } + + static NetworkInterface fromPb( + com.google.api.services.compute.model.NetworkInterface interfacePb) { + Builder builder = builder(NetworkId.fromUrl(interfacePb.getNetwork())) + .name(interfacePb.getName()); + if (interfacePb.getSubnetwork() != null){ + builder.subnetwork(SubnetworkId.fromUrl(interfacePb.getSubnetwork())); + } + builder.networkIp(interfacePb.getNetworkIP()); + builder.accessConfigurations(interfacePb.getAccessConfigs() != null + ? Lists.transform(interfacePb.getAccessConfigs(), AccessConfig.FROM_PB_FUNCTION) : + ImmutableList.of()); + return builder.build(); + } +} diff --git a/gcloud-java-compute/src/test/java/com/google/gcloud/compute/NetworkInterfaceTest.java b/gcloud-java-compute/src/test/java/com/google/gcloud/compute/NetworkInterfaceTest.java new file mode 100644 index 000000000000..22913937d0b1 --- /dev/null +++ b/gcloud-java-compute/src/test/java/com/google/gcloud/compute/NetworkInterfaceTest.java @@ -0,0 +1,179 @@ +/* + * Copyright 2016 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.gcloud.compute; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +import com.google.common.collect.ImmutableList; +import com.google.gcloud.compute.NetworkInterface.AccessConfig; +import com.google.gcloud.compute.NetworkInterface.AccessConfig.Type; + +import org.junit.Test; + +import java.util.List; + +public class NetworkInterfaceTest { + + private static final String NAME = "networkInterface"; + private static final NetworkId NETWORK = NetworkId.of("project", "network"); + private static final String NETWORK_IP = "192.168.1.1"; + private static final SubnetworkId SUBNETWORK = SubnetworkId.of("project", "region", "subnetwork"); + private static final AccessConfig ACCESS_CONFIG = AccessConfig.builder() + .name("accessConfig") + .natIp("192.168.1.1") + .type(Type.ONE_TO_ONE_NAT) + .build(); + private static final List ACCESS_CONFIGURATIONS = + ImmutableList.of(ACCESS_CONFIG); + private static final NetworkInterface NETWORK_INTERFACE = NetworkInterface.builder(NETWORK) + .name(NAME) + .networkIp(NETWORK_IP) + .subnetwork(SUBNETWORK) + .accessConfigurations(ACCESS_CONFIGURATIONS) + .build(); + + @Test + public void testAccessConfigToBuilder() { + AccessConfig accessConfig = ACCESS_CONFIG.toBuilder().name("newName").build(); + assertEquals("newName", accessConfig.name()); + compareAccessConfig(ACCESS_CONFIG, accessConfig.toBuilder().name("accessConfig").build()); + } + + @Test + public void testAccessConfigToBuilderIncomplete() { + AccessConfig accessConfig = AccessConfig.of(); + compareAccessConfig(accessConfig, accessConfig.toBuilder().build()); + } + + @Test + public void testToBuilder() { + compareNetworkInterface(NETWORK_INTERFACE, NETWORK_INTERFACE.toBuilder().build()); + NetworkInterface networkInterface = NETWORK_INTERFACE.toBuilder().name("newInterface").build(); + assertEquals("newInterface", networkInterface.name()); + networkInterface = networkInterface.toBuilder().name(NAME).build(); + compareNetworkInterface(NETWORK_INTERFACE, networkInterface); + } + + @Test + public void testToBuilderIncomplete() { + NetworkInterface networkInterface = NetworkInterface.of(NETWORK); + assertEquals(networkInterface, networkInterface.toBuilder().build()); + networkInterface = NetworkInterface.of(NETWORK.network()); + assertEquals(networkInterface, networkInterface.toBuilder().build()); + } + + @Test + public void testAccessConfigBuilder() { + assertEquals("accessConfig", ACCESS_CONFIG.name()); + assertEquals("192.168.1.1", ACCESS_CONFIG.natIp()); + assertEquals(Type.ONE_TO_ONE_NAT, ACCESS_CONFIG.type()); + } + + @Test + public void testBuilder() { + assertEquals(NAME, NETWORK_INTERFACE.name()); + assertEquals(NETWORK, NETWORK_INTERFACE.network()); + assertEquals(NETWORK_IP, NETWORK_INTERFACE.networkIp()); + assertEquals(SUBNETWORK, NETWORK_INTERFACE.subnetwork()); + assertEquals(ACCESS_CONFIGURATIONS, NETWORK_INTERFACE.accessConfigurations()); + NetworkInterface networkInterface = NetworkInterface.builder("network") + .name(NAME) + .networkIp(NETWORK_IP) + .subnetwork(SUBNETWORK) + .accessConfigurations(ACCESS_CONFIG) + .build(); + assertEquals(NAME, networkInterface.name()); + assertEquals(NetworkId.of("network"), networkInterface.network()); + assertEquals(NETWORK_IP, networkInterface.networkIp()); + assertEquals(SUBNETWORK, networkInterface.subnetwork()); + assertEquals(ACCESS_CONFIGURATIONS, networkInterface.accessConfigurations()); + } + + @Test + public void testAccessConfigOf() { + AccessConfig accessConfig = AccessConfig.of("192.168.1.1"); + assertNull(accessConfig.name()); + assertEquals("192.168.1.1", accessConfig.natIp()); + assertNull(accessConfig.type()); + accessConfig = AccessConfig.of(); + assertNull(accessConfig.name()); + assertNull(accessConfig.natIp()); + assertNull(accessConfig.type()); + } + + @Test + public void testOf() { + NetworkInterface networkInterface = NetworkInterface.of(NETWORK); + assertNull(networkInterface.name()); + assertEquals(NETWORK, networkInterface.network()); + assertNull(networkInterface.networkIp()); + assertNull(networkInterface.subnetwork()); + networkInterface = NetworkInterface.of(NETWORK.network()); + assertNull(networkInterface.name()); + assertNull(networkInterface.network().project()); + assertEquals(NETWORK.network(), networkInterface.network().network()); + assertNull(networkInterface.networkIp()); + assertNull(networkInterface.subnetwork()); + } + + @Test + public void testAccessConfigToAndFromPb() { + AccessConfig accessConfig = AccessConfig.fromPb(ACCESS_CONFIG.toPb()); + compareAccessConfig(ACCESS_CONFIG, accessConfig); + accessConfig = AccessConfig.of(); + compareAccessConfig(accessConfig, AccessConfig.fromPb(accessConfig.toPb())); + } + + @Test + public void testToAndFromPb() { + NetworkInterface networkInterface = NetworkInterface.fromPb(NETWORK_INTERFACE.toPb()); + compareNetworkInterface(NETWORK_INTERFACE, networkInterface); + networkInterface = NetworkInterface.of(NETWORK); + compareNetworkInterface(networkInterface, NetworkInterface.fromPb(networkInterface.toPb())); + } + + @Test + public void testSetProjectId() { + NetworkInterface networkInterface = NetworkInterface.of(NETWORK); + compareNetworkInterface(networkInterface, + NetworkInterface.of(NetworkId.of("network")).setProjectId("project")); + networkInterface = NETWORK_INTERFACE.toBuilder() + .network(NetworkId.of("network")) + .subnetwork(SubnetworkId.of("region", "subnetwork")) + .build(); + compareNetworkInterface(NETWORK_INTERFACE, networkInterface.setProjectId("project")); + } + + public void compareAccessConfig(AccessConfig expected, AccessConfig value) { + assertEquals(expected, value); + assertEquals(expected.name(), value.name()); + assertEquals(expected.natIp(), value.natIp()); + assertEquals(expected.type(), value.type()); + assertEquals(expected.hashCode(), value.hashCode()); + } + + public void compareNetworkInterface(NetworkInterface expected, NetworkInterface value) { + assertEquals(expected, value); + assertEquals(expected.name(), value.name()); + assertEquals(expected.network(), value.network()); + assertEquals(expected.networkIp(), value.networkIp()); + assertEquals(expected.subnetwork(), value.subnetwork()); + assertEquals(expected.accessConfigurations(), value.accessConfigurations()); + assertEquals(expected.hashCode(), value.hashCode()); + } +} diff --git a/gcloud-java-compute/src/test/java/com/google/gcloud/compute/SerializationTest.java b/gcloud-java-compute/src/test/java/com/google/gcloud/compute/SerializationTest.java index 2e5dbdca6ceb..7ab0ff597222 100644 --- a/gcloud-java-compute/src/test/java/com/google/gcloud/compute/SerializationTest.java +++ b/gcloud-java-compute/src/test/java/com/google/gcloud/compute/SerializationTest.java @@ -22,6 +22,7 @@ import com.google.common.collect.ImmutableList; import com.google.gcloud.AuthCredentials; import com.google.gcloud.RetryParams; +import com.google.gcloud.compute.NetworkInterface.AccessConfig; import org.junit.Test; @@ -171,6 +172,10 @@ public class SerializationTest { NetworkInfo.of(NETWORK_ID, STANDARD_NETWORK_CONFIGURATION); private static final Network NETWORK = new Network.Builder(COMPUTE, NETWORK_ID, STANDARD_NETWORK_CONFIGURATION).build(); + private static final AccessConfig ACCESS_CONFIG = AccessConfig.of("192.168.1.1"); + private static final NetworkInterface NETWORK_INTERFACE = NetworkInterface.builder(NETWORK_ID) + .accessConfigurations(ACCESS_CONFIG) + .build(); private static final Compute.DiskTypeOption DISK_TYPE_OPTION = Compute.DiskTypeOption.fields(); private static final Compute.DiskTypeFilter DISK_TYPE_FILTER = @@ -272,11 +277,11 @@ public void testModelAndRequests() throws Exception { STANDARD_DISK_CONFIGURATION, IMAGE_DISK_CONFIGURATION, SNAPSHOT_DISK_CONFIGURATION, DISK_INFO, DISK, SUBNETWORK_ID, NETWORK_ID, SUBNETWORK_INFO, SUBNETWORK, STANDARD_NETWORK_CONFIGURATION, SUBNET_NETWORK_CONFIGURATION, NETWORK_INFO, NETWORK, - DISK_TYPE_OPTION, DISK_TYPE_FILTER, DISK_TYPE_LIST_OPTION, DISK_TYPE_AGGREGATED_LIST_OPTION, - MACHINE_TYPE_OPTION, MACHINE_TYPE_FILTER, MACHINE_TYPE_LIST_OPTION, - MACHINE_TYPE_AGGREGATED_LIST_OPTION, REGION_OPTION, REGION_FILTER, REGION_LIST_OPTION, - ZONE_OPTION, ZONE_FILTER, ZONE_LIST_OPTION, LICENSE_OPTION, OPERATION_OPTION, - OPERATION_FILTER, OPERATION_LIST_OPTION, ADDRESS_OPTION, ADDRESS_FILTER, + ACCESS_CONFIG, NETWORK_INTERFACE, DISK_TYPE_OPTION, DISK_TYPE_FILTER, DISK_TYPE_LIST_OPTION, + DISK_TYPE_AGGREGATED_LIST_OPTION, MACHINE_TYPE_OPTION, MACHINE_TYPE_FILTER, + MACHINE_TYPE_LIST_OPTION, MACHINE_TYPE_AGGREGATED_LIST_OPTION, REGION_OPTION, REGION_FILTER, + REGION_LIST_OPTION, ZONE_OPTION, ZONE_FILTER, ZONE_LIST_OPTION, LICENSE_OPTION, + OPERATION_OPTION, OPERATION_FILTER, OPERATION_LIST_OPTION, ADDRESS_OPTION, ADDRESS_FILTER, ADDRESS_LIST_OPTION, ADDRESS_AGGREGATED_LIST_OPTION, SNAPSHOT_OPTION, SNAPSHOT_FILTER, SNAPSHOT_LIST_OPTION, IMAGE_OPTION, IMAGE_FILTER, IMAGE_LIST_OPTION, DISK_OPTION, DISK_FILTER, DISK_LIST_OPTION, DISK_AGGREGATED_LIST_OPTION, SUBNETWORK_OPTION,