Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 12 additions & 12 deletions src/azure-cli/azure/cli/command_modules/vm/_format.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,19 +38,19 @@ def transform_vm_create_output(result):
from azure.mgmt.core.tools import parse_resource_id
from collections import OrderedDict
try:
resource_group = getattr(result, 'resource_group', None) or parse_resource_id(result.id)['resource_group']
output = OrderedDict([('id', result.id),
resource_group = result.get('resource_group', None) or parse_resource_id(result['id'])['resource_group']
output = OrderedDict([('id', result['id']),
('resourceGroup', resource_group),
('powerState', result.power_state),
('publicIpAddress', result.public_ips),
('fqdns', result.fqdns),
('privateIpAddress', result.private_ips),
('macAddress', result.mac_addresses),
('location', result.location)])
if getattr(result, 'identity', None):
output['identity'] = result.identity
if hasattr(result, 'zones'): # output 'zones' column even the property value is None
output['zones'] = result.zones[0] if result.zones else ''
('powerState', result.get('powerState', '')),
('publicIpAddress', result.get('publicIps', '')),
('fqdns', result.get('fqdns', '')),
('privateIpAddress', result.get('privateIps', '')),
('macAddress', result.get('macAddresses', '')),
('location', result.get('location', ''))])
if result.get('identity', None):
output['identity'] = result['identity']
if 'zones' in result: # output 'zones' column even the property value is None
output['zones'] = result['zones'][0] if result['zones'] else ''
return output
except AttributeError:
from msrest.pipeline import ClientRawResponse
Expand Down
43 changes: 0 additions & 43 deletions src/azure-cli/azure/cli/command_modules/vm/_help.py
Original file line number Diff line number Diff line change
Expand Up @@ -1058,33 +1058,6 @@
az vm boot-diagnostics get-boot-log-uris -g MyResourceGroup -n MyVirtualMachine
"""

helps['vm capture'] = """
type: command
short-summary: Capture information for a stopped VM.
long-summary: 'For an end-to-end tutorial, see https://learn.microsoft.com/azure/virtual-machines/linux/capture-image'
parameters:
- name: --vhd-name-prefix
type: string
short-summary: The VHD name prefix specify for the VM disks.
- name: --storage-container
short-summary: The storage account container name in which to save the disks.
- name: --overwrite
short-summary: Overwrite the existing disk file.
examples:
- name: Deallocate, generalize, and capture a stopped virtual machine.
text: |
az vm deallocate -g MyResourceGroup -n MyVm
az vm generalize -g MyResourceGroup -n MyVm
az vm capture -g MyResourceGroup -n MyVm --vhd-name-prefix MyPrefix
- name: Deallocate, generalize, and capture multiple stopped virtual machines.
text: |
vms_ids=$(az vm list -g MyResourceGroup --query "[].id" -o tsv)
az vm deallocate --ids {vms_ids}
az vm generalize --ids {vms_ids}
az vm capture --ids {vms_ids} --vhd-name-prefix MyPrefix

"""

helps['vm create'] = """
type: command
short-summary: Create an Azure Virtual Machine.
Expand Down Expand Up @@ -1188,22 +1161,6 @@
az vm create -n MyVm -g MyResourceGroup --image /CommunityGalleries/{gallery_unique_name}/Images/{image}/Versions/{version}
"""

helps['vm delete'] = """
type: command
short-summary: Delete a VM.
parameters:
- name: --force-deletion
short-summary: Optional parameter to force delete virtual machines. Default value is None.
examples:
- name: Delete a VM without a prompt for confirmation.
text: >
az vm delete -g MyResourceGroup -n MyVm --yes
- name: Delete all VMs in a resource group.
text: >
az vm delete --ids $(az vm list -g MyResourceGroup --query "[].id" -o tsv)

"""

helps['vm diagnostics'] = """
type: group
short-summary: Configure the Azure Virtual Machine diagnostics extension.
Expand Down
2 changes: 0 additions & 2 deletions src/azure-cli/azure/cli/command_modules/vm/_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -409,8 +409,6 @@ def load_arguments(self, _):
c.argument('nsg_rule', help='NSG rule to create when creating a new NSG. Defaults to open ports for allowing RDP on Windows and allowing SSH on Linux.', arg_group='Network', arg_type=get_enum_type(['RDP', 'SSH']))
c.argument('application_security_groups', min_api='2017-09-01', nargs='+', options_list=['--asgs'], help='Space-separated list of existing application security groups to associate with the VM.', arg_group='Network')
c.argument('workspace', is_preview=True, arg_group='Monitor', help='Name or ID of Log Analytics Workspace. If you specify the workspace through its name, the workspace should be in the same resource group with the vm, otherwise a new workspace will be created.')
with self.argument_context('vm capture') as c:
c.argument('overwrite', action='store_true')

with self.argument_context('vm update') as c:
c.argument('os_disk', min_api='2017-12-01', help="Managed OS disk ID or name to swap to")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,13 @@

from .__cmd_group import *
from ._assess_patches import *
from ._capture import *
from ._convert import *
from ._deallocate import *
from ._delete import *
from ._generalize import *
from ._list import *
from ._list_all import *
from ._list_sizes import *
from ._list_skus import *
from ._list_vm_resize_options import *
Expand All @@ -25,3 +29,4 @@
from ._simulate_eviction import *
from ._start import *
from ._update import *
from ._wait import *
253 changes: 253 additions & 0 deletions src/azure-cli/azure/cli/command_modules/vm/aaz/latest/vm/_capture.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,253 @@
# --------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
#
# Code generated by aaz-dev-tools
# --------------------------------------------------------------------------------------------

# pylint: skip-file
# flake8: noqa

from azure.cli.core.aaz import *


@register_command(
"vm capture",
)
class Capture(AAZCommand):
"""Capture information for a stopped VM.

For an end-to-end tutorial, see https://learn.microsoft.com/azure/virtual-machines/linux/capture-image

:example: Deallocate, generalize, and capture a stopped virtual machine.
az vm deallocate -g MyResourceGroup -n MyVm
az vm generalize -g MyResourceGroup -n MyVm
az vm capture -g MyResourceGroup -n MyVm --vhd-name-prefix MyPrefix

:example: Deallocate, generalize, and capture multiple stopped virtual machines.
az vm deallocate --ids MyVmIds
az vm generalize --ids MyVmIds
az vm capture --ids MyVmIds --vhd-name-prefix MyPrefix
"""

_aaz_info = {
"version": "2024-11-01",
"resources": [
["mgmt-plane", "/subscriptions/{}/resourcegroups/{}/providers/microsoft.compute/virtualmachines/{}/capture", "2024-11-01"],
]
}

AZ_SUPPORT_NO_WAIT = True

def _handler(self, command_args):
super()._handler(command_args)
return self.build_lro_poller(self._execute_operations, self._output)

_args_schema = None

@classmethod
def _build_arguments_schema(cls, *args, **kwargs):
if cls._args_schema is not None:
return cls._args_schema
cls._args_schema = super()._build_arguments_schema(*args, **kwargs)

# define Arg Group ""

_args_schema = cls._args_schema
_args_schema.resource_group = AAZResourceGroupNameArg(
required=True,
)
_args_schema.name = AAZStrArg(
options=["-n", "--name"],
help="The name of the virtual machine.",
required=True,
id_part="name",
)

# define Arg Group "Parameters"

_args_schema = cls._args_schema
_args_schema.storage_container = AAZStrArg(
options=["--storage-container"],
arg_group="Parameters",
help="The storage account container name in which to save the disks.",
required=True,
default="vhds",
)
_args_schema.overwrite = AAZBoolArg(
options=["--overwrite"],
arg_group="Parameters",
help="Overwrite the existing disk file.",
required=True,
default=True,
)
_args_schema.vhd_name_prefix = AAZStrArg(
options=["--vhd-name-prefix"],
arg_group="Parameters",
help="The VHD name prefix specify for the VM disks.",
required=True,
)
return cls._args_schema

def _execute_operations(self):
self.pre_operations()
yield self.VirtualMachinesCapture(ctx=self.ctx)()
self.post_operations()

@register_callback
def pre_operations(self):
pass

@register_callback
def post_operations(self):
pass

def _output(self, *args, **kwargs):
result = self.deserialize_output(self.ctx.vars.instance, client_flatten=True)
return result

class VirtualMachinesCapture(AAZHttpOperation):
CLIENT_TYPE = "MgmtClient"

def __call__(self, *args, **kwargs):
request = self.make_request()
session = self.client.send_request(request=request, stream=False, **kwargs)
if session.http_response.status_code in [202]:
return self.client.build_lro_polling(
self.ctx.args.no_wait,
session,
self.on_200,
self.on_error,
lro_options={"final-state-via": "location"},
path_format_arguments=self.url_parameters,
)
if session.http_response.status_code in [200]:
return self.client.build_lro_polling(
self.ctx.args.no_wait,
session,
self.on_200,
self.on_error,
lro_options={"final-state-via": "location"},
path_format_arguments=self.url_parameters,
)

return self.on_error(session.http_response)

@property
def url(self):
return self.client.format_url(
"/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/virtualMachines/{vmName}/capture",
**self.url_parameters
)

@property
def method(self):
return "POST"

@property
def error_format(self):
return "ODataV4Format"

@property
def url_parameters(self):
parameters = {
**self.serialize_url_param(
"resourceGroupName", self.ctx.args.resource_group,
required=True,
),
**self.serialize_url_param(
"subscriptionId", self.ctx.subscription_id,
required=True,
),
**self.serialize_url_param(
"vmName", self.ctx.args.name,
required=True,
),
}
return parameters

@property
def query_parameters(self):
parameters = {
**self.serialize_query_param(
"api-version", "2024-11-01",
required=True,
),
}
return parameters

@property
def header_parameters(self):
parameters = {
**self.serialize_header_param(
"Content-Type", "application/json",
),
**self.serialize_header_param(
"Accept", "application/json",
),
}
return parameters

@property
def content(self):
_content_value, _builder = self.new_content_builder(
self.ctx.args,
typ=AAZObjectType,
typ_kwargs={"flags": {"required": True, "client_flatten": True}}
)
_builder.set_prop("destinationContainerName", AAZStrType, ".storage_container", typ_kwargs={"flags": {"required": True}})
_builder.set_prop("overwriteVhds", AAZBoolType, ".overwrite", typ_kwargs={"flags": {"required": True}})
_builder.set_prop("vhdPrefix", AAZStrType, ".vhd_name_prefix", typ_kwargs={"flags": {"required": True}})

return self.serialize_content(_content_value)

def on_200(self, session):
data = self.deserialize_http_content(session)
self.ctx.set_var(
"instance",
data,
schema_builder=self._build_schema_on_200
)

_schema_on_200 = None

@classmethod
def _build_schema_on_200(cls):
if cls._schema_on_200 is not None:
return cls._schema_on_200

cls._schema_on_200 = AAZObjectType()

_schema_on_200 = cls._schema_on_200
_schema_on_200["$schema"] = AAZStrType(
flags={"read_only": True},
)
_schema_on_200.content_version = AAZStrType(
serialized_name="contentVersion",
flags={"read_only": True},
)
_schema_on_200.id = AAZStrType()
_schema_on_200.parameters = AAZDictType(
flags={"read_only": True},
)
_schema_on_200.resources = AAZListType(
flags={"read_only": True},
)

parameters = cls._schema_on_200.parameters
parameters.Element = AAZAnyType()

resources = cls._schema_on_200.resources
resources.Element = AAZDictType()

_element = cls._schema_on_200.resources.Element
_element.Element = AAZAnyType()

return cls._schema_on_200


class _CaptureHelper:
"""Helper class for Capture"""


__all__ = ["Capture"]
Loading
Loading