Skip to content

Commit

Permalink
Merge pull request #318 from CloudSlang/gcc_instances_sync
Browse files Browse the repository at this point in the history
Added sync functionality and new operation
  • Loading branch information
ionutmarisca committed Sep 6, 2017
2 parents 57f213d + 36b4bfb commit a93bfed
Show file tree
Hide file tree
Showing 21 changed files with 881 additions and 304 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,8 @@ class DisksDelete {
* @param proxyPasswordInp Optional - Proxy server password associated with the <proxyUsername> input value.
* @param prettyPrintInp Optional - Whether to format the resulting JSON.
* Default: "true"
* @return a map containing a ZoneOperation resource as returnResult, it's name as zoneOperationName and the disk name.
* If <syncInp> is set to true the map will also contain the status of the operation.
* @return a map containing a ZoneOperation resource as returnResult, it's name as zoneOperationName, the disk name
* and the status of the operation.
* In case an exception occurs the failure message is provided.
*/
@Action(name = "Delete Disk",
Expand Down Expand Up @@ -114,27 +114,22 @@ class DisksDelete {
val prettyPrint = toBoolean(prettyPrintStr)
val sync = toBoolean(syncStr)
val timeout = toLong(timeoutStr)
val pollingInterval = toDouble(pollingIntervalStr)
val pollingIntervalMilli = convertSecondsToMilli(toDouble(pollingIntervalStr))

try {
val httpTransport = HttpTransportUtils.getNetHttpTransport(proxyHostOpt, proxyPort, proxyUsernameOpt, proxyPassword)
val jsonFactory = JsonFactoryUtils.getDefaultJacksonFactory
val credential = GoogleAuth.fromAccessToken(accessToken)

val pollingIntervalMilli = convertSecondsToMilli(pollingInterval)

val operation = DiskService.delete(httpTransport, jsonFactory, credential, projectId, zone, diskName, sync, timeout, pollingIntervalMilli)
val name = defaultIfEmpty(operation.getName, EMPTY)
val status = defaultIfEmpty(operation.getStatus, EMPTY)
val resultMap = getSuccessResultsMap(toPretty(prettyPrint, operation)) +
(ZONE_OPERATION_NAME -> operation.getName) +
(DISK_NAME -> diskName)

if (sync) {
val status = Option(operation.getStatus).getOrElse("")
(ZONE_OPERATION_NAME -> name) +
(DISK_NAME -> diskName) +
(STATUS -> status)

resultMap + (STATUS -> status)
} else {
resultMap
}
resultMap
} catch {
case t: TimeoutException => getFailureResultsMap(TIMEOUT_EXCEPTION, t)
case e: Throwable => getFailureResultsMap(e)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import com.google.api.services.compute.model.Disk
import com.hp.oo.sdk.content.annotations.{Action, Output, Param, Response}
import com.hp.oo.sdk.content.plugin.ActionMetadata.{MatchType, ResponseType}
import io.cloudslang.content.constants.BooleanValues.FALSE
import io.cloudslang.content.constants.OutputNames.{EXCEPTION, RETURN_CODE, RETURN_RESULT}
import io.cloudslang.content.constants.{OutputNames, ResponseNames, ReturnCodes}
import io.cloudslang.content.google.services.compute.compute_engine.disks.{DiskController, DiskService}
import io.cloudslang.content.google.utils.Constants.{NEW_LINE, TIMEOUT_EXCEPTION}
Expand Down Expand Up @@ -103,15 +104,16 @@ class DisksInsert {
* Valid values: "true", "false"
* Default: "true"
* @return A map with strings as keys and strings as values that contains: outcome of the action, returnCode of the
* operation, zoneOperationName, zone and diskName if the <syncInp> is false. If <syncInp> is true the map
* will also contain the disk size, the disk id and the status of the disk.
* operation, zoneOperationName, zone, diskName and the status of the operation if the <syncInp> is false.
* If <syncInp> is true the map will also contain the disk size, the disk id and the status of the operation
* will be replaced by the status of the disk.
* In case an exception occurs the failure message is provided.
*/
@Action(name = "Insert Disk",
outputs = Array(
new Output(OutputNames.RETURN_CODE),
new Output(OutputNames.RETURN_RESULT),
new Output(OutputNames.EXCEPTION),
new Output(RETURN_CODE),
new Output(RETURN_RESULT),
new Output(EXCEPTION),
new Output(ZONE_OPERATION_NAME),
new Output(DISK_ID),
new Output(DISK_NAME),
Expand All @@ -120,8 +122,8 @@ class DisksInsert {
new Output(ZONE)
),
responses = Array(
new Response(text = ResponseNames.SUCCESS, field = OutputNames.RETURN_CODE, value = ReturnCodes.SUCCESS, matchType = MatchType.COMPARE_EQUAL, responseType = ResponseType.RESOLVED),
new Response(text = ResponseNames.FAILURE, field = OutputNames.RETURN_CODE, value = ReturnCodes.FAILURE, matchType = MatchType.COMPARE_EQUAL, responseType = ResponseType.ERROR, isOnFail = true)
new Response(text = ResponseNames.SUCCESS, field = RETURN_CODE, value = ReturnCodes.SUCCESS, matchType = MatchType.COMPARE_EQUAL, responseType = ResponseType.RESOLVED),
new Response(text = ResponseNames.FAILURE, field = RETURN_CODE, value = ReturnCodes.FAILURE, matchType = MatchType.COMPARE_EQUAL, responseType = ResponseType.ERROR, isOnFail = true)
)
)
def execute(@Param(value = PROJECT_ID, required = true) projectId: String,
Expand Down Expand Up @@ -179,15 +181,13 @@ class DisksInsert {
val diskSize = toInteger(diskSizeStr).toLong
val sync = toBoolean(syncStr)
val timeout = toLong(timeoutStr)
val pollingInterval = toDouble(pollingIntervalStr)
val pollingIntervalMilli = convertSecondsToMilli(toDouble(pollingIntervalStr))

try {
val httpTransport = HttpTransportUtils.getNetHttpTransport(proxyHostOpt, proxyPort, proxyUsernameOpt, proxyPassword)
val jsonFactory = JsonFactoryUtils.getDefaultJacksonFactory
val credential = GoogleAuth.fromAccessToken(accessToken)

val pollingIntervalMilli = convertSecondsToMilli(pollingInterval)

val computeDisk: Disk = DiskController.createDisk(
zone = zone,
diskName = diskName,
Expand All @@ -209,15 +209,19 @@ class DisksInsert {

if (sync) {
val disk = DiskService.get(httpTransport, jsonFactory, credential, projectId, zone, diskName)
val status = Option(disk.getStatus).getOrElse("")
val diskSize = Option(disk.getSizeGb).getOrElse(0.toLong)
val diskId = Option(disk.getId).getOrElse(BigInt(0)).toString
val status = defaultIfEmpty(disk.getStatus, EMPTY)
val diskSize = Option(disk.getSizeGb).getOrElse(0.toLong).toString

resultMap +
(DISK_ID -> disk.getId.toString) +
(DISK_SIZE -> diskSize.toString) +
(DISK_ID -> diskId) +
(DISK_SIZE -> diskSize) +
(STATUS -> status)
} else {
resultMap
val status = defaultIfEmpty(operation.getStatus, EMPTY)

resultMap +
(STATUS -> status)
}
} catch {
case t: TimeoutException => getFailureResultsMap(TIMEOUT_EXCEPTION, t)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,21 @@ import io.cloudslang.content.constants.OutputNames.{EXCEPTION, RETURN_CODE, RETU
import io.cloudslang.content.constants.{ResponseNames, ReturnCodes}
import io.cloudslang.content.google.services.compute.compute_engine.disks.DiskController
import io.cloudslang.content.google.services.compute.compute_engine.instances.InstanceService
import io.cloudslang.content.google.utils.Constants.NEW_LINE
import io.cloudslang.content.google.utils.action.DefaultValues.{DEFAULT_INTERFACE, DEFAULT_PRETTY_PRINT, DEFAULT_PROXY_PORT, DEFAULT_VOLUME_MOUNT_MODE}
import io.cloudslang.content.google.utils.action.GoogleOutputNames.ZONE_OPERATION_NAME
import io.cloudslang.content.google.utils.action.InputNames._
import io.cloudslang.content.google.utils.action.InputUtils.verifyEmpty
import io.cloudslang.content.google.utils.action.InputValidator.{validateBoolean, validateProxyPort}
import io.cloudslang.content.google.utils.Constants.{NEW_LINE, TIMEOUT_EXCEPTION}
import io.cloudslang.content.google.utils.action.DefaultValues._
import io.cloudslang.content.google.utils.action.GoogleOutputNames.{ZONE_OPERATION_NAME => _, _}
import io.cloudslang.content.google.utils.action.InputNames.{ZONE_OPERATION_NAME, _}
import io.cloudslang.content.google.utils.action.InputUtils.{convertSecondsToMilli, verifyEmpty}
import io.cloudslang.content.google.utils.action.InputValidator.{validateBoolean, validateNonNegativeDouble, validateNonNegativeLong, validateProxyPort}
import io.cloudslang.content.google.utils.action.OutputUtils.toPretty
import io.cloudslang.content.google.utils.service.{GoogleAuth, HttpTransportUtils, JsonFactoryUtils}
import io.cloudslang.content.utils.BooleanUtilities.toBoolean
import io.cloudslang.content.utils.NumberUtilities.toInteger
import io.cloudslang.content.utils.NumberUtilities.{toDouble, toInteger, toLong}
import io.cloudslang.content.utils.OutputUtilities.{getFailureResultsMap, getSuccessResultsMap}
import org.apache.commons.lang3.StringUtils.{EMPTY, defaultIfEmpty}

import scala.collection.JavaConversions._
import scala.concurrent.TimeoutException

/**
* Created by sandorr on 5/2/2017.
Expand All @@ -31,47 +33,64 @@ class InstancesAttachDisk {
/**
* Creates a disk resource in the specified project using the data included as inputs.
*
* @param projectId Name of the Google Cloud project.
* @param zone Name of the zone for this request.
* @param accessToken The access token from GetAccessToken.
* @param instanceName Name of the instance to attach the disk to.
* @param source A valid partial or full URL to an existing Persistent Disk resource.
* @param mode Optional - The mode in which to attach the disk to the instance.
* Valid values: "READ_WRITE", "READ_ONLY"
* Default: "READ_WRITE"
* @param autoDelete Optional - Whether to delete the disk when the instance is deleted.
* Default: "false"
* @param deviceName Optional - Specifies a unique device name of your choice that is reflected into the
* /dev/disk/by-id/google-* tree of a Linux operating system running within the instance.
* This name can be used to reference the device for mounting, resizing, and so on, from
* within the instance.
* Note: If not specified, the server chooses a default device name to apply to this disk,
* in the form persistent-disks-x, where x is a number assigned by Google Compute Engine.
* This field is only applicable for persistent disks.
* @param interfaceInp Optional - Specifies the disk interface to use for attaching this disk.
* Note: Persistent disks must always use SCSI and the request will fail if you attempt to
* attach a persistent disk in any other format than SCSI. Local SSDs can use either
* NVME or SCSI.
* Valid values: "SCSI", "NVME"
* Default: "SCSI"
* @param proxyHost Optional - Proxy server used to connect to Google Cloud API. If empty no proxy will
* be used.
* @param proxyPortInp Optional - Proxy server port.
* Default: "8080"
* @param proxyUsername Optional - Proxy server user name.
* @param proxyPasswordInp Optional - Proxy server password associated with the proxyUsername input value.
* @param prettyPrintInp Optional - Whether to format (pretty print) the resulting json.
* Valid values: "true", "false"
* Default: "true"
* @param projectId Name of the Google Cloud project.
* @param zone Name of the zone for this request.
* @param accessToken The access token from GetAccessToken.
* @param instanceName Name of the instance to attach the disk to.
* @param source A valid partial or full URL to an existing Persistent Disk resource.
* @param mode Optional - The mode in which to attach the disk to the instance.
* Valid values: "READ_WRITE", "READ_ONLY"
* Default: "READ_WRITE"
* @param autoDelete Optional - Whether to delete the disk when the instance is deleted.
* Default: "false"
* @param deviceName Optional - Specifies a unique device name of your choice that is reflected into the
* /dev/disk/by-id/google-* tree of a Linux operating system running within the instance.
* This name can be used to reference the device for mounting, resizing, and so on, from
* within the instance.
* Note: If not specified, the server chooses a default device name to apply to this disk,
* in the form persistent-disks-x, where x is a number assigned by Google Compute Engine.
* This field is only applicable for persistent disks.
* @param interfaceInp Optional - Specifies the disk interface to use for attaching this disk.
* Note: Persistent disks must always use SCSI and the request will fail if you attempt to
* attach a persistent disk in any other format than SCSI. Local SSDs can use either
* NVME or SCSI.
* Valid values: "SCSI", "NVME"
* Default: "SCSI"
* @param syncInp Optional - Boolean specifying whether the operation to run sync or async.
* Valid values: "true", "false"
* Default: "false"
* @param timeoutInp Optional - The time, in seconds, to wait for a response if the sync input is set to "true".
* If the value is 0, the operation will wait until zone operation progress is 100.
* Valid values: Any positive number including 0.
* Default: "30"
* @param pollingIntervalInp Optional - The time, in seconds, to wait before a new request that verifies if the operation finished
* is executed, if the sync input is set to "true".
* Valid values: Any positive number including 0.
* Default: "1"
* @param proxyHost Optional - Proxy server used to connect to Google Cloud API. If empty no proxy will
* be used.
* @param proxyPortInp Optional - Proxy server port.
* Default: "8080"
* @param proxyUsername Optional - Proxy server user name.
* @param proxyPasswordInp Optional - Proxy server password associated with the proxyUsername input value.
* @param prettyPrintInp Optional - Whether to format (pretty print) the resulting json.
* Valid values: "true", "false"
* Default: "true"
* @return A map with strings as keys and strings as values that contains: outcome of the action, returnCode of the
* operation, status of the ZoneOperation, or failure message and the exception if there is one
* operation, status of the ZoneOperation if the <syncInp> is false. If <syncInp> is true the map will also
* contain the name of the instance, the details of the instance, including the attached disks and the status
* of the operation will be replaced by the status of the instance.
* In case an exception occurs the failure message is provided.
*/
@Action(name = "Instances Attach Disk",
outputs = Array(
new Output(RETURN_CODE),
new Output(RETURN_RESULT),
new Output(EXCEPTION),
new Output(ZONE_OPERATION_NAME)
new Output(ZONE_OPERATION_NAME),
new Output(INSTANCE_NAME),
new Output(INSTANCE_DETAILS),
new Output(STATUS)
),
responses = Array(
new Response(text = ResponseNames.SUCCESS, field = RETURN_CODE, value = ReturnCodes.SUCCESS, matchType = MatchType.COMPARE_EQUAL, responseType = ResponseType.RESOLVED),
Expand All @@ -87,6 +106,9 @@ class InstancesAttachDisk {
@Param(value = AUTO_DELETE) autoDelete: String,
@Param(value = DEVICE_NAME) deviceName: String,
@Param(value = INTERFACE) interfaceInp: String,
@Param(value = SYNC) syncInp: String,
@Param(value = TIMEOUT) timeoutInp: String,
@Param(value = POLLING_INTERVAL) pollingIntervalInp: String,
@Param(value = PROXY_HOST) proxyHost: String,
@Param(value = PROXY_PORT) proxyPortInp: String,
@Param(value = PROXY_USERNAME) proxyUsername: String,
Expand All @@ -103,11 +125,16 @@ class InstancesAttachDisk {
val autoDeleteStr = defaultIfEmpty(autoDelete, FALSE)
val interface = defaultIfEmpty(interfaceInp, DEFAULT_INTERFACE)
val deviceNameOpt = verifyEmpty(deviceName)

val syncStr = defaultIfEmpty(syncInp, FALSE)
val timeoutStr = defaultIfEmpty(timeoutInp, DEFAULT_SYNC_TIMEOUT)
val pollingIntervalStr = defaultIfEmpty(pollingIntervalInp, DEFAULT_POLLING_INTERVAL)

val validationStream = validateProxyPort(proxyPortStr) ++
validateBoolean(prettyPrintStr, PRETTY_PRINT) ++
validateBoolean(autoDeleteStr, AUTO_DELETE)
validateBoolean(autoDeleteStr, AUTO_DELETE) ++
validateBoolean(syncStr, SYNC) ++
validateNonNegativeLong(timeoutStr, TIMEOUT) ++
validateNonNegativeDouble(pollingIntervalStr, POLLING_INTERVAL)

if (validationStream.nonEmpty) {
return getFailureResultsMap(validationStream.mkString(NEW_LINE))
Expand All @@ -117,6 +144,9 @@ class InstancesAttachDisk {
val proxyPort = toInteger(proxyPortStr)
val prettyPrint = toBoolean(prettyPrintStr)
val autoDelete = toBoolean(autoDeleteStr)
val sync = toBoolean(syncStr)
val timeout = toLong(timeoutStr)
val pollingIntervalMilli = convertSecondsToMilli(toDouble(pollingIntervalStr))

val httpTransport = HttpTransportUtils.getNetHttpTransport(proxyHostOpt, proxyPort, proxyUsernameOpt, proxyPassword)
val jsonFactory = JsonFactoryUtils.getDefaultJacksonFactory
Expand All @@ -130,11 +160,26 @@ class InstancesAttachDisk {
sourceOpt = Some(source),
interfaceOpt = Some(interface))

val operation = InstanceService.attachDisk(httpTransport, jsonFactory, credential, projectId, zone, instanceName, attachedDisk)
val resultString = if (prettyPrint) operation.toPrettyString else operation.toString
val operation = InstanceService.attachDisk(httpTransport, jsonFactory, credential, projectId, zone, instanceName, attachedDisk, sync, timeout, pollingIntervalMilli)
val resultMap = getSuccessResultsMap(toPretty(prettyPrint, operation)) + (ZONE_OPERATION_NAME -> operation.getName)

if (sync) {
val instance = InstanceService.get(httpTransport, jsonFactory, credential, projectId, zone, instanceName)
val name = defaultIfEmpty(instance.getName, EMPTY)
val status = defaultIfEmpty(instance.getStatus, EMPTY)

resultMap +
(INSTANCE_NAME -> name) +
(INSTANCE_DETAILS -> toPretty(prettyPrint, instance)) +
(STATUS -> status)
} else {
val status = defaultIfEmpty(operation.getStatus, EMPTY)

getSuccessResultsMap(resultString) + (ZONE_OPERATION_NAME -> operation.getName)
resultMap +
(STATUS -> status)
}
} catch {
case t: TimeoutException => getFailureResultsMap(TIMEOUT_EXCEPTION, t)
case e: Throwable => getFailureResultsMap(e)
}
}
Expand Down

0 comments on commit a93bfed

Please sign in to comment.