diff --git a/azure-cli.pyproj b/azure-cli.pyproj
index d03725ea3..059f44a76 100644
--- a/azure-cli.pyproj
+++ b/azure-cli.pyproj
@@ -151,6 +151,9 @@
+
+ Code
+
Code
diff --git a/src/azure/cli/commands/_auto_command.py b/src/azure/cli/commands/_auto_command.py
index 320be63a3..6b08bbdf3 100644
--- a/src/azure/cli/commands/_auto_command.py
+++ b/src/azure/cli/commands/_auto_command.py
@@ -37,11 +37,8 @@ def _get_member(obj, path):
def _make_func(client_factory, member_path, return_type_or_func, unbound_func, extra_parameters):
def call_client(args):
client = client_factory(**args)
- for p in extra_parameters or []:
- param_name = p['name'].split()[0]
- param_name = re.sub('--', '', param_name)
- param_name = re.sub('-', '_', param_name)
- args.pop(param_name)
+ for param in extra_parameters.keys() if extra_parameters else []:
+ args.pop(param)
ops_instance = _get_member(client, member_path)
try:
@@ -156,8 +153,8 @@ def build_operation(command_name,
# append any 'extra' args needed (for example to obtain a client) that aren't required
# by the SDK.
if extra_parameters:
- for arg in extra_parameters:
- options.append(arg.copy())
+ for arg in extra_parameters.keys():
+ options.append(extra_parameters[arg].copy())
command_table[func] = {
'name': ' '.join([command_name, op.opname]),
diff --git a/src/command_modules/azure-cli-storage/azure/cli/command_modules/storage/_params.py b/src/command_modules/azure-cli-storage/azure/cli/command_modules/storage/_params.py
index 691f832e9..e53cf65b1 100644
--- a/src/command_modules/azure-cli-storage/azure/cli/command_modules/storage/_params.py
+++ b/src/command_modules/azure-cli-storage/azure/cli/command_modules/storage/_params.py
@@ -244,9 +244,9 @@ PARAMETER_ALIASES.update({
# SUPPLEMENTAL (EXTRA) PARAMETER SETS
-STORAGE_DATA_CLIENT_ARGS = [
- PARAMETER_ALIASES['account_name'],
- PARAMETER_ALIASES['account_key'],
- PARAMETER_ALIASES['connection_string'],
- PARAMETER_ALIASES['sas_token']
-]
+STORAGE_DATA_CLIENT_ARGS = {
+ 'account_name': PARAMETER_ALIASES['account_name'],
+ 'account_key': PARAMETER_ALIASES['account_key'],
+ 'connection_string': PARAMETER_ALIASES['connection_string'],
+ 'sas_token': PARAMETER_ALIASES['sas_token']
+}
diff --git a/src/command_modules/azure-cli-vm/azure/cli/command_modules/vm/_actions.py b/src/command_modules/azure-cli-vm/azure/cli/command_modules/vm/_actions.py
new file mode 100644
index 000000000..84ab6e100
--- /dev/null
+++ b/src/command_modules/azure-cli-vm/azure/cli/command_modules/vm/_actions.py
@@ -0,0 +1,29 @@
+import argparse
+import os
+import re
+
+class VMImageFieldAction(argparse.Action): #pylint: disable=too-few-public-methods
+ def __call__(self, parser, namespace, values, option_string=None):
+ image = values
+ match = re.match('([^:]*):([^:]*):([^:]*):([^:]*)', image)
+
+ if image.lower().endswith('.vhd'):
+ namespace.os_disk_uri = image
+ elif match:
+ namespace.os_type = 'Custom'
+ namespace.os_publisher = match.group(1)
+ namespace.os_offer = match.group(2)
+ namespace.os_sku = match.group(3)
+ namespace.os_version = match.group(4)
+ else:
+ namespace.os_type = image
+
+class VMSSHFieldAction(argparse.Action): #pylint: disable=too-few-public-methods
+ def __call__(self, parser, namespace, values, option_string=None):
+ ssh_value = values
+
+ if os.path.exists(ssh_value):
+ with open(ssh_value, 'r') as f:
+ namespace.ssh_key_value = f.read()
+ else:
+ namespace.ssh_key_value = ssh_value
diff --git a/src/command_modules/azure-cli-vm/azure/cli/command_modules/vm/_params.py b/src/command_modules/azure-cli-vm/azure/cli/command_modules/vm/_params.py
index b52e3ba9e..a748f6bbc 100644
--- a/src/command_modules/azure-cli-vm/azure/cli/command_modules/vm/_params.py
+++ b/src/command_modules/azure-cli-vm/azure/cli/command_modules/vm/_params.py
@@ -1,10 +1,14 @@
+import argparse
+
from azure.mgmt.compute import ComputeManagementClient, ComputeManagementClientConfiguration
from azure.mgmt.compute.models import VirtualHardDisk
-from azure.cli.commands import (COMMON_PARAMETERS as GLOBAL_COMMON_PARAMETERS, extend_parameter)
+from azure.cli.commands import COMMON_PARAMETERS as GLOBAL_COMMON_PARAMETERS, extend_parameter
from azure.cli.commands._command_creation import get_mgmt_service_client
-from azure.cli._locale import L
from azure.cli.command_modules.vm._validators import MinMaxValue
+from azure.cli.command_modules.vm._actions import VMImageFieldAction, VMSSHFieldAction
+from azure.cli._help_files import helps
+from azure.cli._locale import L
# FACTORIES
@@ -17,19 +21,16 @@ PARAMETER_ALIASES = GLOBAL_COMMON_PARAMETERS.copy()
PARAMETER_ALIASES.update({
'diskname': {
'name': '--name -n',
- 'dest': 'name',
'help': L('Disk name'),
},
'disksize': {
'name': '--disksize',
- 'dest': 'disksize',
'help': L('Size of disk (Gb)'),
'type': MinMaxValue(1, 1023),
'default': 1023
},
'lun': {
'name': '--lun',
- 'dest': 'lun',
'help': L('0-based logical unit number (LUN). Max value depends on the Virtual ' + \
'Machine size'),
'type': int,
@@ -38,4 +39,95 @@ PARAMETER_ALIASES.update({
'name': '--vhd',
'type': VirtualHardDisk
},
+ 'vm_name': {
+ 'name': '--vm-name',
+ 'dest': 'vm_name',
+ 'help': 'Name of Virtual Machine to update',
+ }
})
+
+VM_CREATE_PARAMETER_ALIASES = {
+ 'name': {
+ 'name': '--name -n'
+ },
+ 'os_disk_uri': {
+ 'name': '--os-disk-uri',
+ 'help': argparse.SUPPRESS
+ },
+ 'os_offer': {
+ 'name': '--os_offer',
+ 'help': argparse.SUPPRESS
+ },
+ 'os_publisher': {
+ 'name': '--os-publisher',
+ 'help': argparse.SUPPRESS
+ },
+ 'os_sku': {
+ 'name': '--os-sku',
+ 'help': argparse.SUPPRESS
+ },
+ 'os_type': {
+ 'name': '--os-type',
+ 'help': argparse.SUPPRESS
+ },
+ 'os_version': {
+ 'name': '--os-version',
+ 'help': argparse.SUPPRESS
+ },
+}
+
+# EXTRA PARAMETER SETS
+
+VM_CREATE_EXTRA_PARAMETERS = {
+ 'image': {
+ 'name': '--image',
+ 'help': 'The OS image. Supported values: Common OS (e.g. Win2012R2Datacenter), ' + \
+ 'URN (e.g. "publisher:offer:sku:version"), or existing VHD URI.',
+ 'action': VMImageFieldAction
+ },
+ 'ssh_key_value': {
+ 'name': '--ssh-key-value',
+ 'action': VMSSHFieldAction
+ }
+}
+
+VM_PATCH_EXTRA_PARAMETERS = {
+ 'resource_group_name':
+ extend_parameter(PARAMETER_ALIASES['resource_group_name'], required=True),
+ 'vm_name':
+ extend_parameter(PARAMETER_ALIASES['vm_name'], required=True)
+}
+
+# HELP PARAMETERS
+
+helps['vm create'] = """
+ type: command
+ short-summary: Create an Azure Virtual Machine
+ long-summary: See https://azure.microsoft.com/en-us/documentation/articles/virtual-machines-linux-quick-create-cli/ for an end-to-end tutorial
+ parameters:
+ - name: --image
+ type: string
+ required: false
+ short-summary: OS image
+ long-summary: |
+ Common OS types: CentOS, CoreOS, Debian, openSUSE, RHEL, SLES, UbuntuLTS,
+ Win2012R2Datacenter, Win2012Datacenter, Win2008R2SP1
+ Example URN: canonical:Ubuntu_Snappy_Core:15.04:2016.0318.1949
+ Example URI: http://.blob.core.windows.net/vhds/osdiskimage.vhd
+ populator-commands:
+ - az vm image list
+ - az vm image show
+ examples:
+ - name: Create a simple Windows Server VM with private IP address
+ text: >
+ az vm create --image Win2012R2Datacenter --admin-username myadmin --admin-password Admin_001
+ -l "West US" -g myvms --name myvm001
+ - name: Create a Linux VM with SSH key authentication, add a public DNS entry and add to an existing Virtual Network and Availability Set.
+ text: >
+ az vm create --image canonical:Ubuntu_Snappy_Core:15.04:2016.0318.1949
+ --admin-username myadmin --admin-password Admin_001 --authentication-type sshkey
+ --virtual-network-type existing --virtual-network-name myvnet --subnet-name default
+ --availability-set-type existing --availability-set-id myavailset
+ --public-ip-address-type new --dns-name-for-public-ip myGloballyUniqueVmDnsName
+ -l "West US" -g myvms --name myvm18o --ssh-key-value ""
+ """
diff --git a/src/command_modules/azure-cli-vm/azure/cli/command_modules/vm/custom.py b/src/command_modules/azure-cli-vm/azure/cli/command_modules/vm/custom.py
index e7d37227e..d2b2232e5 100644
--- a/src/command_modules/azure-cli-vm/azure/cli/command_modules/vm/custom.py
+++ b/src/command_modules/azure-cli-vm/azure/cli/command_modules/vm/custom.py
@@ -10,57 +10,32 @@ except ImportError:
from azure.mgmt.compute.models import DataDisk
from azure.mgmt.compute.models.compute_management_client_enums import DiskCreateOptionTypes
-from azure.cli._locale import L
from azure.cli.commands import CommandTable, LongRunningOperation, RESOURCE_GROUP_ARG_NAME
from azure.cli.commands._command_creation import get_mgmt_service_client
-from ._params import PARAMETER_ALIASES, _compute_client_factory
+from ._params import PARAMETER_ALIASES, VM_PATCH_EXTRA_PARAMETERS, _compute_client_factory
command_table = CommandTable()
-def vm_getter(args):
- ''' Retreive a VM based on the `args` passed in.
- '''
- client = _compute_client_factory(**args)
- result = client.virtual_machines.get(args.get(RESOURCE_GROUP_ARG_NAME), args.get('vm_name'))
- return result
+def _vm_get(**kwargs):
+ '''Retrieves a VM if a resource group and vm name are supplied.'''
+ vm_name = kwargs.get('vm_name')
+ resource_group_name = kwargs.get('resource_group_name')
+ client = _compute_client_factory()
+ return client.virtual_machines.get(resource_group_name, vm_name) \
+ if resource_group_name and vm_name else None
-def vm_setter(args, instance, start_msg, end_msg):
- '''Update the given Virtual Machine instance
- '''
+def _vm_set(instance, start_msg, end_msg):
+ '''Update the given Virtual Machine instance'''
instance.resources = None # Issue: https://github.com/Azure/autorest/issues/934
- client = _compute_client_factory(**args)
+ client = _compute_client_factory()
+ parsed_id = _parse_rg_name(instance.id)
poller = client.virtual_machines.create_or_update(
- resource_group_name=args.get(RESOURCE_GROUP_ARG_NAME),
- vm_name=args.get('vm_name'),
+ resource_group_name=parsed_id[0],
+ vm_name=parsed_id[1],
parameters=instance)
return LongRunningOperation(start_msg, end_msg)(poller)
-def patches_vm(start_msg, finish_msg):
- '''Decorator indicating that the decorated function modifies an existing Virtual Machine
- in Azure.
- It automatically adds arguments required to identify the Virtual Machine to be patched and
- handles the actual put call to the compute service, leaving the decorated function to only
- have to worry about the modifications it has to do.
- '''
- def wrapped(func):
- def invoke(args):
- instance = vm_getter(args)
- func(args, instance)
- vm_setter(args, instance, start_msg, finish_msg)
-
- # All Virtual Machines are identified with a resource group name/name pair, so
- # we add these parameters to all commands
- command_table[invoke]['arguments'].append(PARAMETER_ALIASES['resource_group_name'])
- command_table[invoke]['arguments'].append({
- 'name': '--vm-name -n',
- 'dest': 'vm_name',
- 'help': 'Name of Virtual Machine to update',
- 'required': True
- })
- return invoke
- return wrapped
-
def _load_images_from_aliases_doc(publisher, offer, sku):
target_url = ('https://raw.githubusercontent.com/Azure/azure-rest-api-specs/'
'master/arm-compute/quickstart-templates/aliases.json')
@@ -134,7 +109,8 @@ def _create_image_instance(publisher, offer, sku, version):
'offer': offer,
'sku': sku,
'version': version
- }
+ }
+
#
# Composite convenience commands for the CLI
#
@@ -150,23 +126,17 @@ def _parse_rg_name(strid):
class ConvenienceVmCommands(object): # pylint: disable=too-few-public-methods
- def __init__(self, **_):
- pass
+ def __init__(self, **kwargs):
+ self.vm = _vm_get(**kwargs)
def list(self, resource_group_name):
''' List Virtual Machines. '''
ccf = _compute_client_factory()
vm_list = ccf.virtual_machines.list(resource_group_name=resource_group_name) \
- if group else ccf.virtual_machines.list_all()
+ if resource_group_name else ccf.virtual_machines.list_all()
return list(vm_list)
-
- def list_vm_images(self,
- image_location=None,
- publisher=None,
- offer=None,
- sku=None,
- all=False):
+ def list_vm_images(self, image_location=None, publisher=None, offer=None, sku=None, all=False): # pylint: disable=redefined-builtin
'''vm image list
:param str location:Image location
:param str publisher:Image publisher name
@@ -247,34 +217,31 @@ class ConvenienceVmCommands(object): # pylint: disable=too-few-public-methods
return result
- #@command_table.command('vm disk attach-new',
- @patches_vm('Attaching disk', 'Disk attached')
- def attach_new_disk(self, lun, diskname, vhd, disksize=1023, **kwargs):
+ def attach_new_disk(self, lun, diskname, vhd, disksize=1023, **kwargs):
''' Attach a new disk to an existing Virtual Machine'''
- disk = DataDisk(lun=lun, vhd=vhd, name=kwargs.get('name'),
+ disk = DataDisk(lun=lun, vhd=vhd, name=diskname,
create_option=DiskCreateOptionTypes.empty,
disk_size_gb=disksize)
- kwargs.get('instance').storage_profile.data_disks.append(disk)
+ self.vm.storage_profile.data_disks.append(disk)
+ _vm_set(self.vm, 'Attaching disk', 'Disk attached')
- #@command_table.command('vm disk attach-existing',
- @patches_vm('Attaching disk', 'Disk attached')
def attach_existing_disk(self, lun, diskname, vhd, disksize=1023, **kwargs):
''' Attach an existing disk to an existing Virtual Machine '''
# TODO: figure out size of existing disk instead of making the default value 1023
- disk = DataDisk(lun=lun, vhd=vhd, name=kwargs.get('name'),
+ disk = DataDisk(lun=lun, vhd=vhd, name=diskname,
create_option=DiskCreateOptionTypes.attach,
disk_size_gb=disksize)
- kwargs.get('instance').storage_profile.data_disks.append(disk)
+ self.vm.storage_profile.data_disks.append(disk)
+ _vm_set(self.vm, 'Attaching disk', 'Disk attached')
- #@command_table.command('vm disk detach')
- @patches_vm('Detaching disk', 'Disk detached')
def detach_disk(self, diskname, **kwargs):
+ ''' Detach a disk from a Virtual Machine '''
# Issue: https://github.com/Azure/autorest/issues/934
- instance = kwargs.get('instance')
- instance.resources = None
+ self.vm.resources = None
try:
- disk = next(d for d in instance.storage_profile.data_disks
+ disk = next(d for d in self.vm.storage_profile.data_disks
if d.name == kwargs.get('name'))
- instance.storage_profile.data_disks.remove(disk)
+ self.vm.storage_profile.data_disks.remove(disk)
except StopIteration:
- raise RuntimeError("No disk with the name '%s' found" % args.get('name'))
+ raise RuntimeError("No disk with the name '{}' found".format(diskname))
+ _vm_set(self.vm, 'Detaching disk', 'Disk detached')
diff --git a/src/command_modules/azure-cli-vm/azure/cli/command_modules/vm/generated.py b/src/command_modules/azure-cli-vm/azure/cli/command_modules/vm/generated.py
index a56c987cf..70038680a 100644
--- a/src/command_modules/azure-cli-vm/azure/cli/command_modules/vm/generated.py
+++ b/src/command_modules/azure-cli-vm/azure/cli/command_modules/vm/generated.py
@@ -1,7 +1,3 @@
-import argparse
-import os
-import re
-
from azure.mgmt.compute.operations import (AvailabilitySetsOperations,
VirtualMachineExtensionImagesOperations,
VirtualMachineExtensionsOperations,
@@ -15,14 +11,14 @@ from azure.mgmt.compute.operations import (AvailabilitySetsOperations,
from azure.cli.commands._auto_command import build_operation, AutoCommandDefinition
from azure.cli.commands._command_creation import get_mgmt_service_client
from azure.cli.commands import CommandTable, LongRunningOperation
-from azure.cli._locale import L
from azure.cli.command_modules.vm.mgmt.lib import (VMCreationClient as VMClient,
VMCreationClientConfiguration
as VMClientConfig)
from azure.cli.command_modules.vm.mgmt.lib.operations import VMOperations
-from azure.cli._help_files import helps
+from azure.cli._locale import L
-from ._params import PARAMETER_ALIASES, _compute_client_factory
+from ._params import (PARAMETER_ALIASES, VM_CREATE_EXTRA_PARAMETERS, VM_CREATE_PARAMETER_ALIASES,
+ VM_PATCH_EXTRA_PARAMETERS, _compute_client_factory)
from .custom import ConvenienceVmCommands
command_table = CommandTable()
@@ -62,7 +58,7 @@ build_operation(
AutoCommandDefinition(ConvenienceVmCommands.attach_existing_disk, 'Object', 'attach-existing'),
AutoCommandDefinition(ConvenienceVmCommands.detach_disk, 'Object', 'detach'),
],
- command_table, PARAMETER_ALIASES)
+ command_table, PARAMETER_ALIASES, VM_PATCH_EXTRA_PARAMETERS)
build_operation(
'vm extension', 'virtual_machine_extensions', _compute_client_factory,
@@ -86,7 +82,7 @@ build_operation(
command_table, PARAMETER_ALIASES)
build_operation(
- 'vm usage', 'usage',_compute_client_factory,
+ 'vm usage', 'usage', _compute_client_factory,
[
AutoCommandDefinition(UsageOperations.list, '[Usage]'),
],
@@ -161,116 +157,15 @@ build_operation(
],
command_table, PARAMETER_ALIASES)
-vm_param_aliases = {
- 'name': {
- 'name': '--name -n'
- },
- 'os_disk_uri': {
- 'name': '--os-disk-uri',
- 'help': argparse.SUPPRESS
- },
- 'os_offer': {
- 'name': '--os_offer',
- 'help': argparse.SUPPRESS
- },
- 'os_publisher': {
- 'name': '--os-publisher',
- 'help': argparse.SUPPRESS
- },
- 'os_sku': {
- 'name': '--os-sku',
- 'help': argparse.SUPPRESS
- },
- 'os_type': {
- 'name': '--os-type',
- 'help': argparse.SUPPRESS
- },
- 'os_version': {
- 'name': '--os-version',
- 'help': argparse.SUPPRESS
- },
- }
-
-class VMImageFieldAction(argparse.Action): #pylint: disable=too-few-public-methods
- def __call__(self, parser, namespace, values, option_string=None):
- image = values
- match = re.match('([^:]*):([^:]*):([^:]*):([^:]*)', image)
-
- if image.lower().endswith('.vhd'):
- namespace.os_disk_uri = image
- elif match:
- namespace.os_type = 'Custom'
- namespace.os_publisher = match.group(1)
- namespace.os_offer = match.group(2)
- namespace.os_sku = match.group(3)
- namespace.os_version = match.group(4)
- else:
- namespace.os_type = image
-
-class VMSSHFieldAction(argparse.Action): #pylint: disable=too-few-public-methods
- def __call__(self, parser, namespace, values, option_string=None):
- ssh_value = values
-
- if os.path.exists(ssh_value):
- with open(ssh_value, 'r') as f:
- namespace.ssh_key_value = f.read()
- else:
- namespace.ssh_key_value = ssh_value
-
-extra_parameters = [
- {
- 'name': '--image',
- 'help': 'The OS image. Supported values: Common OS (e.g. Win2012R2Datacenter), URN (e.g. "publisher:offer:sku:version"), or existing VHD URI.',
- 'action': VMImageFieldAction
- },
- {
- 'name': '--ssh-key-value',
- 'action': VMSSHFieldAction
- }
- ]
-
-helps['vm create'] = """
- type: command
- short-summary: Create an Azure Virtual Machine
- long-summary: See https://azure.microsoft.com/en-us/documentation/articles/virtual-machines-linux-quick-create-cli/ for an end-to-end tutorial
- parameters:
- - name: --image
- type: string
- required: false
- short-summary: OS image
- long-summary: |
- Common OS types: CentOS, CoreOS, Debian, openSUSE, RHEL, SLES, UbuntuLTS,
- Win2012R2Datacenter, Win2012Datacenter, Win2008R2SP1
- Example URN: canonical:Ubuntu_Snappy_Core:15.04:2016.0318.1949
- Example URI: http://.blob.core.windows.net/vhds/osdiskimage.vhd
- populator-commands:
- - az vm image list
- - az vm image show
- examples:
- - name: Create a simple Windows Server VM with private IP address
- text: >
- az vm create --image Win2012R2Datacenter --admin-username myadmin --admin-password Admin_001
- -l "West US" -g myvms --name myvm001
- - name: Create a Linux VM with SSH key authentication, add a public DNS entry and add to an existing Virtual Network and Availability Set.
- text: >
- az vm create --image canonical:Ubuntu_Snappy_Core:15.04:2016.0318.1949
- --admin-username myadmin --admin-password Admin_001 --authentication-type sshkey
- --virtual-network-type existing --virtual-network-name myvnet --subnet-name default
- --availability-set-type existing --availability-set-id myavailset
- --public-ip-address-type new --dns-name-for-public-ip myGloballyUniqueVmDnsName
- -l "West US" -g myvms --name myvm18o --ssh-key-value ""
- """
-
build_operation(
- 'vm', 'vm', lambda _: get_mgmt_service_client(VMClient, VMClientConfig),
+ 'vm', 'vm', lambda **_: get_mgmt_service_client(VMClient, VMClientConfig),
[
- AutoCommandDefinition(VMOperations.create_or_update,
- LongRunningOperation(L('Creating virtual machine'), L('Virtual machine created')),
- 'create')
+ AutoCommandDefinition(
+ VMOperations.create_or_update,
+ LongRunningOperation(L('Creating virtual machine'), L('Virtual machine created')),
+ 'create')
],
- command_table,
- vm_param_aliases,
- extra_parameters)
+ command_table, VM_CREATE_PARAMETER_ALIASES, VM_CREATE_EXTRA_PARAMETERS)
build_operation(
'vm image', None, ConvenienceVmCommands,