http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/functions/InstanceToNodeMetadataTest.java
----------------------------------------------------------------------
diff --git 
a/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/functions/InstanceToNodeMetadataTest.java
 
b/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/functions/InstanceToNodeMetadataTest.java
new file mode 100644
index 0000000..2cefe83
--- /dev/null
+++ 
b/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/functions/InstanceToNodeMetadataTest.java
@@ -0,0 +1,249 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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.aliyun.ecs.compute.functions;
+
+import com.google.common.base.Supplier;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.inject.Guice;
+import org.jclouds.aliyun.ecs.domain.DedicatedHostAttribute;
+import org.jclouds.aliyun.ecs.domain.EipAddress;
+import org.jclouds.aliyun.ecs.domain.Instance;
+import org.jclouds.aliyun.ecs.domain.NetworkInterface;
+import org.jclouds.aliyun.ecs.domain.Tag;
+import org.jclouds.aliyun.ecs.domain.VpcAttributes;
+import org.jclouds.aliyun.ecs.domain.internal.Regions;
+import org.jclouds.aliyun.ecs.domain.regionscoped.RegionAndId;
+import org.jclouds.compute.domain.Hardware;
+import org.jclouds.compute.domain.HardwareBuilder;
+import org.jclouds.compute.domain.Image;
+import org.jclouds.compute.domain.ImageBuilder;
+import org.jclouds.compute.domain.NodeMetadata;
+import org.jclouds.compute.domain.OperatingSystem;
+import org.jclouds.compute.domain.OsFamily;
+import org.jclouds.compute.domain.Processor;
+import org.jclouds.compute.functions.GroupNamingConvention;
+import org.jclouds.date.internal.SimpleDateFormatDateService;
+import org.jclouds.domain.Location;
+import org.jclouds.domain.LocationBuilder;
+import org.jclouds.domain.LocationScope;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+
+@Test(groups = "unit", testName = "InstanceToNodeMetadataTest")
+public class InstanceToNodeMetadataTest {
+
+   private InstanceToNodeMetadata instanceToNodeMetadata;
+   private Image image;
+   private Hardware hardware;
+   private Location location;
+   private Instance instance;
+   private OperatingSystem os;
+   private Map<String, List<Tag>> tags;
+
+   private String imageId = "centos_6_09_64_20G_alibase_20180326.vhd";
+   private String hardwareId = "ecs.t1.xsmall";
+   private String regionId = Regions.EU_CENTRAL_1.getName();
+
+   @BeforeMethod
+   public void setUp() {
+
+      location = new LocationBuilder().id(regionId)
+              .description(Regions.EU_CENTRAL_1.getDescription())
+              .scope(LocationScope.PROVIDER)
+              .build();
+      Supplier<Set<? extends Location>> locations = new Supplier<Set<? extends 
Location>>() {
+         @Override
+         public Set<? extends Location> get() {
+            return ImmutableSet.of(location);
+         }
+      };
+
+      GroupNamingConvention.Factory namingConvention = 
Guice.createInjector().getInstance(GroupNamingConvention.Factory.class);
+
+      hardware = new HardwareBuilder()
+              .ids(hardwareId)
+              .name(hardwareId)
+              .ram(1024)
+              .processor(new Processor(1, 1d))
+              .location(location)
+              .build();
+
+      os = OperatingSystem.builder()
+              .description("CentOS 6.9 64bit")
+              .family(OsFamily.CENTOS)
+              .version("6.9")
+              .is64Bit(true)
+              .build();
+
+      image = new ImageBuilder()
+              .id(RegionAndId.slashEncodeRegionAndId(regionId, imageId))
+              .providerId(imageId)
+              .name("CentOS  6.9 64位")
+              .description("")
+              .operatingSystem(os)
+              .status(Image.Status.AVAILABLE)
+              .build();
+
+      tags = ImmutableMap.<String, List<Tag>>of("Tag", 
ImmutableList.of(Tag.create("hello", "")));
+
+      instance = Instance.builder()
+              .id("serverId")
+              .name("instanceName")
+              .regionId(regionId)
+              .imageId(imageId)
+              .instanceType(hardwareId)
+              .instanceTypeFamily("linux")
+              .vlanId("vlanId")
+              .eipAddress(EipAddress.create("ipAddress", "allocationId", 
EipAddress.InternetChargeType.ECS_INSTANCE))
+              .internetMaxBandwidthIn(1)
+              .zoneId("zoneId")
+              .internetChargeType(Instance.InternetChargeType.PAY_BY_TRAFFIC)
+              .spotStrategy("spotStrategy")
+              .stoppedMode("stoppedMode")
+              .serialNumber("serialNumber")
+              .ioOptimized(true)
+              .memory(1024)
+              .cpu(1)
+              .vpcAttributes(VpcAttributes.create("natIpAddress", 
ImmutableMap.<String, List<String>>of(), "vSwitchId", "vpcId"))
+              .internetMaxBandwidthOut(1)
+              .deviceAvailable(true)
+              .saleCycle("saleCycle")
+              .spotPriceLimit(1d)
+              .autoReleaseTime("")
+              .startTime(new 
SimpleDateFormatDateService().iso8601DateParse("2014-03-22T07:16:45.784120972Z"))
+              .description("desc")
+              .resourceGroupId("resourceGroupId")
+              .osType("osType")
+              .osName("osName")
+              .instanceNetworkType("instanceNetworkType")
+              .hostname("hostname")
+              .creationTime(new 
SimpleDateFormatDateService().iso8601DateParse("2014-03-22T05:16:45.784120972Z"))
+              .status(Instance.Status.RUNNING)
+              .clusterId("clusterId")
+              .recyclable(false)
+              .gpuSpec("")
+              .dedicatedHostAttribute(DedicatedHostAttribute.create("id", 
"name"))
+              .instanceChargeType("instanceChargeType")
+              .gpuAmount(1)
+              .expiredTime(new 
SimpleDateFormatDateService().iso8601DateParse("2014-03-22T09:16:45.784120972Z"))
+              .innerIpAddress(ImmutableMap.<String, 
List<String>>of("IpAddress", ImmutableList.of("192.168.0.1", "192.168.0.2")))
+              .publicIpAddress(ImmutableMap.<String, 
List<String>>of("IpAddress", ImmutableList.of("47.254.152.220", 
"47.254.153.230")))
+              .securityGroupIds(ImmutableMap.<String, List<String>>of())
+              .networkInterfaces(ImmutableMap.<String, 
List<NetworkInterface>>of())
+              .operationLocks(ImmutableMap.<String, List<String>>of())
+              .tags(tags)
+              .build();
+
+      Supplier<Map<String, ? extends Image>> images = new Supplier<Map<String, 
? extends Image>>() {
+         @Override
+         public Map<String, ? extends Image> get() {
+            return ImmutableMap.of(imageId, image);
+         }
+      };
+
+      Supplier<Map<String, ? extends Hardware>> hardwares = new 
Supplier<Map<String, ? extends Hardware>>() {
+         @Override
+         public Map<String, ? extends Hardware> get() {
+            return ImmutableMap.of(hardwareId, hardware);
+         }
+      };
+
+      instanceToNodeMetadata = new InstanceToNodeMetadata(images, hardwares, 
locations,
+              new InstanceStatusToStatus(), namingConvention);
+   }
+
+   @Test
+   public void testInstanceToNodeMetadata() {
+      NodeMetadata node = instanceToNodeMetadata.apply(instance);
+
+      List<String> privateIpAddresses = 
instance.innerIpAddress().entrySet().iterator().next().getValue();
+      List<String> publicIpAddresses = 
instance.publicIpAddress().entrySet().iterator().next().getValue();
+
+      assertNotNull(node);
+      assertEquals(node.getProviderId(), instance.id());
+      assertEquals(node.getName(), instance.name());
+      assertEquals(node.getHostname(), instance.hostname());
+      assertEquals(node.getGroup(), instance.name());
+      assertEquals(node.getHardware(), hardware);
+      assertEquals(node.getImageId(), 
RegionAndId.slashEncodeRegionAndId(regionId, imageId));
+      assertEquals(node.getOperatingSystem(), os);
+      assertEquals(node.getLocation(), location);
+      assertEquals(node.getImageId(), 
RegionAndId.slashEncodeRegionAndId(regionId, imageId));
+      assertEquals(node.getStatus(), NodeMetadata.Status.RUNNING);
+      assertEquals(node.getPrivateAddresses(), privateIpAddresses);
+      assertEquals(node.getPublicAddresses(), publicIpAddresses);
+      assertEquals(node.getTags(), ImmutableSet.of("hello"));
+   }
+
+   @Test
+   public void testInstanceWithInvalidHardwareToNodeMetadata() {
+      Instance instanceWithoutValidHardwareId = 
instance.toBuilder().instanceType("not.valid").build();
+      NodeMetadata node = 
instanceToNodeMetadata.apply(instanceWithoutValidHardwareId);
+
+      List<String> privateIpAddresses = 
instanceWithoutValidHardwareId.innerIpAddress().entrySet().iterator().next().getValue();
+      List<String> publicIpAddresses = 
instanceWithoutValidHardwareId.publicIpAddress().entrySet().iterator().next().getValue();
+
+      assertNotNull(node);
+      assertEquals(node.getProviderId(), instanceWithoutValidHardwareId.id());
+      assertEquals(node.getName(), instanceWithoutValidHardwareId.name());
+      assertEquals(node.getHostname(), 
instanceWithoutValidHardwareId.hostname());
+      assertEquals(node.getGroup(), instanceWithoutValidHardwareId.name());
+      assertEquals(node.getHardware(), null);
+      assertEquals(node.getImageId(), 
RegionAndId.slashEncodeRegionAndId(regionId, imageId));
+      assertEquals(node.getOperatingSystem(), os);
+      assertEquals(node.getLocation(), location);
+      assertEquals(node.getImageId(), 
RegionAndId.slashEncodeRegionAndId(regionId, imageId));
+      assertEquals(node.getStatus(), NodeMetadata.Status.RUNNING);
+      assertEquals(node.getPrivateAddresses(), privateIpAddresses);
+      assertEquals(node.getPublicAddresses(), publicIpAddresses);
+      assertEquals(node.getTags(), ImmutableSet.of("hello"));
+   }
+
+   @Test
+   public void testInstanceWithInvalidImageToNodeMetadata() {
+      Instance instanceWithoutValidHardwareId = 
instance.toBuilder().imageId("not.valid").build();
+      NodeMetadata node = 
instanceToNodeMetadata.apply(instanceWithoutValidHardwareId);
+
+      List<String> privateIpAddresses = 
instanceWithoutValidHardwareId.innerIpAddress().entrySet().iterator().next().getValue();
+      List<String> publicIpAddresses = 
instanceWithoutValidHardwareId.publicIpAddress().entrySet().iterator().next().getValue();
+
+      assertNotNull(node);
+      assertEquals(node.getProviderId(), instanceWithoutValidHardwareId.id());
+      assertEquals(node.getName(), instanceWithoutValidHardwareId.name());
+      assertEquals(node.getHostname(), 
instanceWithoutValidHardwareId.hostname());
+      assertEquals(node.getGroup(), instanceWithoutValidHardwareId.name());
+      assertEquals(node.getHardware(), hardware);
+      assertEquals(node.getImageId(), null);
+      assertEquals(node.getOperatingSystem(), null);
+      assertEquals(node.getImageId(), null);
+      assertEquals(node.getLocation(), location);
+      assertEquals(node.getStatus(), NodeMetadata.Status.RUNNING);
+      assertEquals(node.getPrivateAddresses(), privateIpAddresses);
+      assertEquals(node.getPublicAddresses(), publicIpAddresses);
+      assertEquals(node.getTags(), ImmutableSet.of("hello"));
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/internal/BaseECSComputeServiceApiLiveTest.java
----------------------------------------------------------------------
diff --git 
a/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/internal/BaseECSComputeServiceApiLiveTest.java
 
b/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/internal/BaseECSComputeServiceApiLiveTest.java
index f7b9526..c18d2b6 100644
--- 
a/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/internal/BaseECSComputeServiceApiLiveTest.java
+++ 
b/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/internal/BaseECSComputeServiceApiLiveTest.java
@@ -16,19 +16,33 @@
  */
 package org.jclouds.aliyun.ecs.compute.internal;
 
+import com.google.common.base.Predicate;
 import com.google.inject.Injector;
+import com.google.inject.Key;
 import com.google.inject.Module;
+import com.google.inject.TypeLiteral;
+import com.google.inject.name.Names;
 import org.jclouds.aliyun.ecs.ECSComputeServiceApi;
+import org.jclouds.aliyun.ecs.domain.internal.Regions;
 import org.jclouds.apis.BaseApiLiveTest;
 import org.jclouds.compute.config.ComputeServiceProperties;
 
 import java.util.Properties;
 import java.util.concurrent.TimeUnit;
 
+import static 
org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_RUNNING;
+import static 
org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_SUSPENDED;
+
 public class BaseECSComputeServiceApiLiveTest extends 
BaseApiLiveTest<ECSComputeServiceApi> {
 
+   protected static final String TEST_REGION = 
System.getProperty("test.alibaba-ecs.region", Regions.EU_CENTRAL_1.getName());
+   protected static final String TEST_ZONE = 
System.getProperty("test.alibaba-ecs.zone", TEST_REGION + "a");
+
+   protected Predicate<String> instanceRunningPredicate;
+   protected Predicate<String> instanceSuspendedPredicate;
+
    public BaseECSComputeServiceApiLiveTest() {
-      provider = "aliyun-ecs";
+      provider = "alibaba-ecs";
    }
 
    @Override
@@ -43,6 +57,12 @@ public class BaseECSComputeServiceApiLiveTest extends 
BaseApiLiveTest<ECSCompute
    @Override
    protected ECSComputeServiceApi create(Properties props, Iterable<Module> 
modules) {
       Injector injector = 
newBuilder().modules(modules).overrides(props).buildInjector();
+
+      instanceRunningPredicate = injector.getInstance(Key.get(new 
TypeLiteral<Predicate<String>>() {
+      }, Names.named(TIMEOUT_NODE_RUNNING)));
+      instanceSuspendedPredicate = injector.getInstance(Key.get(new 
TypeLiteral<Predicate<String>>() {
+      }, Names.named(TIMEOUT_NODE_SUSPENDED)));
+
       return injector.getInstance(ECSComputeServiceApi.class);
    }
 

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/internal/BaseECSComputeServiceApiMockTest.java
----------------------------------------------------------------------
diff --git 
a/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/internal/BaseECSComputeServiceApiMockTest.java
 
b/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/internal/BaseECSComputeServiceApiMockTest.java
index dd3938d..e25b08f 100644
--- 
a/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/internal/BaseECSComputeServiceApiMockTest.java
+++ 
b/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/internal/BaseECSComputeServiceApiMockTest.java
@@ -29,6 +29,7 @@ import com.squareup.okhttp.mockwebserver.RecordedRequest;
 import org.jclouds.ContextBuilder;
 import org.jclouds.aliyun.ecs.ECSComputeServiceApi;
 import org.jclouds.aliyun.ecs.ECSComputeServiceProviderMetadata;
+import org.jclouds.aliyun.ecs.domain.internal.Regions;
 import org.jclouds.concurrent.config.ExecutorServiceModule;
 import org.jclouds.json.Json;
 import org.jclouds.rest.ApiContext;
@@ -48,6 +49,8 @@ import static org.testng.Assert.assertTrue;
 public class BaseECSComputeServiceApiMockTest {
 
    private static final String DEFAULT_ENDPOINT = new 
ECSComputeServiceProviderMetadata().getEndpoint();
+   protected static final String TEST_REGION = Regions.EU_CENTRAL_1.getName();
+   protected static final String TEST_ZONE = TEST_REGION + "a";
 
    private final Set<Module> modules = ImmutableSet.<Module>of(new 
ExecutorServiceModule(newDirectExecutorService()));
    protected MockWebServer server;
@@ -59,7 +62,7 @@ public class BaseECSComputeServiceApiMockTest {
    public void start() throws IOException {
       server = new MockWebServer();
       server.play();
-      ctx = ContextBuilder.newBuilder("aliyun-ecs").credentials("user", 
"password").endpoint(url("")).modules(modules)
+      ctx = ContextBuilder.newBuilder("alibaba-ecs").credentials("user", 
"password").endpoint(url("")).modules(modules)
             .overrides(overrides()).build();
       json = ctx.utils().injector().getInstance(Json.class);
       api = ctx.getApi();

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/strategy/CreateResourcesThenCreateNodesTest.java
----------------------------------------------------------------------
diff --git 
a/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/strategy/CreateResourcesThenCreateNodesTest.java
 
b/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/strategy/CreateResourcesThenCreateNodesTest.java
new file mode 100644
index 0000000..4bff6d3
--- /dev/null
+++ 
b/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/strategy/CreateResourcesThenCreateNodesTest.java
@@ -0,0 +1,395 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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.aliyun.ecs.compute.strategy;
+
+import com.google.common.collect.ArrayListMultimap;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Lists;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import org.easymock.EasyMock;
+import org.jclouds.aliyun.ecs.ECSComputeServiceApi;
+import org.jclouds.aliyun.ecs.compute.options.ECSServiceTemplateOptions;
+import org.jclouds.aliyun.ecs.domain.IpProtocol;
+import org.jclouds.aliyun.ecs.domain.KeyPairRequest;
+import org.jclouds.aliyun.ecs.domain.Permission;
+import org.jclouds.aliyun.ecs.domain.Request;
+import org.jclouds.aliyun.ecs.domain.ResourceInfo;
+import org.jclouds.aliyun.ecs.domain.ResourceType;
+import org.jclouds.aliyun.ecs.domain.SecurityGroup;
+import org.jclouds.aliyun.ecs.domain.SecurityGroupRequest;
+import org.jclouds.aliyun.ecs.domain.Tag;
+import org.jclouds.aliyun.ecs.domain.VPCRequest;
+import org.jclouds.aliyun.ecs.domain.VSwitch;
+import org.jclouds.aliyun.ecs.domain.VSwitchRequest;
+import org.jclouds.aliyun.ecs.domain.Zone;
+import org.jclouds.aliyun.ecs.domain.internal.PaginatedCollection;
+import org.jclouds.aliyun.ecs.domain.internal.Regions;
+import org.jclouds.aliyun.ecs.domain.options.CreateSecurityGroupOptions;
+import org.jclouds.aliyun.ecs.domain.options.CreateVPCOptions;
+import org.jclouds.aliyun.ecs.domain.options.CreateVSwitchOptions;
+import org.jclouds.aliyun.ecs.domain.options.ListVSwitchesOptions;
+import org.jclouds.aliyun.ecs.domain.options.TagOptions;
+import org.jclouds.aliyun.ecs.features.RegionAndZoneApi;
+import org.jclouds.aliyun.ecs.features.SecurityGroupApi;
+import org.jclouds.aliyun.ecs.features.SshKeyPairApi;
+import org.jclouds.aliyun.ecs.features.TagApi;
+import org.jclouds.aliyun.ecs.features.VPCApi;
+import org.jclouds.aliyun.ecs.features.VSwitchApi;
+import org.jclouds.collect.IterableWithMarkers;
+import org.jclouds.collect.PagedIterables;
+import org.jclouds.compute.config.CustomizationResponse;
+import org.jclouds.compute.domain.NodeMetadata;
+import org.jclouds.compute.domain.Template;
+import org.jclouds.compute.functions.GroupNamingConvention;
+import org.jclouds.compute.reference.ComputeServiceConstants;
+import org.jclouds.compute.strategy.CreateNodeWithGroupEncodedIntoName;
+import 
org.jclouds.compute.strategy.CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap;
+import org.jclouds.compute.strategy.ListNodesStrategy;
+import org.jclouds.domain.Location;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+
+import static org.easymock.EasyMock.anyString;
+import static org.easymock.EasyMock.createNiceMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMockSupport.injectMocks;
+import static 
org.jclouds.aliyun.ecs.compute.strategy.CreateResourcesThenCreateNodes.DEFAULT_CIDR_BLOCK;
+import static 
org.jclouds.aliyun.ecs.compute.strategy.CreateResourcesThenCreateNodes.DEFAULT_DESCRIPTION_SUFFIX;
+import static 
org.jclouds.aliyun.ecs.compute.strategy.CreateResourcesThenCreateNodes.VSWITCH_PREFIX;
+import static org.testng.AssertJUnit.assertEquals;
+
+/**
+ *
+ * User can specify security group and vSwitch.
+ * 1. security group and vSwitch
+ * 2. only security group  -> impossible to determine which vSwitch the user 
wants to use or create
+ * 3. only vswitch ID -> create a securitygroup in the same vpc
+ * 4. none of them -> create vpc, vswitch and securitygroup
+ *
+ * Case 1 is tested with testExecuteWithSecurityGroupsVSwitchId
+ * Case 2 testExecuteOnlySecurityGroup
+ * Case 3 is tested with testExecuteOnlyVSwitchId
+ * Case 4 is tested with testExecuteNoSecurityGroupsVSwitchId
+ */
+@Test(groups = "unit", testName = "CreateResourcesThenCreateNodesTest")
+public class CreateResourcesThenCreateNodesTest {
+
+   private CreateResourcesThenCreateNodes createResourcesThenCreateNodes;
+   private SecurityGroupApi securityGroupApi;
+   private VSwitchApi vSwitchApi;
+   private TagApi tagApi;
+   private SshKeyPairApi sshKeyPairApi;
+   private VPCApi vpcApi;
+   private RegionAndZoneApi regionAndZoneApi;
+   private ECSComputeServiceApi api;
+   private Template template;
+   private ECSServiceTemplateOptions templateOptions;
+   private CreateNodeWithGroupEncodedIntoName addNodeWithGroupStrategy;
+   private ListNodesStrategy listNodesStrategy;
+   private GroupNamingConvention.Factory factory;
+   private GroupNamingConvention namingConvention;
+   private ListeningExecutorService userExecutor;
+   private CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap.Factory 
customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory;
+   private ComputeServiceConstants.Timeouts timeouts;
+   private Location location;
+   private String regionId;
+   private SecurityGroup securityGroup;
+   private Permission permission;
+   private VSwitch vswitch;
+   private Zone zone;
+
+   @BeforeMethod
+   public void setUp() {
+      securityGroupApi = EasyMock.createMock(SecurityGroupApi.class);
+      vSwitchApi = EasyMock.createMock(VSwitchApi.class);
+      tagApi = EasyMock.createMock(TagApi.class);
+      sshKeyPairApi = EasyMock.createMock(SshKeyPairApi.class);
+      vpcApi = EasyMock.createMock(VPCApi.class);
+      regionAndZoneApi = EasyMock.createMock(RegionAndZoneApi.class);
+      api = EasyMock.createMock(ECSComputeServiceApi.class);
+      template = EasyMock.createNiceMock(Template.class);
+      addNodeWithGroupStrategy = 
EasyMock.createNiceMock(CreateNodeWithGroupEncodedIntoName.class);
+      listNodesStrategy = EasyMock.createNiceMock(ListNodesStrategy.class);
+      factory = EasyMock.createNiceMock(GroupNamingConvention.Factory.class);
+      namingConvention = EasyMock.createNiceMock(GroupNamingConvention.class);
+
+      userExecutor = EasyMock.createNiceMock(ListeningExecutorService.class);
+      customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory = EasyMock
+            
.createNiceMock(CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap.Factory.class);
+      location = createNiceMock(Location.class);
+      templateOptions = new ECSServiceTemplateOptions();
+      regionId = Regions.EU_CENTRAL_1.getName();
+
+      timeouts = new ComputeServiceConstants.Timeouts();
+
+      createResourcesThenCreateNodes = new 
CreateResourcesThenCreateNodes(addNodeWithGroupStrategy,
+            listNodesStrategy, factory, userExecutor,
+            customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory, api);
+
+      permission = Permission.create(
+              "",
+              "",
+              "",
+              Permission.NicType.INTERNET,
+              "",
+              "",
+              "",
+              Permission.Direction.ALL,
+              "",
+              IpProtocol.ALL,
+              "",
+         Permission.Policy.ACCEPT,
+              new Date(),
+              "",
+              "",
+              ""
+              );
+
+      zone = Zone.create("id",
+              "localName",
+              ImmutableMap.<String, List<Object>>of(),
+              ImmutableMap.<String, List<String>>of(),
+              ImmutableMap.<String, List<String>>of(),
+              ImmutableMap.<String, List<ResourceInfo>>of(),
+              ImmutableMap.<String, List<String>>of(),
+              ImmutableMap.<String, List<String>>of(),
+              ImmutableMap.<String, List<String>>of()
+              );
+
+      injectMocks(api);
+      injectMocks(template);
+      injectMocks(securityGroupApi);
+      injectMocks(vSwitchApi);
+      injectMocks(tagApi);
+      injectMocks(sshKeyPairApi);
+      injectMocks(vpcApi);
+      injectMocks(regionAndZoneApi);
+
+      expect(template.getLocation()).andReturn(location).anyTimes();
+      expect(location.getId()).andReturn(regionId).anyTimes();
+
+      expect(api.securityGroupApi()).andReturn(securityGroupApi).anyTimes();
+      expect(api.vSwitchApi()).andReturn(vSwitchApi).anyTimes();
+      expect(api.tagApi()).andReturn(tagApi).anyTimes();
+      expect(api.sshKeyPairApi()).andReturn(sshKeyPairApi).anyTimes();
+      expect(api.vpcApi()).andReturn(vpcApi).anyTimes();
+      expect(api.regionAndZoneApi()).andReturn(regionAndZoneApi).anyTimes();
+   }
+
+
+   @Test
+   public void testExecuteWithSecurityGroupsVSwitchId() {
+      String vpcId = "vpc-1";
+      String vSwitchId = "vs-1";
+      String securityGroupId = "sg-1";
+      securityGroup = createSecurityGroup(securityGroupId, vpcId);
+      vswitch = createVSwitch(vSwitchId, vpcId);
+
+      templateOptions.vSwitchId(vSwitchId).securityGroups(securityGroupId);
+
+      expect(template.getOptions()).andReturn(templateOptions).anyTimes();
+
+      expect(securityGroupApi.list(regionId))
+              
.andReturn(PagedIterables.onlyPage(IterableWithMarkers.from(Lists.newArrayList(securityGroup))));
+
+      expect(securityGroupApi.get(regionId, securityGroupId))
+              .andReturn(Lists.newArrayList(permission));
+
+      // found VSwitch specified by user in VPC_PREFIX
+      expect(vSwitchApi.list(regionId, 
ListVSwitchesOptions.Builder.vSwitchId(vSwitchId).vpcId(vpcId)))
+              .andReturn(new PaginatedCollection(ImmutableMap.<String, 
Iterable<VSwitch>>of("VSwitch", Lists.<VSwitch> newArrayList(vswitch)), 1, 1, 
1, regionId, "requestId"));
+
+      expect(factory.create()).andReturn(namingConvention).anyTimes();
+      
expect(namingConvention.sharedNameForGroup(anyString())).andReturn("group").anyTimes();
+      
expect(namingConvention.uniqueNameForGroup(anyString())).andReturn("prefix").anyTimes();
+
+      expect(securityGroupApi.create(regionId, 
CreateSecurityGroupOptions.Builder.securityGroupName("group").vpcId(vpcId)))
+              .andReturn(new SecurityGroupRequest("requestId", 
securityGroupId)).anyTimes();
+      expect(securityGroupApi.addInboundRule(regionId, securityGroupId, 
IpProtocol.TCP, "22/22", "0.0.0.0/0"))
+              .andReturn(new Request("requestId")).anyTimes();
+      expect(tagApi.add(regionId, securityGroupId, ResourceType.SECURITYGROUP,
+              TagOptions.Builder.tag(1,  Tag.DEFAULT_OWNER_KEY, 
Tag.DEFAULT_OWNER_VALUE).tag(2, Tag.GROUP, "group"))
+      ).andReturn(new Request("requestId")).anyTimes();
+      expect(sshKeyPairApi.create(regionId, "prefix"))
+              .andReturn(new KeyPairRequest("requestId", "name", 
"fingerPrint", "body")).anyTimes();
+
+      replay(securityGroupApi, vSwitchApi, tagApi, sshKeyPairApi, vpcApi, 
regionAndZoneApi, api, factory, namingConvention, template, location);
+
+      executeAndAssert(vSwitchId, securityGroupId);
+   }
+
+   @Test(dependsOnMethods = "testExecuteWithSecurityGroupsVSwitchId")
+   public void testExecuteNoSecurityGroupsNoVSwitchId() {
+      String vpcId = "vpc-1";
+      String vSwitchId = "vs-1";
+      String securityGroupId = "sg-1";
+
+      vswitch = createVSwitch(vSwitchId, vpcId);
+
+      expect(template.getOptions()).andReturn(templateOptions).anyTimes();
+
+      expect(securityGroupApi.list(regionId))
+      
.andReturn(PagedIterables.onlyPage(IterableWithMarkers.from(Lists.<SecurityGroup>newArrayList())));
+
+      expect(vSwitchApi.list(regionId))
+              
.andReturn(PagedIterables.onlyPage(IterableWithMarkers.from(Lists.<VSwitch>newArrayList())));
+
+      
expect(regionAndZoneApi.describeZones(regionId)).andReturn(ImmutableList.of(zone));
+      expect(vpcApi.create(regionId, 
CreateVPCOptions.Builder.vpcName(anyString()).description(anyString()))).andReturn(new
 VPCRequest("reqId", "routeId", "vRoutId", vpcId));
+
+      String vSwitchName = String.format("%s-%s", VSWITCH_PREFIX, "group");
+      String vSwitchDescription = String.format("%s - %s", vSwitchName, 
DEFAULT_DESCRIPTION_SUFFIX);
+      expect(vSwitchApi.create(zone.id(), DEFAULT_CIDR_BLOCK, vpcId,
+              
CreateVSwitchOptions.Builder.vSwitchName(vSwitchName).description(vSwitchDescription))).andReturn(new
 VSwitchRequest("reqId", vSwitchId));
+
+      expect(factory.create()).andReturn(namingConvention).anyTimes();
+      
expect(namingConvention.sharedNameForGroup(anyString())).andReturn("group").anyTimes();
+      
expect(namingConvention.uniqueNameForGroup(anyString())).andReturn("prefix").anyTimes();
+
+      expect(securityGroupApi.create(regionId, 
CreateSecurityGroupOptions.Builder.securityGroupName("group").vpcId(vpcId)))
+              .andReturn(new SecurityGroupRequest("requestId", 
securityGroupId)).anyTimes();
+      expect(securityGroupApi.addInboundRule(regionId, securityGroupId, 
IpProtocol.TCP, "22/22", "0.0.0.0/0")).andReturn(new 
Request("requestId")).anyTimes();
+      expect(tagApi.add(regionId, securityGroupId, ResourceType.SECURITYGROUP,
+              TagOptions.Builder.tag(1,  Tag.DEFAULT_OWNER_KEY, 
Tag.DEFAULT_OWNER_VALUE).tag(2, Tag.GROUP, "group"))
+      ).andReturn(new Request("requestId")).anyTimes();
+      expect(sshKeyPairApi.create(regionId, "prefix")).andReturn(new 
KeyPairRequest("requestId", "name", "fingerPrint", "body")).anyTimes();
+
+      replay(securityGroupApi, vSwitchApi, tagApi, sshKeyPairApi, vpcApi, 
regionAndZoneApi, api, factory, namingConvention, template, location);
+
+      executeAndAssert(vSwitchId, securityGroupId);
+   }
+
+   @Test(dependsOnMethods = "testExecuteNoSecurityGroupsNoVSwitchId", 
expectedExceptions = IllegalStateException.class)
+   public void testExecuteOnlySecurityGroup() {
+      String vpcId = "vpc-2";
+      String vSwitchId = "";
+      String securityGroupId = "sg-2";
+      templateOptions.vSwitchId(vSwitchId).securityGroups(securityGroupId);
+      securityGroup = createSecurityGroup(securityGroupId, vpcId);
+      vswitch = createVSwitch(vSwitchId, vpcId);
+
+      expect(template.getOptions()).andReturn(templateOptions).anyTimes();
+
+      expect(securityGroupApi.list(regionId))
+            
.andReturn(PagedIterables.onlyPage(IterableWithMarkers.from(Lists.newArrayList(securityGroup))));
+
+      expect(securityGroupApi.get(regionId, securityGroupId))
+            .andReturn(Lists.newArrayList(permission));
+
+      // at least a VSwitch is available in regionId
+      expect(vSwitchApi.list(regionId, 
ListVSwitchesOptions.Builder.vpcId(vpcId)))
+              .andReturn(new PaginatedCollection(ImmutableMap.of("VSwitch", 
Lists.newArrayList(vswitch)), 1, 1, 1, regionId, "requestId"));
+
+      expect(factory.create()).andReturn(namingConvention).anyTimes();
+      
expect(namingConvention.sharedNameForGroup(anyString())).andReturn("group").anyTimes();
+      
expect(namingConvention.uniqueNameForGroup(anyString())).andReturn("prefix").anyTimes();
+
+      expect(securityGroupApi.create(regionId, 
CreateSecurityGroupOptions.Builder.securityGroupName("group").vpcId(vpcId)))
+              .andReturn(new SecurityGroupRequest("requestId", 
securityGroupId)).anyTimes();
+      expect(securityGroupApi.addInboundRule(regionId, securityGroupId, 
IpProtocol.TCP, "22/22", "0.0.0.0/0"))
+              .andReturn(new Request("requestId")).anyTimes();
+      expect(tagApi.add(regionId, securityGroupId, ResourceType.SECURITYGROUP,
+              TagOptions.Builder.tag(1,  Tag.DEFAULT_OWNER_KEY, 
Tag.DEFAULT_OWNER_VALUE).tag(2, Tag.GROUP, "group"))
+      ).andReturn(new Request("requestId")).anyTimes();
+      expect(sshKeyPairApi.create(regionId, "prefix"))
+              .andReturn(new KeyPairRequest("requestId", "name", 
"fingerPrint", "body")).anyTimes();
+
+      replay(securityGroupApi, vSwitchApi, tagApi, sshKeyPairApi, vpcApi, 
regionAndZoneApi, api, factory, namingConvention, template, location);
+
+      executeAndAssert(vSwitchId, securityGroupId);
+   }
+
+   @Test(dependsOnMethods = "testExecuteOnlySecurityGroup")
+   public void testExecuteOnlyVSwitchId() {
+      String vpcId = "vpc-3";
+      String vSwitchId = "vs-3";
+      String securityGroupId = "sg-3";
+      vswitch = createVSwitch(vSwitchId, vpcId);
+
+      templateOptions.vSwitchId(vSwitchId).securityGroups(securityGroupId);
+
+      expect(template.getOptions()).andReturn(templateOptions).anyTimes();
+
+      expect(securityGroupApi.list(regionId))
+              
.andReturn(PagedIterables.onlyPage(IterableWithMarkers.from(Lists.<SecurityGroup>
 newArrayList())));
+
+      expect(securityGroupApi.get(regionId, securityGroupId))
+              .andReturn(Lists.newArrayList(permission));
+
+      // found VSwitch specified by user in VPC_PREFIX
+      expect(vSwitchApi.list(regionId, 
ListVSwitchesOptions.Builder.vSwitchId(vSwitchId)))
+              .andReturn(new PaginatedCollection(ImmutableMap.<String, 
Iterable<VSwitch>>of("VSwitch", Lists.<VSwitch> newArrayList(vswitch)), 1, 1, 
1, regionId, "requestId"));
+
+      expect(factory.create()).andReturn(namingConvention).anyTimes();
+      
expect(namingConvention.sharedNameForGroup(anyString())).andReturn("group").anyTimes();
+      
expect(namingConvention.uniqueNameForGroup(anyString())).andReturn("prefix").anyTimes();
+
+      expect(securityGroupApi.create(regionId, 
CreateSecurityGroupOptions.Builder.securityGroupName("group").vpcId(vpcId)))
+              .andReturn(new SecurityGroupRequest("requestId", 
securityGroupId)).anyTimes();
+      expect(securityGroupApi.addInboundRule(regionId, securityGroupId, 
IpProtocol.TCP, "22/22", "0.0.0.0/0"))
+              .andReturn(new Request("requestId")).anyTimes();
+      expect(tagApi.add(regionId, securityGroupId, ResourceType.SECURITYGROUP,
+              TagOptions.Builder.tag(1,  Tag.DEFAULT_OWNER_KEY, 
Tag.DEFAULT_OWNER_VALUE).tag(2, Tag.GROUP, "group"))
+      ).andReturn(new Request("requestId")).anyTimes();
+      expect(sshKeyPairApi.create(regionId, "prefix"))
+              .andReturn(new KeyPairRequest("requestId", "name", 
"fingerPrint", "body")).anyTimes();
+
+      replay(securityGroupApi, vSwitchApi, tagApi, sshKeyPairApi, vpcApi, 
regionAndZoneApi, api, factory, namingConvention, template, location);
+
+      executeAndAssert(vSwitchId, securityGroupId);
+   }
+
+   private void executeAndAssert(String vSwitchId, String securityGroupId) {
+      createResourcesThenCreateNodes.execute("group", 0, template, 
Collections.<NodeMetadata>emptySet(),
+              Collections.<NodeMetadata, Exception>emptyMap(),
+              ArrayListMultimap.<NodeMetadata, CustomizationResponse>create());
+
+      assertEquals(vSwitchId, templateOptions.getVSwitchId());
+      assertEquals(securityGroupId, 
templateOptions.getGroups().iterator().next());
+   }
+
+   private SecurityGroup createSecurityGroup(String securityGroupId, String 
vpcId) {
+      return SecurityGroup.create(
+              securityGroupId,
+              "",
+              "securityGroupName",
+              vpcId,
+              ImmutableMap.<String, List<Tag>>of()
+      );
+   }
+
+   private VSwitch createVSwitch(String vSwitchId, String vpcId) {
+      return VSwitch.create(
+              "",
+              new Date(),
+              "vSwitch",
+              "",
+              VSwitch.Status.AVAILABLE,
+              1,
+              vpcId,
+              vSwitchId,
+              ""
+      );
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/test/resources/availableZones.json
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/test/resources/availableZones.json 
b/aliyun-ecs/src/test/resources/availableZones.json
new file mode 100644
index 0000000..0b2e092
--- /dev/null
+++ b/aliyun-ecs/src/test/resources/availableZones.json
@@ -0,0 +1,423 @@
+{
+  "RequestId": "C51117E9-1989-4407-AAB6-5E3E433E9A75",
+  "AvailableZones": {
+    "AvailableZone": [
+      {
+        "Status": "Available",
+        "RegionId": "eu-central-1",
+        "AvailableResources": {
+          "AvailableResource": [
+            {
+              "Type": "InstanceType",
+              "SupportedResources": {
+                "SupportedResource": [
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.sn1ne.3xlarge"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.sn1ne.2xlarge"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.t5-c1m1.xlarge"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.se1ne.xlarge"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.t5-c1m4.xlarge"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.t5-c1m4.2xlarge"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.t5-lc1m2.large"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.hfg5.large"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.hfc5.3xlarge"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.hfg5.2xlarge"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.t5-c1m2.xlarge"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.t5-c1m1.2xlarge"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.sn2ne.xlarge"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.hfc5.2xlarge"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.t5-lc1m4.large"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.sn2ne.3xlarge"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.se1ne.2xlarge"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.se1ne.3xlarge"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.hfc5.large"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.hfg5.xlarge"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.hfc5.xlarge"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.t5-lc1m1.small"
+                  },
+                  {
+                    "Status": "SoldOut",
+                    "Value": "ecs.hfg5.3xlarge"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.t5-lc1m2.small"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.t5-c1m1.large"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.se1ne.large"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.t5-lc2m1.nano"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.sn1ne.xlarge"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.sn2ne.2xlarge"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.sn1ne.large"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.t5-c1m2.2xlarge"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.sn2ne.large"
+                  }
+                ]
+              }
+            }
+          ]
+        },
+        "ZoneId": "eu-central-1b"
+      },
+      {
+        "Status": "Available",
+        "RegionId": "eu-central-1",
+        "AvailableResources": {
+          "AvailableResource": [
+            {
+              "Type": "InstanceType",
+              "SupportedResources": {
+                "SupportedResource": [
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.sn1ne.3xlarge"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.n4.xlarge"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.sn1ne.2xlarge"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.t5-lc1m2.large"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.t5-c1m4.2xlarge"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.hfg5.large"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.hfc5.3xlarge"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.mn4.2xlarge"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.se1.2xlarge"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.i1.3xlarge"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.mn4.large"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.t5-c1m2.xlarge"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.e4.small"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.t5-c1m1.2xlarge"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.sn2ne.xlarge"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.hfg5.3xlarge"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.t5-lc1m4.large"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.mn4.xlarge"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.n4.small"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.i1.2xlarge"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.se1ne.2xlarge"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.sn2.large"
+                  },
+                  {
+                    "Status": "SoldOut",
+                    "Value": "ecs.ce4.2xlarge"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.hfc5.large"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.ce4.xlarge"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.hfg5.xlarge"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.mn4.small"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.hfc5.xlarge"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.t5-lc1m2.small"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.t5-c1m1.large"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.se1ne.large"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.d1.4xlarge"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.sn2ne.2xlarge"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.t5-c1m2.2xlarge"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.gn5-c4g1.2xlarge"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.sn1.large"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.se1ne.xlarge"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.t5-c1m1.xlarge"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.sn2.medium"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.t5-c1m4.xlarge"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.se1.xlarge"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.sn1.medium"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.n4.2xlarge"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.hfg5.2xlarge"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.gn5-c8g1.2xlarge"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.sn2.xlarge"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.hfc5.2xlarge"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.sn2ne.3xlarge"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.sn1.xlarge"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.i1.xlarge"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.se1ne.3xlarge"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.i2.xlarge"
+                  },
+                  {
+                    "Status": "SoldOut",
+                    "Value": "ecs.d1.3xlarge"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.xn4.small"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.t5-lc1m1.small"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.d1.2xlarge"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.t5-lc2m1.nano"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.i2.2xlarge"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.sn1ne.xlarge"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.gn5-c4g1.xlarge"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.se1.large"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.n4.large"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.sn1ne.large"
+                  },
+                  {
+                    "Status": "Available",
+                    "Value": "ecs.sn2ne.large"
+                  }
+                ]
+              }
+            }
+          ]
+        },
+        "ZoneId": "eu-central-1a"
+      }
+    ]
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/test/resources/instanceStatus.json
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/test/resources/instanceStatus.json 
b/aliyun-ecs/src/test/resources/instanceStatus.json
new file mode 100644
index 0000000..592ef16
--- /dev/null
+++ b/aliyun-ecs/src/test/resources/instanceStatus.json
@@ -0,0 +1,18 @@
+{
+  "PageNumber": 1,
+  "InstanceStatuses": {
+    "InstanceStatus": [
+      {
+        "Status": "Stopped",
+        "InstanceId": "i-gw8dvsswhc7iifle1hp7"
+      },
+      {
+        "Status": "Stopped",
+        "InstanceId": "i-gw8g25hfbxhyykn3jevq"
+      }
+    ]
+  },
+  "TotalCount": 2,
+  "PageSize": 10,
+  "RequestId": "BDE228AF-8B12-439B-8C1C-FB42CCEB4A65"
+}
\ No newline at end of file

Reply via email to