enov8 vME iSCSI Connector (SQL Server)
This connector integrates Microsoft SQL Server with enov8 vME iSCSI storage. It moves databases from local disks onto vME iSCSI LUNs, then mounts vME-created clones on other servers for dev/test/reporting. Each script includes built-in safety checks, confirmation prompts, and step-by-step guidance. Review the Operational Notes section before running on shared or production servers.
Download the toolkit: vme-db-connector-toolkit-1.2.1.zip
Use Case Diagram

Overview - What Will Happen
This workflow attaches and mounts vME iSCSI LUNs. Snapshot and clone creation are performed in vME. Phase 1 - Source Prep
- Connects the Windows iSCSI initiator to your vME targets.
- Brings the new empty LUNs online.
- Initializes and formats the selected LUNs as NTFS with 64K allocation units.
- Assigns drive letters and labels them
SQL_DataandSQL_Log. Phase 2 - Source Migrate - Creates folders on the iSCSI drives:
X:\MSSQL\Data,Y:\MSSQL\Logs, andX:\MSSQL\Backups. - Grants SQL Server service account permissions on those folders.
- Presents a migration mode menu with three options:
- Mode 1 — Backup and Restore (default): Lists user databases, performs backup + restore to iSCSI.
- Mode 2 — Skip Backup: Restores from pre-existing
.bakfiles (supports striped backups — multiple.bakfiles for one database are auto-grouped). - Mode 3 — Raw File Copy: Copies loose
.mdf/.ldffiles to iSCSI drives. Lets user select which database groups to copy, edit file paths, and auto-offlines attached databases during copy.
- Creates new databases with the prefix
ISCSI_(Modes 1-2) or copies files with prefix (Mode 3). - Restarts the SQL Server service (Modes 1-2 only). Phase 3 - Clone Mount
- Connects to the cloned iSCSI target(s).
- Brings iSCSI disks online without formatting.
- Assigns drive letters to the cloned volumes.
- Attaches MDF/LDF files using
CREATE DATABASE ... FOR ATTACH. Phase 4 - Clone Unmount - Detaches
ISCSI_databases from SQL Server. - Offlines iSCSI disks and disconnects sessions.
- Full iSCSI cleanup (removes persistent targets).
Prerequisites
Windows / SQL
- Windows Server 2019 and 2022.
- PowerShell 5.1+ as Administrator.
- SQL Server 2017+.
sqlcmdavailable in PATH.- Windows authentication with sysadmin privileges. vME / Network
- enov8 vME appliance with iSCSI enabled.
- iSCSI targets and LUNs created in vME before running the scripts.
- Complete source setup in vME first: iSCSI Source Form Instructions.
- For SQL Server, follow that Microweb form flow twice to create one Data source and one Log source.
- Network access to port 3260 between servers and storage. Safety Notes
- Phase 1 can format disks. Only select new empty LUNs.
- Phase 2 creates new databases with the
ISCSI_prefix. - Phase 2 restarts SQL Server (Modes 1-2 only).
- Phase 2 Mode 3 sets databases OFFLINE temporarily if copying files that belong to attached databases. They are brought back ONLINE after copying completes.
- Phase 4 can clear iSCSI configuration.
Operational Notes
These scripts are designed for dedicated servers where iSCSI is used exclusively for this SQL migration/cloning workflow. On multi-purpose iSCSI servers, review the notes below to understand which operations have server-wide effects.
ISCSI_USECASE1.PS1 (Prepare LUNs)
| Consideration | Details |
|---|---|
| Disk format | If a selected disk already has data, the script will format it with only one Y/N confirmation. There is no second "are you sure?" prompt. Always double-check disk numbers before confirming. |
| Portal cleanup is global | Choosing Y to "Clear old portals" will disconnect all existing iSCSI sessions on the server, not just stale ones. Do not use this option if the server has other active iSCSI workloads. |
ISCSI_USECASE2.PS1 (Migrate Data)
| Consideration | Details |
|---|---|
| SQL Server force restart | (Modes 1-2) After migration, the script calls Restart-Service -Force which terminates SQL Server and all dependent services (SQL Agent, SSIS, SSRS, etc.) without waiting for active connections to drain. Schedule this during a maintenance window. |
| Overwrites existing databases | If a database named ISCSI_<name> already exists, RESTORE ... WITH REPLACE will overwrite it. Do not re-run this script unless you intend to replace previously migrated databases. |
| Backup file overwrite | (Mode 1) The BACKUP ... WITH FORMAT option overwrites any existing backup file at the same path. |
| Striped backup auto-grouping | (Mode 2) Multiple .bak files with the same DatabaseName in their header are automatically grouped into a single striped restore. Verify the grouping displayed before confirming. |
| Database offline during copy | (Mode 3) If any selected files belong to databases currently attached in SQL Server, those databases are set OFFLINE before copying and brought back ONLINE afterward. Active connections to those databases will be terminated. |
| No SQL operations in Mode 3 | Mode 3 only copies files — it does not attach databases. Run ISCSI_USECASE3.PS1 afterward to attach. |
ISCSI_USECASE3_UNMOUNT.PS1 (Cleanup Clone)
| Consideration | Details |
|---|---|
| All iSCSI disks taken offline | The full cleanup step takes all iSCSI disks offline on the server, not just the ones mounted by this workflow. |
| All persistent targets removed | The full cleanup runs iscsicli RemovePersistentTargets, which removes all persistent iSCSI targets on the server. After a reboot, other iSCSI-dependent services will need to be reconnected. |
| Global mount point cleanup | mountvol /R is executed, which removes all orphaned volume mount points system-wide, not just those created by this workflow. |
| Database detach skips integrity checks | sp_detach_db is called with @skipchecks = 'true', which skips UPDATE STATISTICS and integrity verification before detaching. |
General
| Consideration | Details |
|---|---|
| No file logging | Errors are only displayed on screen and are not persisted to a log file. Take note of or screenshot any errors during execution. |
| No rollback | If a migration fails midway (e.g., after 2 of 5 databases), there is no automatic rollback. Backup files remain on disk and you must manually retry or clean up. |
Note: These scripts perform administrative actions including disk formatting, database backup/restore, and iSCSI configuration changes. Always run them in a PowerShell session with Administrator privileges and confirm each prompt carefully.
Roles - Source vs Clone Server
| Server role | Scripts to run |
|---|---|
| Source Server (Primary SQL Server) | ISCSI_USECASE1.ps1 to prep LUNs, then ISCSI_USECASE2.ps1 to migrate databases. |
| Clone Server (Dev / Test / Reporting) | ISCSI_USECASE3.ps1 to attach clones, then ISCSI_USECASE3_UNMOUNT.ps1 to detach and clean up. |
Interactive Walkthrough
Open PowerShell as Administrator on each server before running any script.
Phase 1 — Prepare LUNs (Source Server)
On the source server, run .\ISCSI_USECASE1.ps1. This script connects to your storage appliance via iSCSI, brings new (empty) LUNs online, and formats them as NTFS with the 64K allocation unit size recommended for SQL Server.
Step 1: Enter the vME Portal IP Address
The script first verifies it is running as Administrator, then checks that the MSiSCSI service (Windows iSCSI Initiator) is running. If the service is stopped, it starts it automatically and sets it to start on boot.
Next, it prompts for the vME portal IP address — this is the IP of your vME appliance. The script remembers the last portal you used in %USERPROFILE%\.iscsi_portal.txt, so you can press Enter to reuse it.
You will then be asked whether to clear old portals:
- Y = Disconnect sessions from portals other than the one you just entered, then remove those portals. This gives you a clean slate when switching to a new storage IP.
- N = Keep all existing portal connections alongside the new one.
After the vME portal is configured, the script runs target discovery (
Get-IscsiTarget) to find all available IQNs. If automatic discovery fails, you can enter an IQN manually.
Note — Clear old portals disconnects other sessions: Choosing Y will disconnect active iSCSI sessions from portals other than the one you just entered. Only use this option on dedicated servers or when you are certain no other iSCSI workloads are active.
Step 2: Select iSCSI Targets to Connect
The script lists all discovered iSCSI targets with their IQN (iSCSI Qualified Name) and current connection status. You select which targets to connect by entering their numbers (comma-separated, e.g., 1,2).
For each selected target, the script calls Connect-IscsiTarget with -IsPersistent $true, meaning the connection will survive reboots — Windows will automatically reconnect at startup. If CHAP authentication is configured (via config.json or environment variables), the script applies one-way or mutual CHAP credentials during the connection.
Targets that are already connected are skipped. After all connections are established, the script waits up to 10 seconds for the sessions to register and displays the active session list.
Note — Persistent connections survive reboots: Because
-IsPersistent $trueis used, these connections will automatically re-establish after every server restart. When decommissioning, runISCSI_USECASE3_UNMOUNT.PS1or manually remove persistent targets to avoid stale reconnection attempts.Note — CHAP credentials passed via environment variables: If using the non-interactive wrapper (
Run-IscsiWorkflow.ps1), CHAP passwords are passed through process-scoped environment variables. These are not visible to other users but may appear in process dumps or transcript logs.
Step 3: Assign Disks for SQL Data and Log
The script runs a diskpart rescan to detect newly connected LUNs, then enumerates all disks with BusType = iSCSI. For each iSCSI disk, it queries WMI (MSiSCSIInitiator_SessionClass) to map the disk number back to its IQN, then displays a table with:
- DiskNumber — Windows disk number
- SizeGB — Capacity of the LUN
- PartitionStyle —
RAW(uninitialized) orGPT/MBR - IsOffline — Whether the disk is currently offline
- IQN — Which iSCSI target this disk belongs to You must select which disk to use for SQL Data files and which for SQL Log files by entering their disk numbers. The script prevents you from selecting the same disk for both.
Tip: Cross-reference the disk sizes and IQNs shown here with what you configured on your storage appliance to ensure you pick the correct disks.
Note — Selecting the correct disk: The script only allows iSCSI disks (BusType check), so you cannot accidentally format your OS or local disks. If you have multiple iSCSI workloads on the same server, verify the IQN column matches the target you intend to prepare.
Step 4: Assign Drive Letters
The script scans all volumes and partitions to build a list of free drive letters (excluding A, B, C and commonly reserved letters). You choose one letter for the Data disk and one for the Log disk.
The assigned letters determine where the iSCSI volumes will appear in Windows (e.g., J: for Data, K: for Log). These are the drive letters you will reference when running ISCSI_USECASE2.PS1 to migrate databases.
Note — Drive letter conflicts: On busy servers, coordinate drive letter assignments with your team before running this script. If another process claims your chosen letter before the format step completes, the script may fail.
Step 5: Confirm and Format
This is the most critical step. Read carefully before pressing Y. The script displays a summary of what it is about to do:
Data: Disk X -> H:andLog: Disk Y -> I:Before pressing Y, verify that:
- The disk numbers correspond to your iSCSI LUNs (not your local/OS disks).
- The drive letters are not already assigned to existing volumes. When you confirm with Y, the script performs the following for each disk:
- Brings the disk online and clears read-only mode.
- Safety check — Verifies
BusTypeisiSCSI. If not, the script refuses to proceed (hard block). - Initializes as GPT — Only if the disk is RAW (unpartitioned). Existing GPT/MBR partitions are preserved.
- Creates a partition using the maximum available space and assigns the chosen drive letter.
- Checks existing filesystem — If the volume is already NTFS with 64K allocation units, formatting is skipped and only the label is updated (
SQL_DataorSQL_Log). - Formats as NTFS 64K — If the disk is unformatted or has a different filesystem/cluster size, the script formats it. If an existing filesystem is detected, an additional confirmation (
Type YES) is required before formatting proceeds. After formatting, the script runs a final verification showing disk status, partition style, volume details, and cluster size confirmation viafsutil.
Important — Formatting erases the disk: If a selected disk already contains data, formatting will permanently erase it. The script shows a warning and requires you to type
YES(not justY) if it detects an existing filesystem — there is no undo once confirmed.Note — Sector size mismatch: Some iSCSI targets expose LUNs with 4K or 16K logical sector sizes. SQL Server databases backed up from a disk with a different sector size may fail to restore. Check
LogicalSectorSizein the verification table — if it differs from your source disk, investigate compatibility before proceeding.
Phase 2 — Migrate Databases (Source Server)
Still on the source server, run .\ISCSI_USECASE2.ps1. This script moves your existing SQL Server databases from local storage to the iSCSI LUNs that were prepared in Phase 1. It supports three migration modes.
Step 1: Select Migration Mode and Drives
The script first confirms the migration intent, then presents a mode selection menu:
Select migration mode:
1. Backup and Restore (default)
2. Restore from existing .bak files (skip backup)
3. Copy loose .mdf/.ldf files to iSCSI (raw file copy)
After selecting a mode, the script lists all available drives. You must choose:
- A Data drive (where data files will be stored on iSCSI)
- A Log drive (where log files will be stored on iSCSI)
The script then creates the directory structure (
H:\MSSQL\Data,I:\MSSQL\Logs, and for Modes 1-2H:\MSSQL\Backups), detects the SQL Server instance, and grants the SQL Server service account permissions on those directories.
Note — Verify drive selection: Cross-reference the drive letters and labels (
SQL_Data,SQL_Log) that you assigned in USECASE1 before proceeding. Selecting a non-iSCSI drive would write database files to local storage instead.
Mode 1: Backup and Restore (Default)
This is the standard migration path. The script backs up each selected database from local storage and restores it to the iSCSI drives.
Choose Databases to Migrate
The script connects to SQL Server and discovers all user databases (those with database_id > 4). System databases (master, model, msdb, tempdb) are excluded.
Each database is displayed with its DB_ID and name. You can:
- Enter a single ID (e.g.,
6) or comma-separated IDs (e.g.,5,6,7) - Enter
ALLto migrate every user database After confirmation, the script detects the SQL Server edition (Enterprise/Standard support backup compression; Express does not), generates a T-SQL migration script, and saves it to a temporary file.
Note — Verify database selection: Double-check the database names and IDs before confirming. There is no automatic rollback once the migration starts.
![]()
Backup and Restore Execution
After a final Y/N confirmation, the generated SQL script runs via sqlcmd. For each database, two operations occur back-to-back:
- Backup — A full backup is written to the iSCSI backup directory (e.g.,
H:\MSSQL\Backups\demo_Migration.bak). TheWITH FORMAToption overwrites any previous backup file at the same path. On Enterprise/Standard editions,WITH COMPRESSIONis also applied. - Restore — The backup is immediately restored as a new database (
ISCSI_demo) with all data/log files mapped to the iSCSI paths. Progress updates (10%, 21%, 30% ... 100%) are printed for both the backup and restore phases. After all databases complete, the script restarts the SQL Server service and verifies migration.
Note — SQL Server restart: The restart terminates all active SQL connections. Schedule this during a maintenance window.
Note — iSCSI connectivity during migration: The backup and restore both write to the iSCSI drives. If the iSCSI session drops mid-operation, the restore may fail and leave a partially written database.
Mode 2: Skip Backup (Restore from Existing .bak Files)
If you already have .bak backup files (from scheduled backups, another server, etc.), choose Mode 2 to skip the time-consuming BACKUP DATABASE step and restore directly.
Add Backup Sources
After selecting Mode 2, the script enters a multi-source input loop. Each prompt accepts one of:
- A directory path (e.g.,
D:\Backups) — auto-discovers all.bakfiles in that directory - A wildcard pattern (e.g.,
D:\Backups\Sales*.bak) — matches.bakfiles by pattern - An individual file path (e.g.,
D:\Backups\SalesDB.bak)
You can add multiple sources one at a time. Press Enter on a blank line when done. The script deduplicates files and shows a total count (e.g., Total: 5 .bak file(s) from 1 source(s)). All discovered files are then validated.
Striped backup support: If a database was backed up across multiple .bak files for performance, simply point to the directory containing all stripe files (or add them individually). The script reads RESTORE HEADERONLY from each file and automatically groups files that share the same DatabaseName.

Header Grouping, Database Selection, and Edit
After reading all headers, the script displays numbered database groups with file counts. In this example, 5 .bak files are grouped into two databases: one standalone and one striped backup with 4 parts.
You then select which database groups to restore by entering numbers (e.g., 1,3 or ALL). After selection, an Edit backup files? (Y/N) prompt lets you modify the file list for each group if needed. A final confirmation shows the selected groups and file paths before proceeding.
The script configures SQL Server permissions, then proceeds with SQL script generation and restore — the same flow as Mode 1 but without the backup step.

Striped Restore Execution
The restore command uses all stripe files in a single RESTORE DATABASE ... FROM DISK='Part1.bak', DISK='Part2.bak', DISK='Part3.bak', DISK='Part4.bak' statement. Logical file names are auto-detected: the script tries sys.master_files first (if the DB exists locally), then falls back to RESTORE FILELISTONLY.
After restore completes, the script reports success and the database is immediately usable on the iSCSI drives.

Mode 3: Raw File Copy (Loose .mdf/.ldf Files)
If you have detached or loose .mdf/.ldf database files that need to be moved to iSCSI drives, choose Mode 3. This mode performs file copy only — no SQL backup, restore, or attach operations. After copying, run ISCSI_USECASE3.ps1 to attach the databases.
Enter Source Paths
After selecting Mode 3, the script prompts for source locations. You can enter either:
- A drive letter (e.g.,
D) — scans the entire drive recursively - A full directory path (e.g.,
C:\Program Files\Microsoft SQL Server\MSSQL13.MSSQLSERVER\MSSQL\DATA) — scans only that directory Separate prompts for data files (.mdf/.ndf) and log files (.ldf) allow them to be on different drives/paths.
File Scanning and Database Group Selection
The script scans the source paths and auto-pairs files into database groups using progressive prefix-based matching (the same algorithm as USECASE3). All discovered groups are displayed with their files.
You then select which database groups to copy by entering numbers (e.g., 1,3,5 or ALL). This lets you skip system databases (master, tempdb, model, msdb) or any databases you don't want to migrate.

Path Editing and Final Review
After selecting database groups, you can edit file paths if the auto-pairing grouped something incorrectly. For each selected group, every file is listed with a prompt to enter a new path or press Enter to keep the current one. The script validates that edited paths point to existing files.
The final list shows all selected groups with their (potentially edited) file paths before proceeding.

Offline, Copy, and Completion
Before copying, a warning is displayed:
WARNING: If any of these files belong to databases currently attached to SQL Server, those databases will be set OFFLINE during the copy and brought back ONLINE after copying completes. The script queries
sys.master_filesfor each file path. If a match is found, that database is set OFFLINE to release the file lock. After all files are copied, the databases are brought back ONLINE. Files are copied to iSCSI drives with theISCSI_prefix (files already namedISCSI_*are not double-prefixed):
.mdf/.ndfgo toH:\MSSQL\Data\ISCSI_<filename>.ldfgo toI:\MSSQL\Logs\ISCSI_<filename>After copying, the script reminds you to runISCSI_USECASE3.ps1to attach the databases to SQL Server.
Create Snapshot and Clone (vME)
Before mounting clones on the clone server, create the snapshot and clone in vME. Reference: Microweb documentation.
- Create a snapshot of the source LUN.
- Create a clone from that snapshot.
- Export the clone as a new iSCSI target.
Phase 3 — Mount Clone (Clone Server)
On the clone server, run .\ISCSI_USECASE3.ps1. This script connects to the cloned targets, brings the disks online without formatting, and attaches the existing database files to SQL Server using CREATE DATABASE ... FOR ATTACH.
Step 1: Connect to vME Portal
The script verifies it is running as Administrator, then checks that the MSiSCSI service is running (starts it automatically if needed). You enter the vME portal IP address — this should be the same vME appliance that exposes your cloned LUNs. The script adds or refreshes the portal and performs target discovery with up to 3 retries if the storage is slow to respond.
Note: This step only queries the vME portal for available targets — no connections or disk changes are made yet.
Step 2: Select and Connect iSCSI Targets
The script lists all discovered targets with their IQN and connection status. In this example, four targets are visible:
- Targets 1–2 are the source LUNs (
ash-source-data-1,ash-source-logs-1) — Not Connected - Targets 3–4 are the clone LUNs (
aum-clone-data-1,aum-clone-log-1) — Already Connected The user selects3,4to connect the clone targets. Since they are already connected, the script prints "Already connected" and moves on. Each connection is made with-IsPersistent $true, so Windows will automatically reconnect to these targets after a reboot. If CHAP authentication is configured, the script applies the credentials during the connection. After connecting, the script detects all NTFS volumes currently available. In this example,D:(SQL_Data) andE:(SQL_Log) are the clone volumes that are already mounted from a previous run.
Important — Select clone targets, not source targets: Verify the IQN names correspond to clone targets before connecting. Mounting the source LUNs on a second server while the source is still active could lead to data corruption.
Note — Persistent connections survive reboots: The clone connections will auto-reconnect on every server restart. When you are done with the cloned data, run
ISCSI_USECASE3_UNMOUNT.PS1to remove persistent targets.
Step 3: Bring Disks Online and Detect Volumes
The script runs diskpart rescan to detect iSCSI disks, then brings each one online without formatting. This is the key difference from USECASE1 — the clone LUNs already contain NTFS filesystems with database files, so no initialization or formatting is performed.
If the clone disks already had drive letters from a previous mount (or because Windows remembered them), the script reports that each volume already has its assigned letter. In this example:
D:→ SQL_Data (~25 GB)E:→ SQL_Log (~25 GB) If the partitions do not have drive letters (first-time mount on this server), the script prompts you to assign letters manually for each hidden partition.
Note — Drive letter conflict: If the clone LUN's partition previously had a drive letter that is already in use on this server, Windows may fail to assign it. Check for conflicts before proceeding.
Note — Disk signature collision: If the clone was created from a snapshot, the disk signature may be identical to the source. Windows may mark the disk as "Offline" with a "signature collision" error. If this happens, change the signature using
diskpart→select disk X→uniqueid disk ID=<new_value>.
Step 3.2: Grant SQL Server Permissions on Clone Drives
The script detects the SQL Server service account (NT Service\MSSQLSERVER) and grants it Full Control on the clone drive(s). This includes clearing read-only flags, taking ownership, re-enabling NTFS inheritance, removing explicit DENY entries, and then applying Full Control permissions recursively.
In this example, permissions are applied to D:\, processing all files under MSSQL\Data, MSSQL\Backups, and System Volume Information.
Note — Automatic permission grant: The script does configure file permissions on the clone drives at this stage, and again per-directory in Step 5 before each attach. If the permission step fails (e.g., due to locked files), the subsequent
CREATE DATABASE ... FOR ATTACHmay fail with "Access is denied".
Step 4: Attach Databases to SQL Server
The script detects the local SQL Server instance (from the Windows registry), then prompts you for:
- MDF drive letter — The drive containing
.mdf(data) files (e.g.,D) - LDF drive letter — The drive containing
.ldf(log) files (e.g.,E). Press Enter if they are on the same drive as the MDF files. It then recursively scans those drives for.mdf,.ndf, and.ldffiles. After scanning, the script asks you to choose how files should be grouped into databases:
Do you want automatic datafile pairing? (Y/N)
Y = Auto-detect database groups from file names
N = Manually select files for each database
- Y (Automatic) — The script groups MDF, NDF, and LDF files by matching filename prefixes. This works well when files follow the standard
ISCSI_<dbname>_<logicalname>.<ext>naming convention from USECASE2. - N (Manual) — You name each database yourself and pick which files belong to it. Use this when file names are non-standard or when automatic grouping produces incorrect results.
In non-interactive mode (
config.json), this is controlled by theautoPairfield in theattachblock. WhenautoPairisfalse, the database name and file list are taken from theattach.databasesarray (see Manual pairing via config.json).
Note — Verify drive letters: If you enter the wrong drive letter, the script will either find no database files (and exit) or find files from a different volume. Confirm the letters match the clone volumes shown in the previous step.
Automatic Pairing (Y)
When you choose Y, the script automatically groups files by common filename prefix. It sorts MDF files by name length (longest first) to prevent shorter database names from over-claiming files that belong to longer-named databases (e.g., ISCSI_MRU vs ISCSI_MRU_ARCHIVE).
The results are displayed as a numbered summary table. You are then asked whether to review the file pairs before attaching.
If you choose Y at the review prompt, each database is shown with its files grouped into Data files (MDF/NDF) and Log files (LDF). You can edit the file list using these commands:
remove <N>— Remove a file by its number (the last MDF cannot be removed)add <full-path>— Add a file by its full path (validates the file exists and has a valid extension)rename <new-name>— Change the database name (e.g., if the target name already exists on the SQL instance)doneor Enter — Accept the current file list and move to the next database In this example, two databases were auto-detected:ISCSI_MultiFile_Test(5 files) andISCSI_demo(2 files). The user reviews the file pairs and removes file #4 (ISCSI_MultiFile_Test_DATA4.ndf) from the first database.
Review File Pairs (Editing in Detail)
The review file pairs editor loops until you type done or press Enter, allowing multiple edits per database. After completing edits for one database, the script moves to the next. Available commands:
remove <N>— Remove a file by its index numberadd <full-path>— Add a file by its full pathrename <new-name>— Change the database name (useful when a database with the same name already exists on the SQL instance)doneor Enter — Accept and move to the next database In this example, the user:
- Removes
ISCSI_MultiFile_Test_DATA4.ndfusingremove 4 - Adds it back using
add D:\MSSQL\Data\ISCSI_MultiFile_Test_DATA4.ndf - Types
doneto accept and moves to the next database (ISCSI_demo) - Presses Enter to accept
ISCSI_demoas-is After all databases are reviewed, the updated summary table is displayed before proceeding to the attach step.
Manual Pairing (N)
When you choose N, the script skips automatic grouping and shows all discovered files grouped by drive:
- Data drive — Lists all MDF and NDF files with their type tags
- Log drive — Lists all LDF files You then create database groups one at a time:
- Enter a database name (or press Enter to finish)
- Select files by number from the list (comma-separated), or type P to enter full file paths manually
- Repeat for additional databases
In this example, the user creates a database named
multidbtest newand selects files2,3,4,5,7— four data files and one LDF log file from the log drive.
Tip — When to use manual pairing: Manual pairing is useful when clone files do not follow the standard naming convention, when databases span non-obvious file groupings, or when automatic pairing produces incorrect results.
Step 5: Select Databases and Execute Attach
After pairing (automatic or manual) and optional review, you select which databases to attach by entering their numbers (comma-separated, or ALL).
Before attaching each database, the script checks whether a database with the same name already exists on the SQL instance by querying sys.databases. If a collision is detected:
- Interactive mode — You are prompted to choose:
- [S] Skip — Skip this database and move to the next one.
- [R] Rename — Enter a new database name. The script re-checks the new name against the server and loops until you provide a unique name (or press Enter to skip).
- Non-interactive mode (
config.json) — The database is automatically skipped with a warning message. For each selected database, the script fixes NTFS permissions on the file directories, then runs:
CREATE DATABASE [ISCSI_MultiFile_Test]
ON (FILENAME = N'D:\MSSQL\Data\ISCSI_MultiFile_Test_DATA1.mdf'),
(FILENAME = N'D:\MSSQL\Data\ISCSI_MultiFile_Test_DATA2.ndf'),
(FILENAME = N'D:\MSSQL\Data\ISCSI_MultiFile_Test_DATA3.ndf'),
(FILENAME = N'D:\MSSQL\Data\ISCSI_MultiFile_Test_DATA4.ndf'),
(FILENAME = N'E:\MSSQL\Logs\ISCSI_MultiFile_Test_LOG.ldf')
FOR ATTACH;
After all attachments complete, the script verifies that all databases on the instance are ONLINE by querying sys.databases.
Note — SQL version compatibility:
CREATE DATABASE ... FOR ATTACHrequires that the database files were created by the same or an older version of SQL Server. If the clone comes from a newer version, the attach will fail with a version mismatch error.Note — Database name collision: If a database with the same name already exists (e.g., from a previous clone mount), the script prompts you to Skip or Rename. You can also proactively rename databases during the review/edit step (Step 4) using the
renamecommand before reaching this point. To remove old clones, useISCSI_USECASE3_UNMOUNT.PS1for safe detachment.Note — File permissions: The script automatically grants the SQL Server service account full NTFS permissions on each database file's directory and on each file individually before attaching. This handles cloned LUNs where baked-in ACLs from the source server may block access. If the attach still fails with "Access is denied", verify the permissions were applied correctly in Step 3.2.
Step 6: Verify Database States
After all attachments complete, the script queries sys.databases to verify that every database on the instance is ONLINE. The output shows each database name and its state_desc.
In this example, the verification confirms all system databases and the attached ISCSI_ database are ONLINE, followed by the === All Done === message.
Tip: This is a good time to run a quick
DBCC CHECKDB('ISCSI_<name>')in SQL Server Management Studio to verify the integrity of the cloned database before using it for development or testing.
Step 7: Verify in SQL Server Management Studio
As a final manual check, open SQL Server Management Studio (SSMS) and connect to the instance. Expand Databases in the Object Explorer to confirm the attached ISCSI_ database is visible.
In this example, ISCSI_ISCSI_MultiFile_Test_ISCSI_MultiFile_Test appears under the Databases node alongside System Databases and Database Snapshots.

Phase 4 — Cleanup Clone (Clone Server)
When finished with the cloned databases, run .\ISCSI_USECASE3_UNMOUNT.ps1 on the clone server. This script detaches the databases from SQL Server, disconnects iSCSI sessions, takes disks offline, and optionally performs a full iSCSI configuration reset — making the server clean and ready for the next clone cycle.
Detect SQL Instance and Detach Databases
The script detects installed SQL Server instances from the Windows registry and prompts you to select one (or press Enter for the default localhost instance).
It then scans for databases whose names start with ISCSI_ — these are the databases that were mounted by ISCSI_USECASE3.PS1. If any are found, you select which ones to detach by number (comma-separated, or ALL).
For each selected database, the script runs sp_detach_db, which removes the database from the SQL instance without deleting the underlying .mdf/.ldf files on the iSCSI volume. The files remain intact on the clone LUN.
In this example, the script detects one ISCSI_ database and detaches it using the configured selection (ALL).
Note — Active connections: If applications or users are connected to the database,
sp_detach_dbwill fail. Close all connections before running this step, or set the database toSINGLE_USERmode first.Note — Only
ISCSI_prefixed databases are shown: If you attached a cloned database with a custom name (not using theISCSI_prefix), the script will not detect it. Detach it manually using SQL Server Management Studio orsqlcmd.
Disconnect iSCSI Sessions and Offline Disks
The script builds an IQN-to-disk-number map using WMI (MSiSCSIInitiator_SessionClass) before disconnecting any sessions — this is critical because the mapping data is lost once a session is disconnected.
It then lists all active iSCSI sessions. You select which targets to disconnect by number. In this example, two clone sessions are listed:
iqn.2025-01.com.storage:clone-data-1iqn.2025-01.com.storage:clone-log-1The user enters1,2to disconnect both. After disconnection, the script uses the pre-built map to identify which Windows disk numbers belonged to those sessions and takes only those disks offline. Other iSCSI disks on the server (if any) are left untouched.
Important — Select the correct sessions: If you have multiple iSCSI workloads on the same server, select only the clone sessions. Disconnecting a session for a production LUN will make that storage inaccessible.
Note — Disk offline affects all volumes: If the iSCSI disk has multiple partitions or volumes, taking it offline removes access to all of them — not just the SQL database files.
Full iSCSI Configuration Reset (Optional)
After the scoped cleanup, the script offers an optional full iSCSI reset. This step is shown with prominent red warnings because it affects all iSCSI configuration on the server, not just the clone sessions. When you confirm with Y, the script:
- Disconnects all remaining iSCSI sessions — any sessions that were not selected in Phase 2.
- Takes all remaining iSCSI disks offline.
- Removes all persistent targets (
iscsicli RemovePersistentTargets) — this clears the list of targets that Windows automatically reconnects to on boot. - Restarts the MSiSCSI service — ensures a clean state. In this example, the user confirms Y because this is a dedicated test/clone server with no other iSCSI workloads.
Important — Full reset affects all iSCSI on this server: This step removes every persistent iSCSI target and disconnects every active session. Only choose Y if this server is dedicated to the clone workflow or if you are certain no other iSCSI workloads exist.
Note — After reboot, no iSCSI will auto-reconnect: Because all persistent targets are removed, the server will not reconnect to any iSCSI target after a reboot. This is the intended behavior — the server is "reset" and ready for a fresh
ISCSI_USECASE3.PS1run with a new clone.
Verification
The script verifies the cleanup by checking the number of active iSCSI sessions. In this example:
- Active Sessions: 0 — all sessions have been cleared.
- The system is confirmed clean and ready for a new iSCSI setup.
The message "Automount is disabled; assign drive letters manually" reminds you that Windows SAN policy may prevent new iSCSI volumes from auto-mounting. When you run
ISCSI_USECASE3.PS1next time, the script will handle drive letter assignment interactively.
Non-Interactive Config
- Copy
config.sample.jsontoconfig.json. - Edit values (vME portal IP, LUN numbers, drive letters, etc).
- Run the wrapper:
.\Run-IscsiWorkflow.ps1 -ConfigPath .\config.json
Supported phases
SourcePrep (USECASE1 + USECASE2), SourcePrepOnly, SourceMigrateOnly, CloneMount, CloneUnmount.
Config fields (summary)
phase: One phase or an array of phases to run.portal: vME iSCSI portal IP.clearOldPortals: Clear previous iSCSI portal entries before discovery.targetSelection: Target numbers to connect (e.g.,1,2). Use"ALL"to connect every discovered target. Optional whenmanualIQNordatasetis set.manualIQN: Connect targets by IQN substring instead of by list number — pass either an IQN keyword (e.g.,"agent","clones") that matches part of the target IQN, or a comma-separated list of full IQNs. Removes the need to look up target list numbers manually.dataset: Alternative IQN substring filter (same semantics asmanualIQN). Use either field.dataDiskNumber,logDiskNumber: Disk numbers for data/log LUNs during prep. Optional whenmanualIQNordatasetis set — the script auto-maps disks to data/log roles by detectingdataorlogkeywords in the IQN, so you don't need to look up Windows disk numbers.dataDriveLetter,logDriveLetter: Drive letters assigned during prep.confirmPrep: Set totrueto auto-confirm the disk format prompt. Skips the interactiveYEStyping step so the workflow runs end-to-end without prompts.migrate: Migration options — includesdbIds,dbNameFilter,backupPaths(supports directories, wildcards, or individual files),sourcePaths, and confirmations. See Migration mode examples below.attach: Clone attach options (SQL instance, drive letters, auto-pair mode, db selection, databases array). See Manual pairing via config.json.unmount: Clone detach options (SQL instance, db selection, cleanup).
CHAP authentication
Set chapUser and chapPassword for one-way CHAP, and add mutualChapPassword for mutual CHAP. Per-target CHAP credentials can be supplied via a targets array. See CHAP authentication (optional) for full details and config examples.
Windows paths in JSON: The wrapper auto-fixes single backslashes, so both C:\Backups and C:\\Backups work in file path values (e.g. backupPaths, sourcePaths, files). Forward slashes (C:/Backups) are also accepted.
Important —
sqlInstancerequires escaped backslashes: Named SQL Server instances likelocalhost\SQLINSTANCEmust use a double backslash in JSON:"sqlInstance": "localhost\\SQLINSTANCE". A single backslash produces aJSON parse error: invalid escape sequencebecause JSON treats\Tas an invalid escape. The auto-fix that helps file paths does not apply tosqlInstance— you must escape it manually.
Automating Manual Activities
Earlier versions of Run-IscsiWorkflow.ps1 still required several interactive lookups even when running from config.json — you had to find the target list number, look up the Windows disk number, type YES to confirm formatting, and query SQL for database IDs. v1.2 makes every one of those steps configurable so the workflow can run end-to-end without prompts.
Use the following fields in config.json:
| Manual activity (old) | Field to use (new) | Behavior |
|---|---|---|
| Look up IQN list numbers each run | manualIQN: "data,log" (substring) or full IQNs | Targets are matched by IQN content, not by list position. List positions can change between runs; substrings are stable. |
| Look up Windows disk numbers each run | Omit dataDiskNumber/logDiskNumber and set manualIQN | Script auto-detects which iSCSI disk is data vs log by scanning the IQN for data/log keywords. |
Press YES at the format prompt | confirmPrep: true | Auto-confirms the format step. Only use on dedicated servers — formatting cannot be undone. |
Look up DB_ID via SQL query | migrate.dbIds: "ALL" or migrate.dbNameFilter: "Sales*" | Use ALL for every user database; use dbNameFilter for a wildcard pattern matched against sys.databases.name. |
Pass a cloned DB name with autoPair: false | attach.autoPair: false + attach.databases: [...] | See Manual pairing via config.json. |
Manual pairing via config.json (attach.databases)
When autoPair is false, the previous version of the wrapper had no field to receive the database name and file list, so the clone DB was never created. v1.2 adds the attach.databases array, which is consumed exactly like the manual-pairing prompts in the interactive walkthrough:
{
"phase": "CloneMount",
"portal": "10.0.0.10",
"manualIQN": "clones",
"attach": {
"sqlInstance": "localhost\\SQLINSTANCE",
"dataDriveLetter": "G",
"logDriveLetter": "H",
"skipPartitionAssign": true,
"autoPair": false,
"dbSelection": "ALL",
"databases": [
{
"name": "MyClone_Sales",
"files": [
"G:\\MSSQL\\Data\\ISCSI_Sales_DATA1.mdf",
"G:\\MSSQL\\Data\\ISCSI_Sales_DATA2.ndf",
"H:\\MSSQL\\Logs\\ISCSI_Sales_LOG.ldf"
]
},
{
"name": "MyClone_Inventory",
"files": [
"G:\\MSSQL\\Data\\ISCSI_Inventory.mdf",
"H:\\MSSQL\\Logs\\ISCSI_Inventory.ldf"
]
}
]
}
}
Each entry in databases:
name— Database name to create withCREATE DATABASE ... FOR ATTACH. Set this when you want the cloned DB to have a different name from the original (avoids the name-collision skip behavior).files— Full paths to the MDF/NDF/LDF files. The script validates each file exists before issuing the SQL statement.
If autoPair: true, the databases array is ignored — the script discovers and groups files automatically.
skipPartitionAssign: true skips the drive-letter assignment step when the clone LUN already presents a partition with the expected letters (e.g., from a previous mount). Useful for repeated clone cycles.
Full automated CloneMount example
The following config combines every automation field so the entire CloneMount phase runs without any prompts — no IQN lookup, no disk number lookup, no manual pairing, and an explicit clone database name:
{
"phase": "CloneMount",
"portal": "10.0.0.10",
"clearOldPortals": false,
"manualIQN": "clones",
"attach": {
"sqlInstance": "localhost\\SQLINSTANCE",
"dataDriveLetter": "G",
"logDriveLetter": "H",
"skipPartitionAssign": true,
"autoPair": false,
"dbSelection": "ALL",
"databases": [
{
"name": "Clone_Sales_2026Q2",
"files": [
"G:\\MSSQL\\Data\\ISCSI_Sales_DATA1.mdf",
"H:\\MSSQL\\Logs\\ISCSI_Sales_LOG.ldf"
]
}
]
}
}
Skip Backup — Restore from existing .bak files via config.json
Run-IscsiWorkflow.ps1 v1.2 supports Mode 2 (Skip Backup) end-to-end from config. Populate migrate.backupPaths and the wrapper runs the same flow as the interactive Mode 2 walkthrough — read backup file headers, group striped backups by database name, and issue RESTORE DATABASE ... FROM DISK=... per group — without any prompts.
For a minimal Mode 2 config, see Migration mode examples → Mode 2. The detail below covers advanced source patterns and striped-backup handling.
backupPaths accepts three shapes — mix freely in the same array:
- A directory — auto-discovers all
*.bakfiles inside. - A wildcard — e.g.
C:\\Backups\\Sales*.bak. - An individual file — full path to a specific
.bak.
"backupPaths": [
"D:\\Backups",
"E:\\Archive\\Sales*.bak",
"F:\\Special\\CustomDB.bak"
]
Striped backups — All stripe files are grouped automatically by DatabaseName from the backup header, even if stripes are spread across different directories. The script runs RESTORE HEADERONLY on each file, then issues one RESTORE DATABASE ... FROM DISK='Part1.bak', DISK='Part2.bak', ... per group. No manual grouping required — just point at all stripe files (a single directory containing them, multiple directories, or individual file paths).
Full SourceMigrateOnly config with mixed sources:
{
"phase": "SourceMigrateOnly",
"migrate": {
"confirmStart": true,
"dataDriveLetter": "H",
"logDriveLetter": "I",
"backupPaths": [
"D:\\Backups",
"E:\\Archive\\Sales*.bak",
"F:\\Special\\CustomDB.bak"
],
"sourcePaths": {},
"confirmSelection": true,
"execute": true
}
}
Migration mode examples (config.json)
The migrate block in config.json controls which migration mode USECASE2 uses. The mode is auto-detected from the fields you populate:
| Priority | Field | Mode |
|---|---|---|
| Highest | sourcePaths populated | Mode 3 — Raw File Copy |
| Medium | backupPaths populated | Mode 2 — Skip Backup |
| Default | Both empty | Mode 1 — Backup and Restore |
| Mode 1 — Backup and Restore (default): | ||
Leave backupPaths empty and sourcePaths empty. The script backs up local databases and restores them to iSCSI. |
{
"phase": "SourceMigrateOnly",
"migrate": {
"dataDriveLetter": "H",
"logDriveLetter": "I",
"dbIds": "5,6",
"backupPaths": [],
"sourcePaths": {},
"confirmSelection": true,
"execute": true
}
}
Mode 2 — Skip Backup (restore from existing .bak files):
Populate backupPaths with the location of your .bak files. The script reads each backup header, auto-groups striped backups by database name, and restores directly to iSCSI — no BACKUP DATABASE step.
{
"phase": "SourceMigrateOnly",
"migrate": {
"dataDriveLetter": "H",
"logDriveLetter": "I",
"backupPaths": [
"D:\\Backups"
],
"sourcePaths": {},
"confirmSelection": true,
"execute": true
}
}
backupPaths also accepts multiple directories, wildcards, and individual files. For advanced patterns and striped backup details, see the Skip Backup — Restore from existing .bak files via config.json section above.
Mode 3 — Raw File Copy (loose .mdf/.ldf files):
Populate sourcePaths with a drive letter or full directory path. This takes highest priority — if sourcePaths is set, backupPaths is ignored.
{
"phase": "SourceMigrateOnly",
"migrate": {
"dataDriveLetter": "H",
"logDriveLetter": "I",
"backupPaths": [],
"sourcePaths": {
"dataPath": "C:\\Program Files\\Microsoft SQL Server\\MSSQL13.MSSQLSERVER\\MSSQL\\DATA",
"logPath": "C:\\Program Files\\Microsoft SQL Server\\MSSQL13.MSSQLSERVER\\MSSQL\\DATA"
},
"confirmSelection": true,
"execute": true
}
}
Or using a drive letter (scans entire drive recursively):
"sourcePaths": {
"dataPath": "D",
"logPath": "D"
}
Then run: .\Run-IscsiWorkflow.ps1 -ConfigPath .\config.json
Example configs by phase (validated against the wrapper)
SourcePrep (USECASE1 + USECASE2) — using manualIQN to skip target/disk number lookups
{
"phase": "SourcePrep",
"portal": "10.0.0.10",
"clearOldPortals": true,
"manualIQN": "data,log",
"dataDriveLetter": "H",
"logDriveLetter": "I",
"confirmPrep": true,
"migrate": {
"confirmStart": true,
"dataDriveLetter": "H",
"logDriveLetter": "I",
"dbIds": "ALL",
"backupPaths": [],
"sourcePaths": {},
"confirmSelection": true,
"execute": true
}
}
SourcePrepOnly (USECASE1 only) — classic numeric form
{
"phase": "SourcePrepOnly",
"portal": "10.0.0.10",
"clearOldPortals": true,
"targetSelection": "1,2",
"dataDiskNumber": 3,
"logDiskNumber": 4,
"dataDriveLetter": "H",
"logDriveLetter": "I",
"confirmPrep": true
}
SourceMigrateOnly (USECASE2 only) — using dbNameFilter instead of explicit dbIds
{
"phase": "SourceMigrateOnly",
"migrate": {
"confirmStart": true,
"dataDriveLetter": "H",
"logDriveLetter": "I",
"dbNameFilter": "Sales*",
"backupPaths": [],
"sourcePaths": {},
"confirmSelection": true,
"execute": true
}
}
CloneMount (USECASE3) — autoPair: true (no manual database list needed)
{
"phase": "CloneMount",
"portal": "10.0.0.10",
"manualIQN": "clones",
"attach": {
"sqlInstance": "localhost\\SQLINSTANCE",
"dataDriveLetter": "G",
"logDriveLetter": "H",
"autoPair": true,
"dbSelection": "ALL",
"skipPartitionAssign": true
}
}
CloneMount (USECASE3) — autoPair: false with explicit database names (see Manual pairing)
CloneUnmount (USECASE3_UNMOUNT)
{
"phase": "CloneUnmount",
"unmount": {
"sqlInstance": "localhost\\SQLINSTANCE",
"dbSelection": "ALL",
"disconnectTargets": "ALL",
"fullCleanup": true
}
}
CHAP authentication (optional)
Set chapUser and chapPassword for one-way CHAP. Add mutualChapPassword to enable mutual CHAP.
To use different credentials per target, add a targets array. The script matches each discovered target's IQN using substring matching. If no match is found, the top-level chapUser / chapPassword are used as a fallback. If neither is set, the target is connected without authentication.
mutualChapPassword is always global — Windows only supports a single initiator reverse CHAP secret system-wide. The script calls Set-IscsiChapSecret once before connecting.
CHAP secret length — Windows iSCSI Initiator enforces a length range of 12–16 ASCII characters on the CHAP secret. Shorter or longer values are rejected at connection time with an error like "Target CHAP secret given is invalid. Maximum size of CHAP secret is 16 bytes. Minimum size is 12 bytes if IPSec is not used." For predictable behavior, prefer 16 characters of mixed-case alphanumeric — Windows may auto-decode pure-hex strings to fewer bytes and reject them as too short.
{
"chapUser": "default-user",
"chapPassword": "default-password",
"mutualChapPassword": "global-mutual-secret",
"targets": [
{
"iqn": "iqn.2025-01.com.storage:lun-data",
"chapUser": "user-for-data",
"chapPassword": "secret-for-data"
},
{
"iqn": "iqn.2025-01.com.storage:lun-log",
"chapUser": "user-for-log",
"chapPassword": "secret-for-log"
}
]
}
The targets array is optional. Configs without it use the top-level chapUser / chapPassword for every connected target, or no CHAP at all if those are empty.
CHAP and the new automation fields (manualIQN, confirmPrep, attach.databases) compose freely — you can use them together in the same config.
Example configs by phase with CHAP
SourcePrep (USECASE1 + USECASE2) with per-target CHAP
{
"phase": "SourcePrep",
"portal": "10.0.0.10",
"clearOldPortals": true,
"manualIQN": "data,log",
"chapUser": "",
"chapPassword": "",
"mutualChapPassword": "",
"targets": [
{
"iqn": "iqn.2025-01.com.storage:lun-data",
"chapUser": "user-for-data",
"chapPassword": "secret-for-data"
},
{
"iqn": "iqn.2025-01.com.storage:lun-log",
"chapUser": "user-for-log",
"chapPassword": "secret-for-log"
}
],
"dataDriveLetter": "H",
"logDriveLetter": "I",
"confirmPrep": true,
"migrate": {
"confirmStart": true,
"dataDriveLetter": "H",
"logDriveLetter": "I",
"dbIds": "ALL",
"backupPaths": [],
"sourcePaths": {},
"confirmSelection": true,
"execute": true
}
}
SourcePrepOnly (USECASE1 only) with per-target CHAP
{
"phase": "SourcePrepOnly",
"portal": "10.0.0.10",
"clearOldPortals": true,
"manualIQN": "data,log",
"targets": [
{
"iqn": "iqn.2025-01.com.storage:lun-data",
"chapUser": "user-for-data",
"chapPassword": "secret-for-data"
},
{
"iqn": "iqn.2025-01.com.storage:lun-log",
"chapUser": "user-for-log",
"chapPassword": "secret-for-log"
}
],
"dataDriveLetter": "H",
"logDriveLetter": "I",
"confirmPrep": true
}
SourceMigrateOnly (USECASE2 only)
SourceMigrateOnly does not connect to iSCSI targets — it operates on disks already mounted by an earlier SourcePrep / SourcePrepOnly run. CHAP fields (chapUser, chapPassword, targets, mutualChapPassword) are therefore ignored for this phase. Listed here for completeness alongside the other phase examples.
{
"phase": "SourceMigrateOnly",
"migrate": {
"confirmStart": true,
"dataDriveLetter": "H",
"logDriveLetter": "I",
"dbIds": "ALL",
"backupPaths": [],
"sourcePaths": {},
"confirmSelection": true,
"execute": true
}
}
CloneMount (USECASE3) with per-target CHAP
{
"phase": "CloneMount",
"portal": "10.0.0.10",
"manualIQN": "clones",
"targets": [
{
"iqn": "iqn.2025-01.com.storage:clone-data",
"chapUser": "user-for-data",
"chapPassword": "secret-for-data"
},
{
"iqn": "iqn.2025-01.com.storage:clone-log",
"chapUser": "user-for-log",
"chapPassword": "secret-for-log"
}
],
"attach": {
"sqlInstance": "localhost\\SQLINSTANCE",
"dataDriveLetter": "G",
"logDriveLetter": "H",
"autoPair": true,
"dbSelection": "ALL",
"skipPartitionAssign": true
}
}
Chained phases example
{
"phase": ["SourcePrep", "SourceMigrateOnly"],
"portal": "10.0.0.10",
"clearOldPortals": true,
"manualIQN": "data,log",
"dataDriveLetter": "H",
"logDriveLetter": "I",
"confirmPrep": true,
"migrate": {
"dbIds": "ALL"
}
}
Verification Checklist
After Phase 1
- iSCSI disks are online.
- Data and log LUNs are NTFS with 64K cluster size.
- Drive letters are correct. After Phase 2
ISCSI_databases appear in SQL Server (Modes 1-2).- Database data/log files are on iSCSI drives.
- SQL Server service restarted successfully (Modes 1-2).
- For Mode 3: Files copied to iSCSI drives, ready for USECASE3 attach. After Phase 3
- Databases attach cleanly.
sys.databasesshows them ONLINE. After Phase 4ISCSI_databases detached.- iSCSI disks offline.
- Sessions disconnected (if cleanup chosen).
Troubleshooting Notes
- No targets discovered: Check the vME portal IP and access rules, confirm port 3260 is open, and ensure SendTargets is enabled on vME.
- sqlcmd fails: Verify SQL Server service is running, confirm Windows auth and sysadmin access, and check that
sqlcmdis in PATH. - Sector size mismatch: Ensure LUN sector size is compatible with SQL Server, and recreate LUNs if needed.
- Restore file/path conflicts: Ensure target
ISCSI_database names are not already in use, and verify target data/log file paths are not already used by another database. - File locked during raw copy (Mode 3): The script auto-offlines attached databases. If the error persists, manually detach the database or stop SQL Server before copying.
- Striped backup restore fails (Mode 2): Ensure all stripe files are provided — a partial set will fail. Verify all files belong to the same backup set.
JSON parse error: invalid escape sequencenearsqlInstance: A backslash inlocalhost\SQLINSTANCEmust be escaped tolocalhost\\SQLINSTANCEin JSON. See the note in Non-Interactive Config.- Cloned DB is not created when
autoPair: false: Earlier versions had no way to receive the database name and file list from config — the script would skip the attach. v1.2 adds theattach.databasesarray. See Manual pairing via config.json.















