if (IPAddressStatus.RELEASED.equals(newState.ipAddressStatus) && IPAddressStatus.AVAILABLE.equals(currentState.ipAddressStatus)) { logInfo("IP address [%s] is already available, and need not be released. Operation ignored.", currentState.documentSelfLink); StringUtils.equals(currentState.ipAddress, newState.ipAddress) && StringUtils.equals(currentState.subnetRangeLink, newState.subnetRangeLink) && currentState.ipAddressStatus.equals(newState.ipAddressStatus)) { return true;
/** * @param currentState current IP address * @param desiredState requested IP address * @throws IllegalArgumentException if an invalid transition */ private void validateIPAddressStatusTransition(IPAddressState currentState, IPAddressState desiredState) { AssertUtil.assertTrue(IPAddressStatus .isValidTransition(currentState.ipAddressStatus, desiredState.ipAddressStatus), String.format("Invalid IP address status transition from [%s] to [%s]", currentState.ipAddressStatus, desiredState.ipAddressStatus)); }
/** * Retrieves ip addresses that are in RELEASED state for more than IP_ADDRESS_RELEASE_INTERVAL_MS milliseconds. * * @return List of IP addresses that are in RELEASED state for more than IP_ADDRESS_RELEASE_PERIOD_MS millii seconds. */ private DeferredResult<List<IPAddressService.IPAddressState>> retrieveReleasedIPAddresses() { long currentTime = Utils.getNowMicrosUtc(); long ipAddressReleaseCutoffTime = currentTime - TimeUnit.SECONDS.toMicros(IP_ADDRESS_RELEASE_PERIOD_SECONDS); QueryTask.Query getReleasedIPAddressesQuery = QueryTask.Query.Builder.create() .addKindFieldClause(IPAddressService.IPAddressState.class) .addFieldClause(FIELD_NAME_IP_ADDRESS_STATUS, IPAddressService.IPAddressState.IPAddressStatus.RELEASED.toString()) .addRangeClause(ServiceDocument.FIELD_NAME_UPDATE_TIME_MICROS, QueryTask.NumericRange.createLessThanRange(ipAddressReleaseCutoffTime)) .build(); QueryUtils.QueryByPages<IPAddressService.IPAddressState> queryByPages = new QueryUtils.QueryByPages<>( this.getHost(), getReleasedIPAddressesQuery, IPAddressService.IPAddressState.class, null); queryByPages.setClusterType(ServiceTypeCluster.INVENTORY_SERVICE); return queryByPages.collectDocuments(Collectors.toList()) .exceptionally(e -> { logWarning(String.format("Failed to retrieve released IP addresses due to error %s", e.getMessage())); return new ArrayList<>(); }); }
if (IPAddressStatus.RELEASED.equals(newState.ipAddressStatus)) { newState.connectedResourceLink = null;
return; if (IPAddressStatus.RELEASED.equals(patchState.ipAddressStatus)) { patchState.connectedResourceLink = ResourceUtils.NULL_LINK_VALUE;
if (IPAddressStatus.AVAILABLE.equals(ipAddressState.ipAddressStatus)) { IPAddressState patchedState = new IPAddressState(); patchedState.ipAddressStatus = IPAddressStatus.ALLOCATED;
@Test public void testAllocateSpecificIPWhenAlreadyAllocatedToSameResource() throws Throwable { //This service is used by other tests. Hence stop it first if it's already started. try { deleteServiceSynchronously(TestStatelessService.SELF_LINK); } catch (ServiceNotFoundException exception) { //do nothing } this.host.startService(new TestStatelessService(new DeferredResult<>())); this.host.waitForServiceAvailable(TestStatelessService.SELF_LINK); // Create IP address state in allocated mode, with the same resource createNewIpAddressResourceAsAllocated(SPECIFIC_IP, this.subnetRangeState2.documentSelfLink, ComputeService.FACTORY_LINK + "/machine-1"); IPAddressAllocationTaskState allocationTask = createIpAddressAllocationTask( this.subnetState.documentSelfLink, ComputeService.FACTORY_LINK + "/machine-1"); allocationTask.requestType = RequestType.ALLOCATE_SPECIFIC_IP; allocationTask.ipAddresses.add(SPECIFIC_IP); addFakeCallBack(allocationTask); IPAddressAllocationTaskState allocationTaskResult = performTask(allocationTask); // No failure expected, since IP already allocated to the request resource assertNotNull(allocationTaskResult); assertEquals(SPECIFIC_IP, allocationTaskResult.ipAddresses.get(0)); assertEquals(1, allocationTaskResult.rsrcToAllocatedIpsMap.values().size()); String ipAddressLink = allocationTaskResult.rsrcToAllocatedIpsMap.values().iterator().next().get(0); IPAddressState ipAddressState = getIpAddressState(ipAddressLink); assertTrue(IPAddressStatus.ALLOCATED.equals(ipAddressState.ipAddressStatus)); assertEquals(SPECIFIC_IP, ipAddressState.ipAddress); }
@Test public void testAllocateSpecificIPFromAvailable() throws Throwable { //This service is used by other tests. Hence stop it first if it's already started. try { deleteServiceSynchronously(TestStatelessService.SELF_LINK); } catch (ServiceNotFoundException exception) { //do nothing } this.host.startService(new TestStatelessService(new DeferredResult<>())); this.host.waitForServiceAvailable(TestStatelessService.SELF_LINK); // Create IP address state in available mode createNewIpAddressResourceAsAvailable(SPECIFIC_IP, this.subnetRangeState2.documentSelfLink); IPAddressAllocationTaskState allocationTask = createIpAddressAllocationTask( this.subnetState.documentSelfLink, ComputeService.FACTORY_LINK + "/machine-1"); allocationTask.requestType = RequestType.ALLOCATE_SPECIFIC_IP; allocationTask.ipAddresses.add(SPECIFIC_IP); addFakeCallBack(allocationTask); IPAddressAllocationTaskState allocationTaskResult = performTask(allocationTask); assertNotNull(allocationTaskResult); assertEquals(SPECIFIC_IP, allocationTaskResult.ipAddresses.get(0)); assertEquals(1, allocationTaskResult.rsrcToAllocatedIpsMap.values().size()); String ipAddressLink = allocationTaskResult.rsrcToAllocatedIpsMap.values().iterator().next().get(0); IPAddressState ipAddressState = getIpAddressState(ipAddressLink); assertTrue(IPAddressStatus.ALLOCATED.equals(ipAddressState.ipAddressStatus)); assertEquals(SPECIFIC_IP, ipAddressState.ipAddress); }
@Test public void testAllocateSpecificIP() throws Throwable { //This service is used by other tests. Hence stop it first if it's already started. try { deleteServiceSynchronously(TestStatelessService.SELF_LINK); } catch (ServiceNotFoundException exception) { //do nothing } this.host.startService(new TestStatelessService(new DeferredResult<>())); this.host.waitForServiceAvailable(TestStatelessService.SELF_LINK); IPAddressAllocationTaskState allocationTask = createIpAddressAllocationTask( this.subnetState.documentSelfLink, ComputeService.FACTORY_LINK + "/machine-1"); allocationTask.requestType = RequestType.ALLOCATE_SPECIFIC_IP; allocationTask.ipAddresses.add(SPECIFIC_IP); addFakeCallBack(allocationTask); IPAddressAllocationTaskState allocationTaskResult = performTask(allocationTask); assertNotNull(allocationTaskResult); assertEquals(SPECIFIC_IP, allocationTaskResult.ipAddresses.get(0)); assertEquals(1, allocationTaskResult.rsrcToAllocatedIpsMap.values().size()); String ipAddressLink = allocationTaskResult.rsrcToAllocatedIpsMap.values().iterator().next().get(0); IPAddressState ipAddressState = getIpAddressState(ipAddressLink); assertTrue(IPAddressStatus.ALLOCATED.equals(ipAddressState.ipAddressStatus)); assertEquals(SPECIFIC_IP, ipAddressState.ipAddress); }
/** * Allocated IPs should be in 'released' state before becoming 'available' again for allocation. * This method validates the status transitions. * * @param currentStatus current IPAddressStatus * @param newStatus IPAddressStatus to transition to * @return true if the transition is valid */ static boolean isValidTransition(IPAddressStatus currentStatus, IPAddressStatus newStatus) { return (currentStatus != null && currentStatus.equals(newStatus) || (AVAILABLE.equals(currentStatus) && ALLOCATED.equals(newStatus)) || (ALLOCATED.equals(currentStatus) && RELEASED.equals(newStatus)) || (RELEASED.equals(currentStatus) && AVAILABLE.equals(newStatus))); } }
/** * Allocated IPs should be in 'released' state before becoming 'available' again for allocation. * This method validates the status transitions. * * @param currentStatus current IPAddressStatus * @param newStatus IPAddressStatus to transition to * @return true if the transition is valid */ static boolean isValidTransition(IPAddressStatus currentStatus, IPAddressStatus newStatus) { return (currentStatus != null && currentStatus.equals(newStatus) || (AVAILABLE.equals(currentStatus) && ALLOCATED.equals(newStatus)) || (ALLOCATED.equals(currentStatus) && RELEASED.equals(newStatus)) || (RELEASED.equals(currentStatus) && AVAILABLE.equals(newStatus))); } }
/** * @param currentState current IP address * @param desiredState requested IP address * @throws IllegalArgumentException if an invalid transition */ private void validateIPAddressStatusTransition(IPAddressState currentState, IPAddressState desiredState) { AssertUtil.assertTrue(IPAddressStatus .isValidTransition(currentState.ipAddressStatus, desiredState.ipAddressStatus), String.format("Invalid IP address status transition from [%s] to [%s]", currentState.ipAddressStatus, desiredState.ipAddressStatus)); }