Migration plans are the core orchestration resources that define which VMs to migrate, how to map their resources, and what settings to apply during migration. This chapter covers comprehensive plan creation with all supported configuration options.

Overview of Migration Plans

What is a Migration Plan?

A migration plan is a Kubernetes custom resource that defines:

  • VM Selection: Which VMs to migrate from the source provider
  • Resource Mapping: How to translate networks and storage to target resources
  • Migration Configuration: Type, timing, and behavioral settings
  • Target Customization: Where and how VMs should run on the target platform

Plan Components

Every migration plan includes:

  1. Source and Target Providers: Define the migration endpoints
  2. VM List: Specific VMs to include in the migration
  3. Mappings: Network and storage resource translations
  4. Migration Settings: Type, hooks, templates, and optimization options

VM Selection Methods

kubectl-mtv supports three flexible methods for VM selection, verified from the command code:

Method 1: Comma-separated List of VM Names

The simplest method specifies VM names directly:

1
2
3
4
5
6
7
8
9
# Basic VM list
kubectl mtv create plan simple-migration \
  --source vsphere-prod \
  --vms "web-server-01,db-server-01,app-server-01"

# Single VM migration
kubectl mtv create plan single-vm \
  --source vsphere-prod \
  --vms "critical-database-01"

Method 2: File Reference (--vms @file.yaml)

Use file references for complex VM configurations or large VM sets:

Create VM List File

1
2
3
4
5
6
7
8
# Save as vm-list.yaml
- name: web-server-01
  targetName: web-prod-01
- name: web-server-02
  targetName: web-prod-02
- name: database-01
  targetName: db-prod-01
  rootDisk: /dev/sda

Use File in Plan Creation

1
2
3
4
5
6
7
8
9
# Reference VM file
kubectl mtv create plan file-based-migration \
  --source vsphere-prod \
  --vms @vm-list.yaml

# Alternative: JSON format
kubectl mtv create plan json-migration \
  --source vsphere-prod \
  --vms @vm-list.json

Method 3: Query String Selection (--vms "where ...")

Use Tree Search Language (TSL) queries for dynamic VM selection:

Basic Query Selection

1
2
3
4
5
6
7
8
9
# Migrate all powered-on VMs
kubectl mtv create plan powered-on-vms \
  --source vsphere-prod \
  --vms "where powerState = 'poweredOn'"

# Migrate VMs by name pattern
kubectl mtv create plan production-vms \
  --source vsphere-prod \
  --vms "where name ~= '^prod-.*'"

Advanced Query Selection

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# Select VMs by resource criteria
kubectl mtv create plan small-vms \
  --source vsphere-prod \
  --vms "where powerState = 'poweredOn' and memoryMB <= 8192 and len disks <= 3"

# Select VMs in specific infrastructure
kubectl mtv create plan cluster-migration \
  --source vsphere-prod \
  --vms "where cluster.name = 'Production-Cluster' and not template"

# Complex multi-condition queries
kubectl mtv create plan filtered-migration \
  --source vsphere-prod \
  --vms "where (name ~= '^web-.*' or name ~= '^app-.*') and powerState = 'poweredOn' and memoryMB >= 4096"

Mapping Configuration Options in Plan Creation

Migration plans support three approaches for resource mapping:

Using Existing Mappings

Reference pre-created mapping resources:

1
2
3
4
5
6
7
8
9
10
11
12
13
# Use existing network and storage mappings
kubectl mtv create plan mapped-migration \
  --source vsphere-prod \
  --network-mapping production-network-map \
  --storage-mapping production-storage-map \
  --vms "web-01,web-02,db-01"

# Use mappings from different namespaces
kubectl mtv create plan cross-ns-mappings \
  --source vsphere-prod \
  --network-mapping shared-mappings/network-map \
  --storage-mapping shared-mappings/storage-map \
  --vms @vm-list.yaml

Using Inline Mapping Pairs

Define mappings directly in the plan creation command:

1
2
3
4
5
6
7
8
9
10
11
12
13
# Inline network and storage pairs
kubectl mtv create plan inline-mappings \
  --source vsphere-prod \
  --network-pairs "VM Network:default,Management Network:multus-system/mgmt-net" \
  --storage-pairs "datastore1:fast-ssd,datastore2:standard-storage" \
  --vms "web-server-01,app-server-01"

# Complex inline mappings with enhanced storage options
kubectl mtv create plan advanced-inline \
  --source vsphere-prod \
  --network-pairs "Production VLAN:prod-net,DMZ Network:security/dmz-net,Backup Network:ignored" \
  --storage-pairs "fast-ds:premium-ssd;volumeMode=Block;accessMode=ReadWriteOnce,shared-ds:shared-nfs;volumeMode=Filesystem;accessMode=ReadWriteMany" \
  --vms "where cluster.name = 'Prod-Cluster'"

Using Default Mappings (Simplest Approach)

Let kubectl-mtv create simple default mappings:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# Use default network and storage class
kubectl mtv create plan default-migration \
  --source vsphere-prod \
  --default-target-network default \
  --default-target-storage-class standard-ssd \
  --vms "test-vm-01,test-vm-02"

# Default pod networking and specific storage
kubectl mtv create plan pod-network-migration \
  --source vsphere-prod \
  --default-target-network default \
  --default-target-storage-class premium-nvme \
  --vms "where name ~= '^test-.*'"

# Auto-mapping (no mappings needed for any provider)
kubectl mtv create plan simple-migration \
  --source vsphere-prod \
  --vms "where powerState = 'poweredOn'"

Note: All source providers support automatic mapping generation. Provider-specific mappers intelligently match source networks and storage to appropriate target resources.

Key Plan Configuration Flags

Migration Types

kubectl-mtv supports four migration types (see Forklift Migration Types):

Type Description Use Case
cold Offline migration Production VMs where downtime is acceptable
warm Pre-copy with minimal downtime Large VMs where downtime must be minimized
live Live migration (KubeVirt sources only) Zero-downtime migration between KubeVirt clusters
conversion Guest conversion only (VMware only) When storage vendors provide pre-populated PVCs

For detailed information about conversion migration, including prerequisites, workflow, and integration requirements, see Chapter 3.6: Conversion Migration.

Migration Type Examples

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# Cold migration (default)
kubectl mtv create plan cold-migration \
  --source vsphere-prod \
  --migration-type cold \
  --vms "batch-processor-01,backup-server-01"

# Warm migration for large VMs
kubectl mtv create plan warm-migration \
  --source vsphere-prod \
  --migration-type warm \
  --vms "where memoryMB > 16384"

# Live migration (KubeVirt to KubeVirt)
kubectl mtv create plan live-migration \
  --source kubevirt-cluster1 \
  --migration-type live \
  --vms "production-workload-01"

# Conversion-only migration (VMware only)
# Prerequisites: PVCs must be pre-created with proper labels and annotations
kubectl mtv create plan conversion-only \
  --source vsphere-prod \
  --migration-type conversion \
  --vms "vm-with-precreated-pvcs"

Target Namespace and Transfer Network

Target Namespace Configuration

1
2
3
4
5
6
7
8
9
10
11
# Specify target namespace
kubectl mtv create plan namespaced-migration \
  --source vsphere-prod \
  --target-namespace production-workloads \
  --vms "prod-web-01,prod-api-01"

# Use current namespace (default)
kubectl mtv create plan current-ns-migration \
  --source vsphere-prod \
  --vms "dev-app-01,dev-db-01" \
  -n development

Transfer Network Configuration

1
2
3
4
5
6
7
8
9
10
11
# Use specific transfer network for disk operations
kubectl mtv create plan transfer-net-migration \
  --source vsphere-prod \
  --transfer-network migration-net \
  --vms "large-vm-01,large-vm-02"

# Cross-namespace transfer network
kubectl mtv create plan cross-ns-transfer \
  --source vsphere-prod \
  --transfer-network network-system/high-bandwidth \
  --vms "where sum disks.capacityGB > 500"

Naming Templates

kubectl-mtv provides Go template variables for customizing resource names:

PVC Name Template

Available variables: {{.VmName}}, {{.PlanName}}, {{.DiskIndex}}, {{.WinDriveLetter}}, {{.RootDiskIndex}}, {{.Shared}}, {{.FileName}}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# Custom PVC naming with plan and VM name
kubectl mtv create plan custom-pvc-names \
  --source vsphere-prod \
  --pvc-name-template "{{.PlanName}}-{{.VmName}}-disk-{{.DiskIndex}}" \
  --vms "web-01,web-02"

# Windows-specific PVC naming
kubectl mtv create plan windows-migration \
  --source vsphere-prod \
  --pvc-name-template "{{.VmName}}-{{.WinDriveLetter}}-disk" \
  --vms "where guestOS ~= '.*windows.*'"

# Shared disk identification
kubectl mtv create plan shared-disk-migration \
  --source vsphere-prod \
  --pvc-name-template "{{.VmName}}-{{if .Shared}}shared{{else}}local{{end}}-{{.DiskIndex}}" \
  --vms "cluster-node-01,cluster-node-02"

Volume Name Template

Available variables: {{.PVCName}}, {{.VolumeIndex}}

1
2
3
4
5
# Custom volume interface names
kubectl mtv create plan custom-volumes \
  --source vsphere-prod \
  --volume-name-template "vol-{{.VolumeIndex}}-{{.PVCName}}" \
  --vms "multi-disk-vm-01"

Network Name Template

Available variables: {{.NetworkName}}, {{.NetworkNamespace}}, {{.NetworkType}}, {{.NetworkIndex}}

1
2
3
4
5
# Custom network interface names
kubectl mtv create plan custom-networks \
  --source vsphere-prod \
  --network-name-template "{{.NetworkType}}-{{.NetworkIndex}}" \
  --vms "multi-nic-vm-01"

Advanced Plan Configuration

VM-Level Customization

Target VM Labels and Node Scheduling

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# Add labels to target VMs
kubectl mtv create plan labeled-migration \
  --source vsphere-prod \
  --target-labels "environment=production,team=platform,tier=web" \
  --vms "web-server-01,web-server-02"

# Node selector for VM placement
kubectl mtv create plan node-constrained \
  --source vsphere-prod \
  --target-node-selector "zone=east,storage=ssd" \
  --vms "performance-app-01"

# Combined labels and node selector
kubectl mtv create plan full-scheduling \
  --source vsphere-prod \
  --target-labels "app=database,performance=high" \
  --target-node-selector "zone=central,memory=high" \
  --vms "database-cluster-01"

VM Affinity with KARL (Kubernetes Affinity Rule Language)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# Require co-location with specific pods
kubectl mtv create plan affinity-colocation \
  --source vsphere-prod \
  --target-affinity "REQUIRE pods(app=database) on node" \
  --vms "app-server-01"

# Anti-affinity for high availability
kubectl mtv create plan ha-placement \
  --source vsphere-prod \
  --target-affinity "AVOID pods(app=web) on node" \
  --vms "web-server-03,web-server-04"

# Complex affinity rules
kubectl mtv create plan complex-affinity \
  --source vsphere-prod \
  --target-affinity "REQUIRE zone(east) AND AVOID pods(resource=intensive)" \
  --vms "latency-sensitive-01"

Target Power State Control

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# Keep VMs powered off after migration
kubectl mtv create plan offline-migration \
  --source vsphere-prod \
  --target-power-state off \
  --vms "backup-vm-01,archive-vm-01"

# Ensure VMs start after migration
kubectl mtv create plan online-migration \
  --source vsphere-prod \
  --target-power-state on \
  --vms "web-service-01,api-service-01"

# Auto power state (match source)
kubectl mtv create plan auto-power \
  --source vsphere-prod \
  --target-power-state auto \
  --vms "where powerState in ('poweredOn', 'suspended')"

Guest OS and Compatibility Settings

Guest Conversion Configuration

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# Skip guest conversion for Linux VMs
kubectl mtv create plan linux-migration \
  --source vsphere-prod \
  --skip-guest-conversion \
  --use-compatibility-mode \
  --vms "where guestOS ~= '.*linux.*'"

# Enable guest conversion with cleanup
kubectl mtv create plan windows-conversion \
  --source vsphere-prod \
  --delete-guest-conversion-pod \
  --vms "where guestOS ~= '.*windows.*'"

# Legacy driver installation for Windows
kubectl mtv create plan legacy-windows \
  --source vsphere-prod \
  --install-legacy-drivers true \
  --vms "windows-2012-server"

Static IP Preservation

1
2
3
4
5
6
7
8
9
10
11
# Preserve static IPs (vSphere only)
kubectl mtv create plan preserve-ips \
  --source vsphere-prod \
  --preserve-static-ips \
  --vms "database-01,web-lb-01"

# Disable IP preservation
kubectl mtv create plan new-ips \
  --source vsphere-prod \
  --preserve-static-ips=false \
  --vms "test-vm-01,dev-vm-01"

Convertor Pod Configuration

Configure the virt-v2v conversion pods:

1
2
3
4
5
6
7
8
9
10
11
12
# Convertor pod labels and scheduling
kubectl mtv create plan convertor-config \
  --source vsphere-prod \
  --convertor-labels "team=migration,priority=high" \
  --convertor-node-selector "conversion=true,cpu=high" \
  --vms "large-workload-01"

# Convertor affinity with KARL
kubectl mtv create plan convertor-affinity \
  --source vsphere-prod \
  --convertor-affinity "REQUIRE nodes(conversion=dedicated)" \
  --vms "complex-vm-01"

Disk and Storage Configuration

Shared Disk Migration

1
2
3
4
5
6
7
8
9
10
11
# Include shared disks in migration
kubectl mtv create plan shared-disks \
  --source vsphere-prod \
  --migrate-shared-disks \
  --vms "cluster-vm-01,cluster-vm-02"

# Exclude shared disks
kubectl mtv create plan no-shared-disks \
  --source vsphere-prod \
  --migrate-shared-disks=false \
  --vms "standalone-vm-01"

Preflight Inspection (Warm Migrations)

1
2
3
4
5
6
7
8
9
10
11
12
13
# Enable preflight disk inspection for warm migrations
kubectl mtv create plan warm-with-preflight \
  --source vsphere-prod \
  --migration-type warm \
  --run-preflight-inspection \
  --vms "critical-database-01"

# Disable preflight for faster warm start
kubectl mtv create plan warm-no-preflight \
  --source vsphere-prod \
  --migration-type warm \
  --run-preflight-inspection=false \
  --vms "test-warm-vm-01"

Migration Hooks Integration

Add hooks to run custom automation during migrations:

Pre-migration and Post-migration Hooks

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# Add pre and post hooks to all VMs
kubectl mtv create plan hooked-migration \
  --source vsphere-prod \
  --pre-hook backup-hook \
  --post-hook cleanup-hook \
  --vms "web-01,db-01"

# Pre-hook only for preparation tasks
kubectl mtv create plan prep-migration \
  --source vsphere-prod \
  --pre-hook application-quiesce \
  --vms "database-cluster-01"

# Post-hook only for validation
kubectl mtv create plan validated-migration \
  --source vsphere-prod \
  --post-hook health-check \
  --vms "web-service-01"

Complete Plan Creation Examples

Example 1: Enterprise Production Migration

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# Comprehensive enterprise migration plan
kubectl mtv create plan enterprise-production \
  --source vsphere-production \
  --target openshift-production \
  --network-mapping enterprise-network-map \
  --storage-mapping enterprise-storage-map \
  --migration-type warm \
  --target-namespace production-workloads \
  --transfer-network migration-backbone \
  --preserve-static-ips \
  --target-labels "environment=production,migration=phase1" \
  --target-node-selector "zone=east,performance=high" \
  --pvc-name-template "{{.PlanName}}-{{.VmName}}-{{.DiskIndex}}" \
  --pre-hook production-backup \
  --post-hook production-validation \
  --run-preflight-inspection \
  --delete-guest-conversion-pod \
  --vms "where cluster.name = 'Production-East' and powerState = 'poweredOn' and not template"

Example 2: Development Environment Migration

1
2
3
4
5
6
7
8
9
10
11
12
# Simple development migration
kubectl mtv create plan dev-migration \
  --source vsphere-dev \
  --migration-type cold \
  --default-target-network default \
  --default-target-storage-class standard-ssd \
  --target-namespace development \
  --skip-guest-conversion \
  --use-compatibility-mode \
  --target-power-state on \
  --vms "dev-web-01,dev-api-01,dev-db-01" \
  -n development

Example 3: Query-Based Batch Migration

1
2
3
4
5
6
7
8
9
10
11
# Large-scale query-driven migration
kubectl mtv create plan batch-small-vms \
  --source vsphere-prod \
  --migration-type cold \
  --network-pairs "VM Network:default,Management Network:ignored" \
  --storage-pairs "datastore1:standard-ssd,datastore2:premium-nvme;volumeMode=Block" \
  --target-labels "batch=phase1,size=small" \
  --convertor-node-selector "batch-processing=true" \
  --pvc-name-template "batch-{{.PlanName}}-{{.VmName}}-disk{{.DiskIndex}}" \
  --delete-vm-on-fail-migration \
  --vms "where powerState = 'poweredOn' and memoryMB <= 4096 and len disks <= 2 and not template"

Example 4: Multi-Provider Migration

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# oVirt to OpenShift migration
kubectl mtv create plan ovirt-migration \
  --source ovirt-production \
  --target openshift-target \
  --migration-type warm \
  --network-pairs "ovirtmgmt:default,production:prod-net" \
  --storage-pairs "data:standard-rwo;volumeMode=Filesystem,fast:premium-ssd;volumeMode=Block" \
  --preserve-cluster-cpu-model \
  --target-namespace migrated-workloads \
  --vms @ovirt-vm-list.yaml

# OpenStack to OpenShift migration
kubectl mtv create plan openstack-migration \
  --source openstack-prod \
  --target openshift-target \
  --migration-type cold \
  --network-pairs "internal:default,external:multus-system/external" \
  --storage-pairs "__DEFAULT__:standard-rwo,ssd:premium-ssd" \
  --target-labels "source=openstack,migration=batch2" \
  --vms "where flavor.name = 'm1.medium' and status = 'ACTIVE'"

Example 5: Storage Array Offloading

1
2
3
4
5
6
7
8
9
10
11
12
13
# Plan with storage array offloading
kubectl mtv create plan offload-migration \
  --source vsphere-prod \
  --storage-pairs "tier1-ds:flashsystem-gold;offloadPlugin=vsphere;offloadVendor=flashsystem" \
  --default-offload-plugin vsphere \
  --offload-vsphere-username vcenter-svc@vsphere.local \
  --offload-vsphere-password VCenterPassword \
  --offload-vsphere-url https://vcenter.company.com \
  --offload-storage-username flashsystem-admin \
  --offload-storage-password FlashSystemPassword \
  --offload-storage-endpoint https://flashsystem.company.com \
  --migration-type warm \
  --vms "where sum disks.capacityGB > 500"

Plan Validation and Testing

Pre-Creation Validation

1
2
3
4
5
6
7
8
9
10
11
12
# Test VM query before creating plan
kubectl mtv get inventory vms vsphere-prod \
  -q "where powerState = 'poweredOn' and memoryMB <= 8192" \
  -o table

# Validate mapping resources exist
kubectl mtv describe mapping network enterprise-network-map
kubectl mtv describe mapping storage enterprise-storage-map

# Check target namespace and resources
kubectl get storageclass premium-ssd
kubectl get network-attachment-definitions -n production

Dry-Run Planning

1
2
3
4
5
6
7
8
9
10
# Use --dry-run to validate without creating
kubectl mtv create plan test-validation \
  --source vsphere-prod \
  --vms "test-vm-01" \
  --dry-run=client

# Validate query results
kubectl mtv get inventory vms vsphere-prod \
  -q "where cluster.name = 'Test-Cluster'" \
  -o planvms > test-query-results.yaml

Plan Lifecycle Management

Plan Status Monitoring

1
2
3
4
5
6
7
8
# Check plan creation status
kubectl mtv get plans

# Detailed plan information
kubectl mtv describe plan enterprise-production

# Monitor plan progress
kubectl mtv get plan enterprise-production --watch

Plan Modification

1
2
3
4
5
6
7
8
9
# Plans are immutable after creation, but you can:

# 1. Create modified copy
kubectl get plan original-plan -o yaml > modified-plan.yaml
# Edit modified-plan.yaml
kubectl apply -f modified-plan.yaml

# 2. Use plan patching (covered in Chapter 15)
kubectl mtv patch plan enterprise-production --archived=true

Troubleshooting Plan Creation

Common Plan Creation Issues

VM Selection Errors

1
2
3
4
5
6
7
8
9
# Debug query results
kubectl mtv get inventory vms vsphere-prod \
  -q "where powerState = 'poweredOn'" \
  -v=2

# Check if VMs exist
for vm in vm1 vm2 vm3; do
  kubectl mtv get inventory vms vsphere-prod -q "where name = '$vm'"
done

Mapping Resolution Errors

1
2
3
4
5
6
7
8
# Verify mappings exist
kubectl get networkmapping,storagemapping -A

# Check mapping content
kubectl describe networkmapping enterprise-network-map

# Test inline pairs syntax
echo "source1:target1,source2:target2" | tr ',' '\n'

Resource Availability Issues

1
2
3
4
5
6
# Check target resources
kubectl get storageclass
kubectl get network-attachment-definitions -A

# Verify namespace access
kubectl auth can-i create virtualmachines -n target-namespace

Debug Plan Creation

1
2
3
4
5
6
7
8
9
10
11
# Enable verbose logging
kubectl mtv create plan debug-plan \
  --source vsphere-prod \
  --vms "debug-vm-01" \
  -v=2

# Check plan resource creation
kubectl get plan debug-plan -o yaml

# Monitor plan events
kubectl get events --sort-by='.metadata.creationTimestamp' | grep plan

Integration with Other Components

Integration with Inventory

1
2
3
4
5
6
7
8
9
10
11
12
13
# Use inventory queries in plans
kubectl mtv create plan inventory-driven \
  --source vsphere-prod \
  --vms "where cluster.name = 'Production' and host.name ~= 'esxi-0[1-3].*'"

# Export VMs for plan creation
kubectl mtv get inventory vms vsphere-prod \
  -q "where powerState = 'poweredOn'" \
  -o planvms > selected-vms.yaml

kubectl mtv create plan exported-vms \
  --source vsphere-prod \
  --vms @selected-vms.yaml

Integration with Mappings

1
2
3
4
5
6
7
8
9
10
# Reference existing mappings
kubectl mtv create plan mapped-migration \
  --network-mapping existing-network-map \
  --storage-mapping existing-storage-map

# Mix mappings and inline pairs (not allowed)
# This will error:
kubectl mtv create plan mixed-mappings \
  --network-mapping existing-map \
  --network-pairs "VM Network:default"  # Error: conflicting options

Best Practices for Plan Creation

Planning Strategy

  1. Start Small: Begin with test/development VMs
  2. Batch by Similarity: Group VMs with similar requirements
  3. Use Queries Effectively: Leverage TSL for dynamic VM selection
  4. Plan Resource Capacity: Ensure target resources can handle the workload

Configuration Best Practices

  1. Use Descriptive Names: Name plans clearly for operational clarity
  2. Leverage Templates: Use naming templates for consistent resource naming
  3. Document Dependencies: Maintain clear documentation of plan relationships
  4. Test Mappings: Validate mappings before large-scale migrations

Operational Best Practices

  1. Monitor Plan Progress: Use watching and logging for plan execution
  2. Plan for Rollback: Understand rollback procedures before starting
  3. Coordinate Teams: Ensure all stakeholders understand migration timing
  4. Validate Results: Have testing procedures ready for post-migration validation

Next Steps

After mastering plan creation:

  1. Customize VMs: Learn detailed VM customization in Chapter 11: Customizing Individual VMs (PlanVMS Format)
  2. Optimize Placement: Configure advanced placement in Chapter 12: Target VM Placement
  3. Execute Plans: Manage plan lifecycle in Chapter 16: Plan Lifecycle Execution
  4. Advanced Patching: Modify existing plans in Chapter 15: Advanced Plan Patching

Previous: Chapter 9.5: Storage Array Offloading and Optimization
Next: Chapter 11: Customizing Individual VMs (PlanVMS Format)