Migration

from mstrio.access_and_security.privilege import Privilege
from mstrio.connection import Connection
from mstrio.object_management.migration import (
    bulk_full_migration,
    bulk_migrate_package,
    Migration,
    PackageConfig,
    PackageContentInfo,
    PackageSettings
)
from mstrio.types import ObjectTypes
from mstrio.users_and_groups.user import User

# connection parameters
PROJECT_NAME = '<Project_name>'
SOURCE_BASE_URL = '<connection_base_url>'  # usually ends with /MicroStrategyLibrary/api
SOURCE_USERNAME = '<username>'
SOURCE_PASSWORD = '<password>'
TARGET_BASE_URL = '<connection_base_url>'  # usually ends with /MicroStrategyLibrary/api
TARGET_USERNAME = '<username>'
TARGET_PASSWORD = '<password>'

USER_NAME = '<username>'  # user that is executing the migration

# IDs for items to migrate
DOSSIER_ID = '<Dossier_id>'
REPORT_ID = '<Report_id>'

SAVE_PATH = 'path/to/import_package.mmp'
CUSTOM_PACKAGE_PATH = 'path/to/other_import_package.mmp'
UNDO_PACKAGE_PATH = 'path/to/undo_package.mmp'

# Create connections to both source and target environments
source_conn = Connection(
    SOURCE_BASE_URL, SOURCE_USERNAME, SOURCE_PASSWORD, project_name=PROJECT_NAME, login_mode=1
)
target_conn = Connection(
    TARGET_BASE_URL, TARGET_USERNAME, TARGET_PASSWORD, project_name=PROJECT_NAME, login_mode=1
)

# Make sure the current user have the following privileges:
#   'Create package', id: 295
#   'Apply package',  id: 296
# They can be granted by admin with the following commands:
user = User(source_conn, username=USER_NAME)
Privilege(source_conn, id=295).add_to_user(user)
Privilege(source_conn, id=296).add_to_user(user)

# Or by name:
user2 = User(target_conn, username=USER_NAME)
Privilege(target_conn, name='Create package').add_to_user(user2)
Privilege(target_conn, name='Apply package').add_to_user(user2)

# Create PackageConfig with information what object should be migrated and how.
# The options are of type Enum with all possible values listed.
package_settings = PackageSettings(
    PackageSettings.DefaultAction.USE_EXISTING,
    PackageSettings.UpdateSchema.RECAL_TABLE_LOGICAL_SIZE,
    PackageSettings.AclOnReplacingObjects.REPLACE,
    PackageSettings.AclOnNewObjects.KEEP_ACL_AS_SOURCE_OBJECT,
)
package_content_info = PackageContentInfo(
    id=REPORT_ID,
    type=ObjectTypes.REPORT_DEFINITION,
    action=PackageContentInfo.Action.USE_EXISTING,
    include_dependents=True,
)
package_content_info2 = PackageContentInfo(
    id=DOSSIER_ID,
    type=ObjectTypes.DOCUMENT_DEFINITION,
    action=PackageContentInfo.Action.USE_EXISTING,
    include_dependents=True,
)

package_config = PackageConfig(
    PackageConfig.PackageUpdateType.PROJECT, package_settings, package_content_info
)
package_config2 = PackageConfig(
    PackageConfig.PackageUpdateType.PROJECT, package_settings, package_content_info2
)

# Create Migrations objects that can use all the functionalities
mig = Migration(
    save_path=SAVE_PATH,
    source_connection=source_conn,
    target_connection=target_conn,
    configuration=package_config,
)

# Create Migration object that can only use `create_package()`
mig2 = Migration(
    save_path=SAVE_PATH,
    source_connection=source_conn,
    configuration=package_config2,
)

# Create Migration object that can only be used for `migrate_package()`
mig3 = Migration(
    target_connection=target_conn,
    custom_package_path=CUSTOM_PACKAGE_PATH,
)

# Short version
# Create import package and save it to the file
mig.create_package()
# or
mig2.create_package()

# Migrate downloaded package to the target environment.
# Create undo package and save it to file
mig.migrate_package()
# or
mig3.migrate_package()

# End to end migration
mig.perform_full_migration()

# Detailed version
# Create import package and save it to the file specified with `save_path`
# argument during creation of migration object
mig.create_package()
mig2.create_package()

# Migrate downloaded package to the target environment
# `migrate_package()` by default uses a package binary saved to a variable
# during `create_package()`
mig.migrate_package()

# or a custom package binary specified with `custom_package_path`
# during Migration object creation, if `create_package()` was not called.
mig3.migrate_package()

# It is also possible to respecify `custom_package_path` at this stage
mig3.migrate_package(custom_package_path=CUSTOM_PACKAGE_PATH)

# Perform end to end migration. `perform_full_migration()` encapsulates
# `create_package()` and `migrate_package()` from the previous steps
# In order to be able to use, Migration object needs `source_connection`,
# `configuration` and `target_connection` parameters filled during creation
mig.perform_full_migration()

# Perform many full migrations at once
bulk_full_migration([mig])

# Perform many migrations at once
bulk_migrate_package([mig, mig3])

# If the migration needs to be reverted use `undo_migration()`
mig.undo_migration()

# or run `migrate_package()` with path to the custom undo package
Migration(
    save_path=SAVE_PATH, target_connection=target_conn, custom_package_path=UNDO_PACKAGE_PATH
).migrate_package()

# Status of the migration can be checked by checking the `status` property
status = mig.status