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

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
# Licensed under the MIT License. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------


def dms_client_factory(cli_ctx, *_):
from azure.cli.core.commands.client_factory import get_mgmt_service_client
from azure.mgmt.datamigration import DataMigrationManagementClient
Expand All @@ -24,3 +23,10 @@ def dms_cf_projects(cli_ctx, *_):

def dms_cf_tasks(cli_ctx, *_):
return dms_client_factory(cli_ctx).tasks


def get_resource_groups_client(cli_ctx, subscription_id=None):
from azure.cli.core.commands.client_factory import get_mgmt_service_client
from azure.cli.core.profiles import ResourceType
return get_mgmt_service_client(cli_ctx, ResourceType.MGMT_RESOURCE_RESOURCES,
subscription_id=subscription_id).resource_groups
16 changes: 10 additions & 6 deletions src/azure-cli/azure/cli/command_modules/dms/_help.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
examples:
- name: Create an instance of DMS.
text: >
az dms create -l westus -n mydms -g myresourcegroup --sku-name Basic_2vCores --subnet /subscriptions/{vnetSubscriptionId}/resourceGroups/{vnetResourceGroup}/providers/Microsoft.Network/virtualNetworks/{vnetName}/subnets/{subnetName} --tags tagName1=tagValue1 tagWithNoValue
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we mention above that this parameter is available, although it is optional and it defaults to the resource group location? Since resource groups have global scope, someone may wish to create "MySQL migrations" resource group and add a few DMS services in multiple regions, for example. And it is not clear how this could be done from the help.

az dms create -n mydms -g myresourcegroup --sku-name Basic_2vCores --subnet /subscriptions/{vnetSubscriptionId}/resourceGroups/{vnetResourceGroup}/providers/Microsoft.Network/virtualNetworks/{vnetName}/subnets/{subnetName} --tags tagName1=tagValue1 tagWithNoValue
"""

helps['dms delete'] = """
Expand Down Expand Up @@ -122,13 +122,13 @@
examples:
- name: Create a SQL to SQLDB project for a DMS instance.
text: >
az dms project create -l westus -n sqlproject -g myresourcegroup --service-name mydms --source-platform SQL --target-platform SQLDB --tags tagName1=tagValue1 tagWithNoValue
az dms project create -n sqlproject -g myresourcegroup --service-name mydms --source-platform SQL --target-platform SQLDB --tags tagName1=tagValue1 tagWithNoValue
- name: Create a PostgreSql to AzureDbForPostgreSql project for a DMS instance.
text: >
az dms project create -l westus -n pgproject -g myresourcegroup --service-name mydms --source-platform PostgreSQL --target-platform AzureDbForPostgreSQL --tags tagName1=tagValue1 tagWithNoValue
az dms project create -n pgproject -g myresourcegroup --service-name mydms --source-platform PostgreSQL --target-platform AzureDbForPostgreSQL --tags tagName1=tagValue1 tagWithNoValue
- name: Create a MySQL to AzureDbForMySQL project for a DMS instance.
text: >
az dms project create -l westus -n mysqlproject -g myresourcegroup --service-name mydms --source-platform MySQL --target-platform AzureDbForMySQL --tags tagName1=tagValue1 tagWithNoValue
az dms project create -n mysqlproject -g myresourcegroup --service-name mydms --source-platform MySQL --target-platform AzureDbForMySQL --tags tagName1=tagValue1 tagWithNoValue
"""

helps['dms project delete'] = """
Expand Down Expand Up @@ -320,6 +320,8 @@
// Optional setting that configures the delay between updates of result objects in Azure Table Storage.
"DelayProgressUpdatesInStorageInterval": "00:00:30",
},
// Optional setting to migrate the full server.
"migrate_full_server": "true|false",
// Optional setting to set the source server read only.
"make_source_server_read_only": "true|false",
// Optional setting to enable consistent backup. True by default for the sync migration, unless lockless is enabled.
Expand All @@ -339,7 +341,7 @@
// Optional. If true, all users/grants will be migrated.
"migrate_user_system_tables": "true|false",
// Binlog position to start the migration from. Only applicable for the ReplicateChanges migration.
"binLogInfo": {
"binlog_info": {
"filename": "binlog.0004523",
"position": 283287
}
Expand Down Expand Up @@ -376,7 +378,9 @@
"userName": "user name", // if this is missing or null, you will be prompted
"password": null, // if this is missing or null (highly recommended) you will be prompted
"serverName": "server name",
"port": 3306 // if this is missing, it will default to 3306
"port": 3306, // if this is missing, it will default to 3306
"encryptConnection": true, // highly recommended to leave as true
"trustServerCertificate": false // highly recommended to leave as false
}
- name: --target-connection-json
type: string
Expand Down
35 changes: 30 additions & 5 deletions src/azure-cli/azure/cli/command_modules/dms/custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@

from azure.cli.core.azclierror import RequiredArgumentMissingError
from azure.cli.core.util import sdk_no_wait, get_file_json, shell_safe_json_parse
from azure.cli.command_modules.dms._client_factory import dms_cf_projects
from azure.cli.command_modules.dms._client_factory import (dms_cf_projects,
get_resource_groups_client,
dms_cf_services)
from azure.cli.command_modules.dms.scenario_inputs import (get_migrate_sql_to_sqldb_offline_input,
get_migrate_postgresql_to_azuredbforpostgresql_sync_input,
get_migrate_mysql_to_azuredbformysql_offline_input,
Expand All @@ -42,14 +44,17 @@ def check_service_name_availability(client, service_name, location):
parameters=parameters)


def create_service(client,
def create_service(cmd,
client,
service_name,
resource_group_name,
location,
subnet,
sku_name,
location=None,
tags=None,
no_wait=False):
if location is None:
location = get_rg_location(cmd.cli_ctx, resource_group_name)
parameters = DataMigrationService(location=location,
virtual_subnet_id=subnet,
sku=ServiceSku(name=sku_name),
Expand Down Expand Up @@ -102,11 +107,11 @@ def check_project_name_availability(client, resource_group_name, service_name, p
parameters=parameters)


def create_or_update_project(client,
def create_or_update_project(cmd,
client,
project_name,
service_name,
resource_group_name,
location,
source_platform,
target_platform,
tags=None):
Expand All @@ -115,6 +120,8 @@ def create_or_update_project(client,
necessary at the Task level, there is no need to include it at the Project level where for CLI it is more of a
useless redundancy."""

location = get_dms_location(cmd.cli_ctx, resource_group_name, service_name)

# Set inputs to lowercase
source_platform = source_platform.lower()
target_platform = target_platform.lower()
Expand Down Expand Up @@ -474,6 +481,24 @@ def get_scenario_type(source_platform, target_platform, task_type=""):
return scenario_type


def get_rg_location(ctx, resource_group_name, subscription_id=None):
groups = get_resource_groups_client(ctx, subscription_id=subscription_id)
# Just do the get, we don't need the result, it will error out if the group doesn't exist.
rg = groups.get(resource_group_name)
if rg is None:
raise CLIError('Resource group {} not found.'.format(resource_group_name))
return rg.location


def get_dms_location(ctx, resource_group_name, dms_name):
services = dms_cf_services(ctx)
# Just do the get, we don't need the result, it will error out if the group doesn't exist.
service = services.get(group_name=resource_group_name, service_name=dms_name)
if service is None:
raise CLIError('Service {} not found.'.format(dms_name))
return service.location


class ScenarioType(Enum):
unknown = 0
# SQL to SQLDB
Expand Down
35 changes: 21 additions & 14 deletions src/azure-cli/azure/cli/command_modules/dms/scenario_inputs.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,28 +105,35 @@ def get_migrate_mysql_to_azuredbformysql_input(database_options_json,
migration_level_settings = {}
make_source_server_read_only = False
migration_properties = {}
migrate_full_server = False

if not isinstance(database_options_json, dict):
raise ValidationError('Format of the database option file is wrong')

if 'selected_databases' not in database_options_json:
migrate_full_server = database_options_json.get('migrate_full_server', False)
if migrate_full_server:
set_optional(migration_properties, 'migrateFullServer', database_options_json, 'migrate_full_server')

if ('selected_databases' not in database_options_json) and (not migrate_full_server):
raise ValidationError('Database option file should contain at least one selected database for migration')

selected_databases = database_options_json.get('selected_databases')

for database in selected_databases:
if not isinstance(database, dict):
raise ValidationError('Format of the selected database file is wrong')
if 'name' not in database:
raise ValidationError('Selected database should have a name')
if 'target_database_name' not in database:
raise ValidationError('Selected database should have a target_database_name')
if 'table_map' in database and (not isinstance(database.get('table_map'), dict) or
len(database.get('table_map')) == 0):
raise ValidationError('table_map should be dictionary and non empty, to select all tables remove table_map')

db_input = create_db_input(database, has_schema_migration_options)
database_options.append(db_input)
if selected_databases is not None:
Comment thread
temandr marked this conversation as resolved.
for database in selected_databases:
if not isinstance(database, dict):
raise ValidationError('Format of the selected database file is wrong')
if 'name' not in database:
raise ValidationError('Selected database should have a name')
if 'target_database_name' not in database:
raise ValidationError('Selected database should have a target_database_name')
if 'table_map' in database and (not isinstance(database.get('table_map'), dict) or
len(database.get('table_map')) == 0):
raise ValidationError(
'table_map should be dictionary and non empty, to select all tables remove table_map')

db_input = create_db_input(database, has_schema_migration_options)
database_options.append(db_input)

set_optional(migration_properties, 'sourceServerResourceId', database_options_json, 'source_server_resource_id')
set_optional(migration_properties, 'targetServerResourceId', database_options_json, 'target_server_resource_id')
Expand Down
Loading
Loading