use of com.vmware.photon.controller.model.resources.SubnetService.SubnetState in project photon-model by vmware.
the class AWSSubnetTaskServiceTest method testCreateSubnetWithOutboundAccess.
@Test
public void testCreateSubnetWithOutboundAccess() throws Throwable {
// provision a "public" subnet first
SubnetState publicSubnetState = provisionSubnet(AWS_NON_EXISTING_PUBLIC_SUBNET_NAME, AWS_NON_EXISTING_PUBLIC_SUBNET_CIDR, null);
assertNotNull(publicSubnetState.id);
assertEquals(LifecycleState.READY, publicSubnetState.lifecycleState);
SubnetState subnetState = provisionSubnet(AWS_NON_EXISTING_SUBNET_NAME, AWS_NON_EXISTING_SUBNET_CIDR, publicSubnetState.documentSelfLink);
assertNotNull(subnetState.id);
assertEquals(LifecycleState.READY, subnetState.lifecycleState);
if (!this.isMock) {
// Verify that the subnet was created.
DescribeSubnetsRequest describeRequest = new DescribeSubnetsRequest().withSubnetIds(Collections.singletonList(subnetState.id));
List<Subnet> subnets = this.client.describeSubnets(describeRequest).getSubnets();
assertNotNull(subnets);
assertEquals(1, subnets.size());
// Verify that a NAT gateway was created
assertNotNull(subnetState.customProperties);
String natGatewayId = subnetState.customProperties.get(AWS_NAT_GATEWAY_ID);
String routeTableId = subnetState.customProperties.get(AWS_ROUTE_TABLE_ID);
String allocationId = subnetState.customProperties.get(AWS_ELASTIC_IP_ALLOCATION_ID);
assertNotNull(natGatewayId);
assertNotNull(routeTableId);
assertNotNull(allocationId);
DescribeNatGatewaysRequest describeNatGatewaysRequest = new DescribeNatGatewaysRequest().withNatGatewayIds(Collections.singletonList(natGatewayId));
List<NatGateway> natGateways = this.client.describeNatGateways(describeNatGatewaysRequest).getNatGateways();
assertNotNull(natGateways);
assertEquals(1, natGateways.size());
NatGateway natGateway = natGateways.get(0);
assertEquals(publicSubnetState.id, natGateway.getSubnetId());
assertNotNull(natGateway.getNatGatewayAddresses());
assertEquals(1, natGateway.getNatGatewayAddresses().size());
assertEquals(allocationId, natGateway.getNatGatewayAddresses().get(0).getAllocationId());
assertEquals("available", natGateways.get(0).getState());
// verify that a route table was created
DescribeRouteTablesRequest describeRouteTablesRequest = new DescribeRouteTablesRequest().withRouteTableIds(Collections.singletonList(routeTableId));
List<RouteTable> routeTables = this.client.describeRouteTables(describeRouteTablesRequest).getRouteTables();
assertNotNull(routeTables);
assertEquals(1, routeTables.size());
RouteTable routeTable = routeTables.get(0);
assertNotNull(routeTable.getAssociations());
assertEquals(1, routeTable.getAssociations().size());
assertEquals(subnetState.id, routeTable.getAssociations().get(0).getSubnetId());
assertNotNull(routeTable.getRoutes());
assertEquals(2, routeTable.getRoutes().size());
boolean hasRouteToNatGateway = false;
for (Route route : routeTable.getRoutes()) {
if (route.getDestinationCidrBlock().equals("0.0.0.0/0") && route.getNatGatewayId() != null && route.getNatGatewayId().equals(natGatewayId)) {
hasRouteToNatGateway = true;
break;
}
}
assertTrue(hasRouteToNatGateway);
// Verify that an IP address allocation was created
DescribeAddressesRequest describeAddressesRequest = new DescribeAddressesRequest().withAllocationIds(Collections.singletonList(allocationId));
List<Address> addresses = this.client.describeAddresses(describeAddressesRequest).getAddresses();
assertNotNull(addresses);
assertEquals(1, addresses.size());
}
// delete the subnet
kickOffSubnetProvision(InstanceRequestType.DELETE, subnetState, TaskStage.FINISHED);
if (!this.isMock) {
// Verify that the subnet was deleted.
DescribeSubnetsRequest describeRequest = new DescribeSubnetsRequest().withSubnetIds(Collections.singletonList(subnetState.id));
try {
this.client.describeSubnets(describeRequest).getSubnets();
fail("Subnet should not exist in AWS.");
} catch (AmazonEC2Exception ex) {
assertEquals(HttpResponseStatus.BAD_REQUEST.code(), ex.getStatusCode());
}
// Verify that the NAT gateway was deleted
String natGatewayId = subnetState.customProperties.get(AWS_NAT_GATEWAY_ID);
String routeTableId = subnetState.customProperties.get(AWS_ROUTE_TABLE_ID);
String allocationId = subnetState.customProperties.get(AWS_ELASTIC_IP_ALLOCATION_ID);
DescribeNatGatewaysRequest describeNatGatewaysRequest = new DescribeNatGatewaysRequest().withNatGatewayIds(Collections.singletonList(natGatewayId));
List<NatGateway> natGateways = this.client.describeNatGateways(describeNatGatewaysRequest).getNatGateways();
assertNotNull(natGateways);
assertEquals(1, natGateways.size());
assertEquals("deleted", natGateways.get(0).getState());
// Verify that the route table was deleted
DescribeRouteTablesRequest describeRouteTablesRequest = new DescribeRouteTablesRequest().withRouteTableIds(Collections.singletonList(routeTableId));
try {
this.client.describeRouteTables(describeRouteTablesRequest).getRouteTables();
fail("Route table should not exist in AWS.");
} catch (AmazonEC2Exception ex) {
assertEquals(HttpResponseStatus.BAD_REQUEST.code(), ex.getStatusCode());
}
DescribeAddressesRequest describeAddressesRequest = new DescribeAddressesRequest().withAllocationIds(Collections.singletonList(allocationId));
try {
this.client.describeAddresses(describeAddressesRequest).getAddresses();
fail("IP address allocation should not exist in AWS.");
} catch (AmazonEC2Exception ex) {
assertEquals(HttpResponseStatus.BAD_REQUEST.code(), ex.getStatusCode());
}
}
}
use of com.vmware.photon.controller.model.resources.SubnetService.SubnetState in project photon-model by vmware.
the class AWSInstanceContext method createSubnetsIfNotExist.
/**
* For every NIC create AWS Subnet (as specified by {@code AWSNicContext.subnetState}) if it
* does not exist.
*
* @see #getSubnets(AWSInstanceContext)
*/
private DeferredResult<AWSInstanceContext> createSubnetsIfNotExist(AWSInstanceContext context) {
if (context.nics.isEmpty()) {
return DeferredResult.completed(context);
}
List<DeferredResult<Void>> createSubnetDRs = new ArrayList<>();
for (AWSNicContext nicCtx : context.nics) {
if (nicCtx.subnet != null) {
// No need to create
continue;
}
// Create AWS subnet and set it to nicCtx.subnet {{
CreateSubnetRequest subnetRequest = new CreateSubnetRequest().withVpcId(nicCtx.vpc.getVpcId()).withCidrBlock(nicCtx.subnetState.subnetCIDR);
if (nicCtx.subnetState.zoneId != null) {
subnetRequest.withAvailabilityZone(nicCtx.subnetState.zoneId);
}
String msg = "Create AWS subnet + [" + nicCtx.subnetState.name + "]";
AWSDeferredResultAsyncHandler<CreateSubnetRequest, CreateSubnetResult> createAWSSubnet = new AWSDeferredResultAsyncHandler<CreateSubnetRequest, CreateSubnetResult>(this.service, msg) {
@Override
protected DeferredResult<CreateSubnetResult> consumeSuccess(CreateSubnetRequest request, CreateSubnetResult result) {
nicCtx.subnet = result.getSubnet();
AWSUtils.tagResourcesWithName(context.amazonEC2Client, nicCtx.subnetState.name, nicCtx.subnet.getSubnetId());
return DeferredResult.completed(result);
}
};
context.amazonEC2Client.createSubnetAsync(subnetRequest, createAWSSubnet);
// }}
// Once AWS subnet creation is done PATCH SubnetState.id {{
Function<CreateSubnetResult, DeferredResult<Void>> patchSubnetState = (ignore) -> {
SubnetState patchSubnet = new SubnetState();
patchSubnet.id = nicCtx.subnet.getSubnetId();
patchSubnet.documentSelfLink = nicCtx.subnetState.documentSelfLink;
patchSubnet.customProperties = singletonMap(CREATE_CONTEXT_PROP_NAME, context.computeRequest.resourceLink());
Operation op = Operation.createPatch(context.service.getHost(), patchSubnet.documentSelfLink).setBody(patchSubnet);
return context.service.sendWithDeferredResult(op, SubnetState.class).thenAccept(patchedSubnet -> nicCtx.subnetState = patchedSubnet);
};
// }}
// Chain AWS subnet creation with SubnetState patching
createSubnetDRs.add(createAWSSubnet.toDeferredResult().thenCompose(patchSubnetState));
}
return DeferredResult.allOf(createSubnetDRs).handle((all, exc) -> {
if (exc != null) {
String msg = String.format("Error creating Subnets in AWS for [%s] VM.", context.child.name);
throw new IllegalStateException(msg, exc);
}
return context;
});
}
use of com.vmware.photon.controller.model.resources.SubnetService.SubnetState in project photon-model by vmware.
the class AWSNetworkService method deleteSubnetStates.
/**
* Delete all subnet states that refer the NetworkState we are about to delete.
*/
private void deleteSubnetStates(AWSNetworkContext context, AWSNetworkStage next) {
Query queryForReferrers = QueryUtils.queryForReferrers(context.network.documentSelfLink, SubnetState.class, SubnetState.FIELD_NAME_NETWORK_LINK);
QueryByPages<SubnetState> subnetStates = new QueryByPages<>(getHost(), queryForReferrers, SubnetState.class, context.network.tenantLinks, context.network.endpointLink);
subnetStates.setClusterType(ServiceTypeCluster.INVENTORY_SERVICE);
DeferredResult<Void> query = subnetStates.queryDocuments(subnetState -> {
// First delete Subnet in AWS
try {
context.client.deleteSubnet(subnetState.id);
} catch (AmazonEC2Exception ex) {
if (AWSNetworkClient.STATUS_CODE_SUBNET_NOT_FOUND.equals(ex.getErrorCode())) {
// Ignore exception if the subnet is no longer available in AWS.
this.logWarning(() -> "Unable to delete the subnet in AWS. Reason: " + ex.getMessage());
} else {
throw ex;
}
}
// Then delete tracking SubnetState
Operation.createDelete(this, subnetState.documentSelfLink).sendWith(this);
});
query.whenComplete((v, e) -> {
if (e != null) {
handleStages(context, e);
} else {
handleStages(context, next);
}
});
}
use of com.vmware.photon.controller.model.resources.SubnetService.SubnetState in project photon-model by vmware.
the class AzureComputeEnumerationAdapterService method loadSubnets.
private DeferredResult<Map<String, String>> loadSubnets(EnumerationContext ctx, List<Pair<NetworkInterfaceInner, String>> remoteNics) {
Map<String, List<Pair<NetworkInterfaceInner, String>>> nicsPerSubnet = remoteNics.stream().filter(p -> p.getLeft() != null && p.getLeft().ipConfigurations() != null && !p.getLeft().ipConfigurations().isEmpty() && p.getLeft().ipConfigurations().get(0).subnet() != null).collect(java.util.stream.Collectors.groupingBy(p -> p.getLeft().ipConfigurations().get(0).subnet().id()));
Query.Builder qBuilder = Query.Builder.create().addKindFieldClause(SubnetState.class).addInClause(NetworkInterfaceState.FIELD_NAME_ID, nicsPerSubnet.keySet().stream().collect(Collectors.toList()));
QueryByPages<SubnetState> queryLocalStates = new QueryByPages<>(getHost(), qBuilder.build(), SubnetState.class, ctx.parentCompute.tenantLinks, // endpointLink
null, ctx.parentCompute.documentSelfLink).setMaxPageSize(QueryUtils.MAX_RESULT_LIMIT).setClusterType(ServiceTypeCluster.INVENTORY_SERVICE);
Map<String, String> subnetLinkPerNicId = new HashMap<>();
return queryLocalStates.queryDocuments(subnet -> nicsPerSubnet.get(subnet.id).forEach(p -> subnetLinkPerNicId.put(p.getLeft().id(), subnet.documentSelfLink))).thenApply(ignore -> subnetLinkPerNicId);
}
use of com.vmware.photon.controller.model.resources.SubnetService.SubnetState in project photon-model by vmware.
the class AzureNetworkEnumerationAdapterService method disassociateSubnetStates.
/**
* Delete subnet states that no longer exist in Azure.
* <p>
* The logic works by recording a timestamp when enumeration starts. This timestamp is used to
* lookup resources which haven't been touched as part of current enumeration cycle and belong
* to networks touched by this enumeration cycle (either created/updated/deleted).
*/
private void disassociateSubnetStates(NetworkEnumContext context, NetworkEnumStages next) {
Builder qBuilder = Query.Builder.create().addKindFieldClause(SubnetState.class).addFieldClause(SubnetState.FIELD_NAME_LIFECYCLE_STATE, LifecycleState.PROVISIONING.name(), MatchType.TERM, Occurance.MUST_NOT_OCCUR).addRangeClause(SubnetState.FIELD_NAME_UPDATE_TIME_MICROS, NumericRange.createLessThanRange(context.enumerationStartTimeInMicros));
QueryByPages<SubnetState> queryLocalStates = new QueryByPages<>(getHost(), qBuilder.build(), SubnetState.class, context.parentCompute.tenantLinks, null, /* endpoint */
context.parentCompute.documentSelfLink).setMaxPageSize(QueryUtils.MAX_RESULT_LIMIT).setClusterType(ServiceTypeCluster.INVENTORY_SERVICE);
disassociateResourceStates(queryLocalStates, context, next);
}
Aggregations