зеркало из https://github.com/Azure/AzureVM.git
227 строки
8.7 KiB
R
227 строки
8.7 KiB
R
#' Virtual machine template class
|
|
#'
|
|
#' Class representing a virtual machine deployment template. This class keeps track of all resources that are created as part of deploying a VM, and exposes methods for managing them.
|
|
#'
|
|
#' @docType class
|
|
#' @section Fields:
|
|
#' The following fields are exposed, in addition to those provided by the [AzureRMR::az_template] class.
|
|
#' - `dns_name`: The DNS name for the VM. Will be NULL if the VM is not publicly visible, or doesn't have a domain name assigned to its public IP address.
|
|
#' - `identity`: The managed identity details for the VM. Will be NULL if the VM doesn't have an identity assigned.
|
|
#' @section Methods:
|
|
#' The following methods are available, in addition to those provided by the [AzureRMR::az_template] class.
|
|
#' - `start(wait=TRUE)`: Start the VM. By default, wait until the startup process is complete.
|
|
#' - `stop(deallocate=TRUE, wait=FALSE)`: Stop the VM. By default, deallocate it as well.
|
|
#' - `restart(wait=TRUE)`: Restart the VM.
|
|
#' - `run_deployed_command(command, parameters, script)`: Run a PowerShell command on the VM.
|
|
#' - `run_script(script, parameters)`: Run a script on the VM. For a Linux VM, this will be a shell script; for a Windows VM, a PowerShell script. Pass the script as a character vector.
|
|
#' - `sync_vm_status()`: Check the status of the VM.
|
|
#' - `resize(size, deallocate=FALSE, wait=FALSE)`: Resize the VM. Optionally stop and deallocate it first (may sometimes be necessary).
|
|
#' - `redeploy()`: Redeploy the VM.
|
|
#' - `reimage()`: Reimage the VM.
|
|
#' - `get_public_ip_address(nic=1, config=1)`: Get the public IP address of the VM. Returns NA if the VM is stopped, or is not publicly accessible.
|
|
#' - `get_private_ip_address(nic=1, config=1)`: Get the private IP address of the VM.
|
|
#' - `get_public_ip_resource(nic=1, config=1)`: Get the Azure resource for the VM's public IP address.
|
|
#' - `get_nic(nic=1)`: Get the VM's network interface resource.
|
|
#' - `get_vnet(nic=1, config=1)`: Get the VM's virtual network resource.
|
|
#' - `get_nsg(nic=1, config=1)`: Get the VM's network security group resource. Note that an NSG can be attached to either the VM's network interface or to its virtual network subnet; if there is an NSG attached to both, this method returns a list containing the two NSG resource objects.
|
|
#' - `get_disk(disk="os")`: Get a managed disk resource attached to the VM. The `disk` argument can be "os" for the OS disk, or a number indicating the LUN of a data disk. AzureVM only supports managed disks.
|
|
#' - `add_extension(publisher, type, version, settings=list(), protected_settings=list(), key_vault_settings=list())`: Add an extension to the VM.
|
|
#' - `do_vm_operation(...)`: Carries out an arbitrary operation on the VM resource. See the `do_operation` method of the [AzureRMR::az_resource] class for more details.
|
|
#'
|
|
#' Many of these methods are actually provided by the [az_vm_resource] class, and propagated to the template as active bindings.
|
|
#'
|
|
#' @details
|
|
#' A single virtual machine in Azure is actually a collection of resources, including any and all of the following.
|
|
#' - Network interface (Azure resource type `Microsoft.Network/networkInterfaces`)
|
|
#' - Network security group (Azure resource type `Microsoft.Network/networkSecurityGroups`)
|
|
#' - Virtual network (Azure resource type `Microsoft.Network/virtualNetworks`)
|
|
#' - Public IP address (Azure resource type `Microsoft.Network/publicIPAddresses`)
|
|
#' - The VM itself (Azure resource type `Microsoft.Compute/virtualMachines`)
|
|
#'
|
|
#' By wrapping the deployment template used to create these resources, the `az_vm_template` class allows managing them all as a single entity.
|
|
#'
|
|
#' @seealso
|
|
#' [AzureRMR::az_template], [create_vm], [get_vm], [delete_vm]
|
|
#'
|
|
#' [VM API reference](https://docs.microsoft.com/en-us/rest/api/compute/virtualmachines)
|
|
#'
|
|
#' @examples
|
|
#' \dontrun{
|
|
#'
|
|
#' sub <- AzureRMR::get_azure_login()$
|
|
#' get_subscription("subscription_id")
|
|
#'
|
|
#' vm <- sub$get_vm("myvm")
|
|
#'
|
|
#' vm$identity
|
|
#'
|
|
#' vm$start()
|
|
#' vm$get_private_ip_address()
|
|
#' vm$get_public_ip_address()
|
|
#'
|
|
#' vm$run_script("echo hello world! > /tmp/hello.txt")
|
|
#'
|
|
#' vm$stop()
|
|
#' vm$get_private_ip_address()
|
|
#' vm$get_public_ip_address() # NA, assuming VM has a dynamic IP address
|
|
#'
|
|
#' vm$resize("Standard_DS13_v2")
|
|
#' vm$sync_vm_status()
|
|
#'
|
|
#' }
|
|
#' @format An R6 object of class `az_vm_template`, inheriting from `AzureRMR::az_template`.
|
|
#' @export
|
|
az_vm_template <- R6::R6Class("az_vm_template", inherit=az_template,
|
|
|
|
public=list(
|
|
dns_name=NULL,
|
|
|
|
initialize=function(token, subscription, resource_group, name, ..., wait=TRUE)
|
|
{
|
|
super$initialize(token, subscription, resource_group, name, ..., wait=wait)
|
|
|
|
if(wait)
|
|
{
|
|
private$vm <- az_vm_resource$new(self$token, self$subscription, id=self$properties$outputs$vmResource$value)
|
|
|
|
# get the hostname/IP address for the VM
|
|
outputs <- unlist(self$properties$outputResources)
|
|
ip_id <- grep("publicIPAddresses/.+$", outputs, ignore.case=TRUE, value=TRUE)
|
|
|
|
if(!is_empty(ip_id))
|
|
{
|
|
ip <- az_resource$new(self$token, self$subscription, id=ip_id)
|
|
self$dns_name <- ip$properties$dnsSettings$fqdn
|
|
}
|
|
}
|
|
else message("Deployment started. Call the sync_vm_status() method to track the status of the deployment.")
|
|
},
|
|
|
|
delete=function(confirm=TRUE, free_resources=TRUE)
|
|
{
|
|
# must reorder template output resources so that freeing resources will work
|
|
private$reorder_for_delete()
|
|
super$delete(confirm=confirm, free_resources=free_resources)
|
|
},
|
|
|
|
print=function(...)
|
|
{
|
|
cat("<Azure virtual machine ", self$name, ">\n", sep="")
|
|
|
|
osProf <- names(private$vm$properties$osProfile)
|
|
os <- if(any(grepl("linux", osProf))) "Linux" else if(any(grepl("windows", osProf))) "Windows" else "<unknown>"
|
|
exclusive <- self$properties$mode == "Complete"
|
|
status <- if(is_empty(private$vm$status))
|
|
"<unknown>"
|
|
else paste0(names(private$vm$status), "=", private$vm$status, collapse=", ")
|
|
|
|
cat(" Operating system:", os, "\n")
|
|
cat(" Exclusive resource group:", exclusive, "\n")
|
|
cat(" Domain name:", self$dns_name, "\n")
|
|
cat(" Status:", status, "\n")
|
|
cat("---\n")
|
|
|
|
exclude <- c("subscription", "resource_group", "name", "dns_name")
|
|
|
|
cat(AzureRMR::format_public_fields(self, exclude=exclude))
|
|
cat(AzureRMR::format_public_methods(self))
|
|
invisible(NULL)
|
|
}
|
|
),
|
|
|
|
# propagate resource methods up to template
|
|
active=list(
|
|
|
|
identity=function()
|
|
private$vm$identity,
|
|
|
|
sync_vm_status=function()
|
|
private$vm$sync_vm_status,
|
|
|
|
start=function()
|
|
private$vm$start,
|
|
|
|
stop=function()
|
|
private$vm$stop,
|
|
|
|
restart=function()
|
|
private$vm$restart,
|
|
|
|
add_extension=function()
|
|
private$vm$add_extension,
|
|
|
|
resize=function()
|
|
private$vm$resize,
|
|
|
|
run_deployed_command=function()
|
|
private$vm$run_deployed_command,
|
|
|
|
run_script=function()
|
|
private$vm$run_script,
|
|
|
|
get_public_ip_address=function()
|
|
private$vm$get_public_ip_address,
|
|
|
|
get_private_ip_address=function()
|
|
private$vm$get_private_ip_address,
|
|
|
|
get_public_ip_resource=function()
|
|
private$vm$get_public_ip_resource,
|
|
|
|
get_nic=function()
|
|
private$vm$get_nic,
|
|
|
|
get_vnet=function()
|
|
private$vm$get_vnet,
|
|
|
|
get_nsg=function()
|
|
private$vm$get_nsg,
|
|
|
|
get_disk=function()
|
|
private$vm$get_disk,
|
|
|
|
redeploy=function()
|
|
private$vm$redeploy,
|
|
|
|
reimage=function()
|
|
private$vm$reimage,
|
|
|
|
do_vm_operation=function()
|
|
private$vm$do_operation
|
|
),
|
|
|
|
private=list(
|
|
vm=NULL,
|
|
|
|
reorder_for_delete=function()
|
|
{
|
|
is_type <- function(id, type)
|
|
{
|
|
grepl(type, id, fixed=TRUE)
|
|
}
|
|
|
|
# insert managed disks into deletion queue
|
|
stor <- private$vm$properties$storageProfile
|
|
managed_disks <- c(
|
|
stor$osDisk$managedDisk$id,
|
|
lapply(stor$dataDisks, function(x) x$managedDisk$id)
|
|
)
|
|
outs <- unique(c(unlist(self$properties$outputResources), unlist(managed_disks)))
|
|
|
|
new_order <- sapply(outs, function(id)
|
|
{
|
|
if(is_type(id, "Microsoft.Compute/virtualMachines")) 1
|
|
else if(is_type(id, "Microsoft.Compute/disks")) 2
|
|
else if(is_type(id, "Microsoft.Network/networkInterfaces")) 3
|
|
else if(is_type(id, "Microsoft.Network/virtualNetworks")) 4
|
|
else if(is_type(id, "Microsoft.Network/publicIPAddresses")) 5
|
|
else if(is_type(id, "Microsoft.Network/networkSecurityGroups")) 6
|
|
else 0 # delete all other resources first
|
|
})
|
|
|
|
outs <- outs[order(new_order)]
|
|
self$properties$outputResources <- lapply(outs, function(x) list(id=x))
|
|
}
|
|
))
|
|
|