зеркало из https://github.com/Azure/AzureVM.git
add more examples, fix vnet
This commit is contained in:
Родитель
0a3c038ca1
Коммит
c829497f5b
2
NEWS.md
2
NEWS.md
|
@ -3,7 +3,7 @@
|
|||
* Complete rewrite of package, to be less DSVM-centric and more flexible:
|
||||
* Separate out deployment of VMs and VM clusters; the latter are implemented as scalesets, rather than simplistic arrays of individual VMs. The methods to work with scalesets are named `get_vm_scaleset`, `create_vm_scaleset` and `delete_vm_scaleset`; `get/create/delete_vm_cluster` are now defunct.
|
||||
* New UI for VM/scaleset creation, with many more ways to fine-tune the deployment options, including specifying the base VM image; networking details like security rules, load balancers and autoscaling; datadisks to attach; use of low-priority VMs for scalesets; etc.
|
||||
* Several predefined configurations supplied to allow quick deployment of commonly used images (Ubuntu, Windows Server, RHEL, Debian, DSVM).
|
||||
* Several predefined configurations supplied to allow quick deployment of commonly used images (Ubuntu, Windows Server, RHEL, Debian, Centos, DSVM).
|
||||
* Allow referring to existing resources in a deployment (eg placing VMs into an existing vnet), by supplying `AzureRMR::az_resource` objects as arguments.
|
||||
* Clear distinction between a VM deployment template and a resource. `get_vm` and `get_vm_scaleset` will always attempt to retrieve the template; to get the resource, use `get_vm_resource` and `get_vm_scaleset_resource`.
|
||||
* New VM resource methods: `get_public_ip_address`, `get_private_ip_address`.
|
||||
|
|
|
@ -4,12 +4,17 @@
|
|||
#' @param ... Other named arguments that will be treated as resource properties.
|
||||
#' @param name For `autoscaler_profile`, a name for the profile.
|
||||
#' @param minsize,maxsize,default For `autoscaler_profile`, the minimum, maximum and default number of instances.
|
||||
#' @param scale_out,scale_in For `autoscaler_profile`, the percentage CPU at which to scale out and in, respectively.
|
||||
#' @param scale_out,scale_in For `autoscaler_profile`, the CPU usage (a fraction between 0 and 1) at which to scale out and in, respectively.
|
||||
#' @param interval For `autoscaler_profile`, The interval between samples, in ISO 8601 format. The default is 1 minute.
|
||||
#' @param window For `autoscaler_profile`, the window width over which to compute the percentage CPU. The default is 5 minutes.
|
||||
#'
|
||||
#' @seealso
|
||||
#' [create_vm_scaleset], [vmss_config]
|
||||
#' @examples
|
||||
#' autoscaler_config()
|
||||
#' autoscaler_config(list(
|
||||
#' autoscaler_profile(minsize=2, maxsize=50, scale_out=0.9, scale_in=0.1)
|
||||
#' ))
|
||||
#' @export
|
||||
autoscaler_config <- function(profiles=list(autoscaler_profile()), ...)
|
||||
{
|
||||
|
|
|
@ -44,21 +44,21 @@
|
|||
#' sub <- AzureRMR::get_azure_login()$
|
||||
#' get_subscription("subscription_id")
|
||||
#'
|
||||
#' vm <- sub$get_vm("myLinuxDSVM")
|
||||
#' vm <- sub$get_vm("myvm")
|
||||
#'
|
||||
#' vm$identity
|
||||
#'
|
||||
#' # start the VM
|
||||
#' vm$start()
|
||||
#' vm$get_private_ip_address()
|
||||
#' vm$get_public_ip_address()
|
||||
#'
|
||||
#' # run a shell command
|
||||
#' vm$run_script("ifconfig > /tmp/ifc.out")
|
||||
#' vm$run_script("echo hello world! > /tmp/hello.txt")
|
||||
#'
|
||||
#' # stop (and deallocate) the VM
|
||||
#' vm$stop()
|
||||
#' vm$get_private_ip_address()
|
||||
#' vm$get_public_ip_address() # NA, assuming VM has a dynamic IP address
|
||||
#'
|
||||
#' # resize the VM
|
||||
#' vm$resize("Standard_DS13_v2")
|
||||
#'
|
||||
#' # get the VM status
|
||||
#' vm$sync_vm_status()
|
||||
#'
|
||||
#' }
|
||||
|
|
|
@ -57,16 +57,20 @@
|
|||
#'
|
||||
#' vmss <- sub$get_vm_scaleset("myscaleset")
|
||||
#'
|
||||
#' # start the VM
|
||||
#' vmss$identity
|
||||
#'
|
||||
#' vmss$get_public_ip_address() # NA if the scaleset doesn't have a load balancer
|
||||
#'
|
||||
#' vmss$start()
|
||||
#'
|
||||
#' # run a shell command
|
||||
#' vmss$run_script("ifconfig > /tmp/ifc.out")
|
||||
#'
|
||||
#' # get private IP addresses
|
||||
#' vmss$get_vm_private_ip_addresses()
|
||||
#' vmss$get_vm_public_ip_addresses() # NA if scaleset nodes are not publicly visible
|
||||
#'
|
||||
#' instances <- vmss$list_instances()
|
||||
#' first <- instances[1]
|
||||
#' vmss$run_script("echo hello world! > /tmp/hello.txt", id=first)
|
||||
#' vmss$stop(id=first)
|
||||
#' vmss$reimage(id=first)
|
||||
#'
|
||||
#' # get the VM status
|
||||
#' vmss$sync_vmss_status()
|
||||
#'
|
||||
#' }
|
||||
|
|
|
@ -8,6 +8,12 @@
|
|||
#'
|
||||
#' @seealso
|
||||
#' [create_vm], [vm_config], [vmss_config]
|
||||
#' @examples
|
||||
#' ip_config()
|
||||
#' ip_config(type="basic", dynamic=TRUE)
|
||||
#'
|
||||
#' # if you don't want a domain name associated with the IP address
|
||||
#' ip_config(domain_name=NULL)
|
||||
#' @export
|
||||
ip_config <- function(type=NULL, dynamic=NULL, ipv6=FALSE, domain_name="[parameters('vmName')]", ...)
|
||||
{
|
||||
|
|
|
@ -16,6 +16,13 @@
|
|||
#'
|
||||
#' @seealso
|
||||
#' [create_vm_scaleset], [vmss_config], [lb_rules] for some predefined load balancing rules and probes
|
||||
#' @examples
|
||||
#' lb_config()
|
||||
#' lb_config(type="basic")
|
||||
#' lb_config(
|
||||
#' rules=list(lb_rule_ssh, lb_rule_rdp),
|
||||
#' probes=list(lb_probe_ssh, lb_probe_rdp)
|
||||
#' )
|
||||
#' @export
|
||||
lb_config <- function(type=NULL, rules=list(), probes=list(), ...)
|
||||
{
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
#'
|
||||
#' @seealso
|
||||
#' [create_vm], [vm_config]
|
||||
#' @examples
|
||||
#' nic_config()
|
||||
#' @export
|
||||
nic_config <- function(nic_ip=list(nic_ip_config()), ...)
|
||||
{
|
||||
|
|
|
@ -12,6 +12,21 @@
|
|||
#'
|
||||
#' @seealso
|
||||
#' [create_vm], [vm_config], [vmss_config], [nsg_rules] for some predefined security rules
|
||||
#' @examples
|
||||
#' nsg_config()
|
||||
#' nsg_config(list(nsg_rule_allow_ssh)) # for Linux
|
||||
#' nsg_config(list(nsg_rule_allow_rdp)) # for Windows
|
||||
#' nsg_config(list(nsg_rule_allow_http, nsg_rule_allow_https))
|
||||
#'
|
||||
#' # a custom rule
|
||||
#' nsg_config(list(
|
||||
#' nsg_rule(
|
||||
#' name="whitelist",
|
||||
#' source_addr="114.198.100.0/24",
|
||||
#' access="allow",
|
||||
#' protocol="*"
|
||||
#' )
|
||||
#' ))
|
||||
#' @export
|
||||
nsg_config <- function(rules=list(), ...)
|
||||
{
|
||||
|
|
|
@ -9,6 +9,12 @@
|
|||
#'
|
||||
#' @seealso
|
||||
#' [create_vm], [vm_config], [vmss_config]
|
||||
#' @examples
|
||||
#' vnet_config()
|
||||
#' vnet_config(address_space="10.1.0.0/16")
|
||||
#' vnet_config(subnets=list(
|
||||
#' subnet_config("subnet", "10.0.0.0/24")
|
||||
#' ))
|
||||
#' @export
|
||||
vnet_config <- function(address_space="10.0.0.0/16", subnets=list(subnet_config()), ...)
|
||||
{
|
||||
|
@ -17,7 +23,7 @@ vnet_config <- function(address_space="10.0.0.0/16", subnets=list(subnet_config(
|
|||
ab_block <- sub(ab_regex, "\\1", address_space)
|
||||
fixaddr <- function(addr)
|
||||
{
|
||||
if(sub(ab_regex, "\\1", addr) == ab_block)
|
||||
if(sub(ab_regex, "\\1", addr) != ab_block)
|
||||
sub("^[0-9]+\\.[0-9]+", ab_block, addr)
|
||||
else addr
|
||||
}
|
||||
|
|
|
@ -4,7 +4,10 @@
|
|||
![Downloads](https://cranlogs.r-pkg.org/badges/AzureVM)
|
||||
[![Travis Build Status](https://travis-ci.org/Azure/AzureVM.png?branch=master)](https://travis-ci.org/Azure/AzureVM)
|
||||
|
||||
AzureVM is a package for interacting with virtual machines and virtual machine scalesets in Azure. You can deploy, start up, shut down, run scripts, deallocate and delete VMs and scalesets from the R command line. It uses the tools provided by the [AzureRMR package](https://github.com/Azure/AzureRMR) to manage VM resources and templates.
|
||||
AzureVM is a package for interacting with [virtual machines](https://azure.microsoft.com/services/virtual-machines/) and [virtual machine scalesets](https://azure.microsoft.com/services/virtual-machine-scale-sets/) in Azure. You can deploy, start up, shut down, run scripts, deallocate and delete VMs and scalesets from the R command line. It uses the tools provided by the [AzureRMR package](https://github.com/Azure/AzureRMR) to manage VM resources and templates.
|
||||
|
||||
Version 2.0 of AzureVM is a complete rewrite of the package, aiming to make it a truly generic and flexible interface to VMs.
|
||||
|
||||
|
||||
## Virtual machines
|
||||
|
||||
|
@ -35,7 +38,7 @@ vm$resize("Standard_DS4_v2")
|
|||
vm$delete()
|
||||
```
|
||||
|
||||
AzureVM comes with a number of predefined configurations, for deploying commonly used VM images. For example, to create an Ubuntu DSVM accessible via SSH, JupyterHub and RStudio Server:
|
||||
AzureVM comes with a number of predefined configurations, for deploying commonly used VM images. For example, to create an Ubuntu [Data Science Virtual Machine](https://azure.microsoft.com/services/virtual-machines/data-science-virtual-machines/) accessible via SSH, JupyterHub and RStudio Server:
|
||||
|
||||
```r
|
||||
sub$create_vm("mydsvm", user_config("myname", "~/.ssh/id_rsa.pub"), config="ubuntu_dsvm",
|
||||
|
|
|
@ -20,7 +20,7 @@ autoscaler_profile(name = "Profile", minsize = 1, maxsize = NA,
|
|||
|
||||
\item{minsize, maxsize, default}{For \code{autoscaler_profile}, the minimum, maximum and default number of instances.}
|
||||
|
||||
\item{scale_out, scale_in}{For \code{autoscaler_profile}, the percentage CPU at which to scale out and in, respectively.}
|
||||
\item{scale_out, scale_in}{For \code{autoscaler_profile}, the CPU usage (a fraction between 0 and 1) at which to scale out and in, respectively.}
|
||||
|
||||
\item{interval}{For \code{autoscaler_profile}, The interval between samples, in ISO 8601 format. The default is 1 minute.}
|
||||
|
||||
|
@ -29,6 +29,12 @@ autoscaler_profile(name = "Profile", minsize = 1, maxsize = NA,
|
|||
\description{
|
||||
Autoscaler configuration
|
||||
}
|
||||
\examples{
|
||||
autoscaler_config()
|
||||
autoscaler_config(list(
|
||||
autoscaler_profile(minsize=2, maxsize=50, scale_out=0.9, scale_in=0.1)
|
||||
))
|
||||
}
|
||||
\seealso{
|
||||
\link{create_vm_scaleset}, \link{vmss_config}
|
||||
}
|
||||
|
|
|
@ -58,21 +58,21 @@ The following methods are available, in addition to those provided by the \link[
|
|||
sub <- AzureRMR::get_azure_login()$
|
||||
get_subscription("subscription_id")
|
||||
|
||||
vm <- sub$get_vm("myLinuxDSVM")
|
||||
vm <- sub$get_vm("myvm")
|
||||
|
||||
vm$identity
|
||||
|
||||
# start the VM
|
||||
vm$start()
|
||||
vm$get_private_ip_address()
|
||||
vm$get_public_ip_address()
|
||||
|
||||
# run a shell command
|
||||
vm$run_script("ifconfig > /tmp/ifc.out")
|
||||
vm$run_script("echo hello world! > /tmp/hello.txt")
|
||||
|
||||
# stop (and deallocate) the VM
|
||||
vm$stop()
|
||||
vm$get_private_ip_address()
|
||||
vm$get_public_ip_address() # NA, assuming VM has a dynamic IP address
|
||||
|
||||
# resize the VM
|
||||
vm$resize("Standard_DS13_v2")
|
||||
|
||||
# get the VM status
|
||||
vm$sync_vm_status()
|
||||
|
||||
}
|
||||
|
|
|
@ -73,16 +73,20 @@ sub <- AzureRMR::get_azure_login()$
|
|||
|
||||
vmss <- sub$get_vm_scaleset("myscaleset")
|
||||
|
||||
# start the VM
|
||||
vmss$identity
|
||||
|
||||
vmss$get_public_ip_address() # NA if the scaleset doesn't have a load balancer
|
||||
|
||||
vmss$start()
|
||||
|
||||
# run a shell command
|
||||
vmss$run_script("ifconfig > /tmp/ifc.out")
|
||||
|
||||
# get private IP addresses
|
||||
vmss$get_vm_private_ip_addresses()
|
||||
vmss$get_vm_public_ip_addresses() # NA if scaleset nodes are not publicly visible
|
||||
|
||||
instances <- vmss$list_instances()
|
||||
first <- instances[1]
|
||||
vmss$run_script("echo hello world! > /tmp/hello.txt", id=first)
|
||||
vmss$stop(id=first)
|
||||
vmss$reimage(id=first)
|
||||
|
||||
# get the VM status
|
||||
vmss$sync_vmss_status()
|
||||
|
||||
}
|
||||
|
|
|
@ -21,6 +21,13 @@ ip_config(type = NULL, dynamic = NULL, ipv6 = FALSE,
|
|||
\description{
|
||||
Public IP address configuration
|
||||
}
|
||||
\examples{
|
||||
ip_config()
|
||||
ip_config(type="basic", dynamic=TRUE)
|
||||
|
||||
# if you don't want a domain name associated with the IP address
|
||||
ip_config(domain_name=NULL)
|
||||
}
|
||||
\seealso{
|
||||
\link{create_vm}, \link{vm_config}, \link{vmss_config}
|
||||
}
|
||||
|
|
|
@ -43,6 +43,14 @@ lb_rule(name, frontend_port, backend_port = frontend_port,
|
|||
\description{
|
||||
Load balancer configuration
|
||||
}
|
||||
\examples{
|
||||
lb_config()
|
||||
lb_config(type="basic")
|
||||
lb_config(
|
||||
rules=list(lb_rule_ssh, lb_rule_rdp),
|
||||
probes=list(lb_probe_ssh, lb_probe_rdp)
|
||||
)
|
||||
}
|
||||
\seealso{
|
||||
\link{create_vm_scaleset}, \link{vmss_config}, \link{lb_rules} for some predefined load balancing rules and probes
|
||||
}
|
||||
|
|
|
@ -27,6 +27,9 @@ nic_ip_config(name = "ipconfig", private_alloc = "dynamic",
|
|||
\description{
|
||||
Network interface configuration
|
||||
}
|
||||
\examples{
|
||||
nic_config()
|
||||
}
|
||||
\seealso{
|
||||
\link{create_vm}, \link{vm_config}
|
||||
}
|
||||
|
|
|
@ -34,6 +34,22 @@ nsg_rule(name, dest_port = "*", dest_addr = "*", dest_asgs = NULL,
|
|||
\description{
|
||||
Network security group configuration
|
||||
}
|
||||
\examples{
|
||||
nsg_config()
|
||||
nsg_config(list(nsg_rule_allow_ssh)) # for Linux
|
||||
nsg_config(list(nsg_rule_allow_rdp)) # for Windows
|
||||
nsg_config(list(nsg_rule_allow_http, nsg_rule_allow_https))
|
||||
|
||||
# a custom rule
|
||||
nsg_config(list(
|
||||
nsg_rule(
|
||||
name="whitelist",
|
||||
source_addr="114.198.100.0/24",
|
||||
access="allow",
|
||||
protocol="*"
|
||||
)
|
||||
))
|
||||
}
|
||||
\seealso{
|
||||
\link{create_vm}, \link{vm_config}, \link{vmss_config}, \link{nsg_rules} for some predefined security rules
|
||||
}
|
||||
|
|
|
@ -27,6 +27,13 @@ subnet_config(name = "subnet", addresses = "10.0.0.0/16",
|
|||
\description{
|
||||
Virtual network configuration
|
||||
}
|
||||
\examples{
|
||||
vnet_config()
|
||||
vnet_config(address_space="10.1.0.0/16")
|
||||
vnet_config(subnets=list(
|
||||
subnet_config("subnet", "10.0.0.0/24")
|
||||
))
|
||||
}
|
||||
\seealso{
|
||||
\link{create_vm}, \link{vm_config}, \link{vmss_config}
|
||||
}
|
||||
|
|
|
@ -103,6 +103,16 @@ test_that("Virtual network config works",
|
|||
)
|
||||
)
|
||||
)
|
||||
|
||||
vnet <- vnet_config("10.1.0.0/16")
|
||||
expect_identical(vnet$properties$subnets[[1]]$properties$addressPrefix, "10.1.0.0/16")
|
||||
|
||||
vnet <- vnet_config(
|
||||
address_space="10.1.0.0/16",
|
||||
subnets=list(subnet_config("mysubnet", addresses="10.0.0.0/24"))
|
||||
)
|
||||
expect_identical(vnet$properties$subnets[[1]]$properties$addressPrefix, "10.1.0.0/24")
|
||||
|
||||
})
|
||||
|
||||
test_that("Network interface config works",
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
context("Custom deployments")
|
||||
context("Manual deletion")
|
||||
|
||||
tenant <- Sys.getenv("AZ_TEST_TENANT_ID")
|
||||
app <- Sys.getenv("AZ_TEST_APP_ID")
|
||||
|
@ -67,28 +67,3 @@ test_that("Custom resource works",
|
|||
expect_true(is_empty(rg$list_resources()))
|
||||
})
|
||||
|
||||
test_that("Scaleset options work",
|
||||
{
|
||||
ssname <- paste0(sample(letters, 10, TRUE), collapse="")
|
||||
size <- "Standard_DS3_v2"
|
||||
opts <- scaleset_options(
|
||||
managed=FALSE,
|
||||
public=TRUE,
|
||||
low_priority=TRUE,
|
||||
delete_on_evict=TRUE,
|
||||
network_accel=TRUE,
|
||||
large_scaleset=TRUE,
|
||||
overprovision=FALSE
|
||||
)
|
||||
|
||||
vmss <- rg$create_vm_scaleset(ssname, user, instances=3, size=size, options=opts)
|
||||
expect_is(vmss, "az_vmss_template")
|
||||
|
||||
expect_is(vmss$get_public_ip_address(), "character")
|
||||
expect_is(vmss$get_vm_public_ip_addresses(), "character")
|
||||
expect_is(vmss$get_vm_private_ip_addresses(), "character")
|
||||
expect_true(is.null(vmss$identity))
|
||||
})
|
||||
|
||||
rg$delete(confirm=FALSE)
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
context("Custom deployments")
|
||||
|
||||
tenant <- Sys.getenv("AZ_TEST_TENANT_ID")
|
||||
app <- Sys.getenv("AZ_TEST_APP_ID")
|
||||
password <- Sys.getenv("AZ_TEST_PASSWORD")
|
||||
subscription <- Sys.getenv("AZ_TEST_SUBSCRIPTION")
|
||||
|
||||
if(tenant == "" || app == "" || password == "" || subscription == "")
|
||||
skip("Tests skipped: ARM credentials not set")
|
||||
|
||||
rgname <- paste0("vm", paste0(sample(letters, 10, TRUE), collapse=""))
|
||||
location <- "australiaeast"
|
||||
user <- user_config("username", "../resources/testkey.pub")
|
||||
size <- "Standard_DS1_v2"
|
||||
|
||||
rg <- AzureRMR::az_rm$
|
||||
new(tenant=tenant, app=app, password=password)$
|
||||
get_subscription(subscription)$
|
||||
create_resource_group(rgname, location)
|
||||
|
||||
test_that("Custom vnet works",
|
||||
{
|
||||
vmname <- paste0(sample(letters, 10, TRUE), collapse="")
|
||||
|
||||
# should detect and fix subnet mismatch
|
||||
vnet <- vnet_config(address_space="10.1.0.0/16")
|
||||
vm <- rg$create_vm(vmname, user, size, vnet=vnet)
|
||||
expect_is(vm, "az_vm_template")
|
||||
})
|
||||
|
||||
test_that("Scaleset options work",
|
||||
{
|
||||
ssname <- paste0(sample(letters, 10, TRUE), collapse="")
|
||||
size <- "Standard_DS3_v2"
|
||||
opts <- scaleset_options(
|
||||
managed=FALSE,
|
||||
public=TRUE,
|
||||
low_priority=TRUE,
|
||||
delete_on_evict=TRUE,
|
||||
network_accel=TRUE,
|
||||
large_scaleset=TRUE,
|
||||
overprovision=FALSE
|
||||
)
|
||||
|
||||
vmss <- rg$create_vm_scaleset(ssname, user, instances=3, size=size, options=opts)
|
||||
expect_is(vmss, "az_vmss_template")
|
||||
|
||||
expect_is(vmss$get_public_ip_address(), "character")
|
||||
expect_is(vmss$get_vm_public_ip_addresses(), "character")
|
||||
expect_is(vmss$get_vm_private_ip_addresses(), "character")
|
||||
expect_true(is.null(vmss$identity))
|
||||
})
|
||||
|
||||
rg$delete(confirm=FALSE)
|
||||
|
|
@ -24,8 +24,12 @@ test_that("Scaleset connection pool works",
|
|||
autoscaler=NULL, load_balancer=NULL)
|
||||
expect_is(vm, "az_vmss_template")
|
||||
|
||||
# sometimes deployment will return prematurely
|
||||
Sys.sleep(5)
|
||||
|
||||
inst <- vm$list_instances()
|
||||
expect_is(inst, "list")
|
||||
expect_length(inst, 5)
|
||||
|
||||
expect_message(vm$run_script("ls /tmp", id=names(inst)[1:2]), "Creating background pool")
|
||||
expect_true(exists("pool", AzureVM:::.AzureVM) && length(AzureVM:::.AzureVM$pool) == 2)
|
Загрузка…
Ссылка в новой задаче