Skip to content
Draft
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
54 changes: 54 additions & 0 deletions src/serial-console/HISTORY.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
Release History
===============
1.0.0b4
++++++
* Fixed `az serial-console connect` crashing with `ValueError: No value for given attribute` when the VM's boot diagnostics storage account is not accessible in the current subscription.

1.0.0b3
++++++
* Fixed an issue where admin commands were not being sent when the VM was using a custom boot diagnostics storage account.

1.0.0b2
++++++
* Changed to 2024 API version, fixes Disable API to track "properties". Essentially return to 2018 format

1.0.0b1
++++++
* Migrated to a new authentication flow to enhance overall security

0.1.8
++++++
* Changed first message flow, fixed typo

0.1.7
++++++
* Preparation for the new websocket authentication mechanism

0.1.6
++++++
* Fix pair region mapping for eastus to westus

0.1.5
++++++
* Fix resource group for custom storage account

0.1.4
++++++
* Fix repeating loading message
* Bump websocket-client version

0.1.3
++++++
* Change to use different region for url calls when custom storage account firewalls are enabled

0.1.2
++++++
* Change to make custom boot diagnostics optional

0.1.1
++++++
* Change to require custom boot diagnostics

0.1.0
++++++
* Initial release.
35 changes: 35 additions & 0 deletions src/serial-console/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Azure CLI Serial Console Extension #
This is a extension for Serial Console Connections

### How to use ###
Install this extension using the CLI command below
```
az extension add --name serial-console
```

### Included Features ###
#### Connect to the text-based Serial Console of a VM or VMSS Instance ####
To exit serial console type Ctrl + ] and then q. To send an NMI/SysRq/Reset type Ctrl + ] and then n/s/r respectively.
```
az serial-console connect -n MyVM -g MyResourceGroup
```
#### Enable the serial console service for an entire subscription ####
```
az serial-console enable
```
#### Disable the serial console service for an entire subscription ####
```
az serial-console disable
```
#### Send a Non-Maskable Interrupt (NMI) to a VM or VMSS Instance ####
```
az serial-console send nmi -n MyVM -g MyResourceGroup
```
#### Send SysRq sequence to a VM or VMSS Instance ####
```
az serial-console send sysrq -n MyVM -g MyResourceGroup --input c
```
#### Perform a "hard" restart of the VM or VMSS Instance ####
```
az serial-console send reset -n MyVM -g MyResourceGroup
```
28 changes: 28 additions & 0 deletions src/serial-console/azext_serialconsole/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# --------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------

from azure.cli.core import AzCommandsLoader
from azext_serialconsole._help import helps # pylint: disable=unused-import


class SerialconsoleCommandsLoader(AzCommandsLoader):

def __init__(self, cli_ctx=None):
from azure.cli.core.commands import CliCommandType
serialconsole_custom = CliCommandType(
operations_tmpl='azext_serialconsole.custom#{}')
super().__init__(cli_ctx=cli_ctx, custom_command_type=serialconsole_custom)

def load_command_table(self, args):
from azext_serialconsole.commands import load_command_table
load_command_table(self, args)
return self.command_table

def load_arguments(self, command):
from azext_serialconsole._params import load_arguments
load_arguments(self, command)


COMMAND_LOADER_CLS = SerialconsoleCommandsLoader
49 changes: 49 additions & 0 deletions src/serial-console/azext_serialconsole/_arm_endpoints.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# --------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------


class ArmEndpoints: # pylint: disable=too-few-public-methods
region_prefix_pairings = {'australiacentral': 'australiaeast',
'australiaeast': 'australiacentral',
'brazilsouth': 'brazilsoutheast',
'brazilsoutheast': 'brazilsouth',
'canadacentral': 'canadaeast',
'canadaeast': 'canadacentral',
'centralindia': 'southindia',
'centralus': 'westcentralus',
'centraluseuap': 'eastus2euap',
'eastasia': 'southeastasia',
'eastus': 'westus',
'eastus2': 'westus2', # pairing eastus2 + westus2 ensure that INT works as expected
'eastus2euap': 'centraluseuap',
'francecentral': 'francesouth',
'francesouth': 'francecentral',
'germanynorth': 'germanywestcentral',
'germanywestcentral': 'germanynorth',
'japaneast': 'japanwest',
'japanwest': 'japaneast',
'koreacentral': 'koreasouth',
'koreasouth': 'koreacentral',
'northeurope': 'westeurope',
'norwayeast': 'norwaywest',
'norwaywest': 'norwayeast',
# 'southafricanorth': 'southafricawest' is not yet deployed
'southeastasia': 'eastasia',
'southindia': 'centralindia',
'swedencentral': 'swedensouth',
'swedensouth': 'swedencentral',
'switzerlandnorth': 'switzerlandwest',
'switzerlandwest': 'switzerlandnorth',
'uaecentral': 'uaenorth',
'uaenorth': 'uaecentral',
'uksouth': 'ukwest',
'ukwest': 'uksouth',
'westcentralus': 'centralus',
'westeurope': 'northeurope',
'westus': 'eastus',
'westus2': 'eastus2',
'usgovarizona': 'usgoveast', # usgoveast == usgovvirginia
'usgovvirginia': 'usgovsw', # usgovsw == usgovarizona
}
29 changes: 29 additions & 0 deletions src/serial-console/azext_serialconsole/_client_factory.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# --------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------

from azure.cli.core.profiles import ResourceType


def _compute_client_factory(cli_ctx, **kwargs):
from azure.cli.core.commands.client_factory import get_mgmt_service_client
return get_mgmt_service_client(cli_ctx, ResourceType.MGMT_COMPUTE,
subscription_id=kwargs.get('subscription_id'),
aux_subscriptions=kwargs.get('aux_subscriptions'))


def cf_serialconsole(cli_ctx, **kwargs):
from azure.cli.core.commands.client_factory import get_mgmt_service_client
from azext_serialconsole.vendored_sdks.serialconsole import MicrosoftSerialConsoleClient
return get_mgmt_service_client(cli_ctx,
MicrosoftSerialConsoleClient, **kwargs)


def cf_serial_port(cli_ctx, **kwargs):
return cf_serialconsole(cli_ctx, **kwargs).serial_ports


def storage_client_factory(cli_ctx, *_):
from azure.cli.core.commands.client_factory import get_mgmt_service_client
return get_mgmt_service_client(cli_ctx, ResourceType.MGMT_STORAGE)
136 changes: 136 additions & 0 deletions src/serial-console/azext_serialconsole/_help.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
# coding=utf-8
# --------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------

from knack.help_files import helps # pylint: disable=unused-import


helps['serial-console'] = """
type: group
short-summary: Connect to the Serial Console of a Linux/Windows Virtual Machine or VMSS Instance.
"""

helps['serial-console send'] = """
type: group
short-summary: Send NMI/SysRq/Reset to a VM or VMSS Instance.
"""

helps['serial-console connect'] = """
type: command
short-summary: Connect to Serial Console VM or VMSS Instance
long-summary: >
This command provides access to a text-based console for Linux and Windows virtual machines (VMs) and virtual machine scale set instances. This serial connection connects to the ttys0 serial port of the VM or virtual machine scale set instance, providing access to it independent of the network or operating system state. To exit serial console type Ctrl + ] and then q. To send an NMI/SysRq/Reset type Ctrl + ] and then n/s/r respectively.
parameters:
- name: --name -n
short-summary: Name of the Virtual Machine or Virtual Machine Scale Set.
- name: --resource-group -g
short-summary: Name of resource group. You can configure the default group using `az configure --defaults group=<name>`.
- name: --instance-id
short-summary: ID of VMSS instance. Not needed when connecting to the serialport of a Virtual Machine.
- name: --subscription
short-summary: Name or ID of subscription. You can configure the default subscription using az account set -s NAME_OR_ID.
examples:
- name: Connect to Serial Console of a VM
text: >
az serial-console connect -n MyVM -g MyResourceGroup
- name: Connect to Serial Console of a VMSS Instance with ID 2
text: >
az serial-console connect -n MyVMSS -g MyResourceGroup --instance-id 2
"""

helps['serial-console enable'] = """
type: command
short-summary: Enable the serial console service for an entire subscription.
parameters:
- name: --subscription
short-summary: Name or ID of subscription. You can configure the default subscription using az account set -s NAME_OR_ID.
examples:
- name: Enable Serial Console for a subscription
text: >
az serial-console enable
"""

helps['serial-console disable'] = """
type: command
short-summary: Disable the serial console service for an entire subscription.
parameters:
- name: --subscription
short-summary: Name or ID of subscription. You can configure the default subscription using az account set -s NAME_OR_ID.
examples:
- name: Disable Serial Console for a subscription
text: >
az serial-console disable
"""

helps['serial-console send nmi'] = """
type: command
short-summary: Send a Non-Maskable Interrupt (NMI) to a VM or VMSS Instance
long-summary: >
A Non-Maskable Interrupt (NMI) is used in debugging scenarios and is designed to crash your target Virtual Machine.
parameters:
- name: --name -n
short-summary: Name of the Virtual Machine or Virtual Machine Scale Set.
- name: --resource-group -g
short-summary: Name of resource group. You can configure the default group using `az configure --defaults group=<name>`.
- name: --instance-id
short-summary: ID of VMSS instance. Not needed when connecting to the serialport of a Virtual Machine.
- name: --subscription
short-summary: Name or ID of subscription. You can configure the default subscription using az account set -s NAME_OR_ID.
examples:
- name: Send NMI to VM
text: >
az serial-console send nmi -n MyVM -g MyResourceGroup
- name: Send NMI to VMSS Instance with ID 2
text: >
az serial-console send nmi -n MyVMSS -g MyResourceGroup --instance-id 2
"""

helps['serial-console send sysrq'] = """
type: command
short-summary: Send SysRq sequence to a VM or VMSS Instance
long-summary:
A SysRq is a sequence of keys understood by the Linux operation system kernel, which can trigger a set of pre-defined actions. These commands are often used when virtual machine troubleshooting or recovery can't be performed through traditional administration (for example, if the VM is not responding).
parameters:
- name: --name -n
short-summary: Name of the Virtual Machine or Virtual Machine Scale Set.
- name: --resource-group -g
short-summary: Name of resource group. You can configure the default group using `az configure --defaults group=<name>`.
- name: --instance-id
short-summary: ID of VMSS instance. Not needed when connecting to the serialport of a Virtual Machine.
- name: --subscription
short-summary: Name or ID of subscription. You can configure the default subscription using az account set -s NAME_OR_ID.
- name: --input
short-summary: Input key to send over serial console. Must be one character.
examples:
- name: Send SysRq to VM to crash system
text: >
az serial-console send sysrq -n MyVM -g MyResourceGroup --input c
- name: Send SysRq to VMSS Instance with ID 2 to crash system
text: >
az serial-console send sysrq -n MyVMSS -g MyResourceGroup --instance-id 2 --input c
"""

helps['serial-console send reset'] = """
type: command
short-summary: Perform a "hard" restart of the VM or VMSS Instance
long-summary: >
This results in a "hard" restart, like powering the computer down, then back up again. This can result in data loss in the virtual machine. You should only perform this operation if a graceful restart is not effective.
parameters:
- name: --name -n
short-summary: Name of the Virtual Machine or Virtual Machine Scale Set.
- name: --resource-group -g
short-summary: Name of resource group. You can configure the default group using `az configure --defaults group=<name>`.
- name: --instance-id
short-summary: ID of VMSS instance. Not needed when connecting to the serialport of a Virtual Machine.
- name: --subscription
short-summary: Name or ID of subscription. You can configure the default subscription using az account set -s NAME_OR_ID.
examples:
- name: Hard reset a VM
text: >
az serial-console send reset -n MyVM -g MyResourceGroup
- name: Hard rest a VMSS Instance with ID 2
text: >
az serial-console send reset -n MyVMSS -g MyResourceGroup --instance-id 2
"""
29 changes: 29 additions & 0 deletions src/serial-console/azext_serialconsole/_params.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# --------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------
# pylint: disable=line-too-long

from knack.arguments import CLIArgumentType


name_arg_type = CLIArgumentType(
options_list=('--name', '-n'), help='Name of the VM or VMSS')
vmss_instance_arg_type = CLIArgumentType(
options_list=('--instance-id'),
help='ID of VMSS instance. Not needed when connecting to the serial port of a VM')
sysrq_input_arg_type = CLIArgumentType(
options_list=('--input'), help='SysRq Input Key')


def load_arguments(self, _):

from azure.cli.core.commands.parameters import resource_group_name_type

with self.argument_context('serial-console') as c:
c.argument('resource_group_name', arg_type=resource_group_name_type)
c.argument('vm_vmss_name', arg_type=name_arg_type)
c.argument('vmss_instanceid', arg_type=vmss_instance_arg_type)

with self.argument_context('serial-console send sysrq') as c:
c.argument('sysrqinput', arg_type=sysrq_input_arg_type)
4 changes: 4 additions & 0 deletions src/serial-console/azext_serialconsole/azext_metadata.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"azext.isPreview": true,
"azext.minCliCoreVersion": "2.15.0"
}
17 changes: 17 additions & 0 deletions src/serial-console/azext_serialconsole/commands.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# --------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------


def load_command_table(self, _):

with self.command_group('serial-console') as g:
g.custom_command('connect', 'connect_serialconsole')
g.custom_command('enable', 'enable_serialconsole')
g.custom_command('disable', 'disable_serialconsole')

with self.command_group('serial-console send') as g:
g.custom_command('nmi', 'send_nmi_serialconsole')
g.custom_command('reset', 'send_reset_serialconsole')
g.custom_command('sysrq', 'send_sysrq_serialconsole')
Loading
Loading