simplified instructions

This commit is contained in:
Kosta Mushkin
2025-06-12 20:09:35 -04:00
parent 4690e82e58
commit bd951d0811
7 changed files with 916 additions and 396 deletions
+41 -5
View File
@@ -58,21 +58,57 @@ The lab is divided into 7 exercises:
```
2. Create and activate a virtual environment:
**On macOS/Linux:**
```bash
python3 -m venv venv
source venv/bin/activate # On Windows, use: venv\Scripts\activate
source venv/bin/activate
```
3. Install required packages:
**On Windows:**
```cmd
python -m venv venv
venv\Scripts\activate
```
**On Windows PowerShell:**
```powershell
python -m venv venv
venv\Scripts\Activate.ps1
```
3. Install the Zerto Python SDK (`zvml` module):
**Option 1: Standard install**
```bash
cd ../zvml-python-sdk
pip install -r requirements.txt
pip install .
cd ../Zerto-Python-SDK-Hands-On-Labs
```
**Option 2: Development mode (recommended for contributors)**
```bash
cd ../zvml-python-sdk
pip install -r requirements.txt
pip install -e .
cd ../Zerto-Python-SDK-Hands-On-Labs
```
4. Install required packages:
```bash
pip install -r prerequisites/requirements.txt
```
4. Set up your environment:
5. Set up your environment:
- Copy `prerequisites/config.example.py` to `prerequisites/config.py`
- Update the configuration with your ZVM details
- Update the configuration with your ZVM details:
- **ZVM_HOST**: Your Zerto Virtual Manager IP address or hostname
- **CLIENT_ID**: Your Keycloak client ID (see Keycloak setup in config.example.py)
- **CLIENT_SECRET**: Your Keycloak client secret
- **Important**: Never commit your `config.py` file as it contains sensitive credentials
5. Start with Exercise 1 in the `exercises` directory
6. Start with Exercise 1 in the `exercises` directory
**Note:** When you're done working on the project, you can deactivate the virtual environment by typing `deactivate` in your terminal.
+74 -25
View File
@@ -3,44 +3,93 @@
## Overview
In this exercise, you'll learn how to authenticate with the Zerto API using Keycloak. You'll create a client and establish a connection to your ZVM.
## Objectives
- Create a Keycloak client
- Configure authentication parameters
- Test the connection to ZVM
- Handle authentication errors
## What You'll Learn
- How to create a ZVMLClient object (your "remote control" for ZVM)
- How to connect to your Zerto Virtual Manager
- How to test if the connection works
- How to handle errors if something goes wrong
## Time
10 minutes
## Prerequisites
- Completed Exercise 1
- Valid ZVM credentials
- Client ID and secret
- Completed Exercise 1
- Valid ZVM credentials (IP address, client ID, client secret)
- ✅ Updated `prerequisites/config.py` with your details
## Exercise Steps
1. Set up your configuration
2. Create the Keycloak client
3. Test the connection
4. Handle authentication errors
## Step-by-Step Instructions
### Step 1: Open the Working File
1. Navigate to `exercises/02_authentication/working/`
2. Open `auth.py` in your code editor
3. Read through the detailed comments - they explain everything!
### Step 2: Complete the Code
The file has three main sections you need to complete:
1. **Create ZVMLClient** - Replace `client = None` with actual code
2. **Test Connection** - Add code to test if it works
3. **Success Message** - Add a final success message
### Step 3: Run Your Code
```bash
cd exercises/02_authentication/working/
python auth.py
```
### Step 4: Check the Results
-**Success**: You'll see "Connection successful!" and ZVM version info
-**Error**: Check the error message and review your config.py
## Working Directory
The `working` directory contains:
- `auth.py` - Template to complete
- `auth.py` - **Beginner-friendly template** with detailed instructions
## Solution
The `solution` directory contains:
- `auth.py` - Complete working example
- `auth.py` - Complete working example (check this if you get stuck!)
## Key Concepts
- Keycloak authentication
- Client credentials flow
- Error handling
- Connection management
## Key Concepts Explained
## Common Issues
- Invalid credentials
- SSL certificate issues
- Network connectivity problems
### What is ZVMLClient?
- Think of it as a "remote control" for your Zerto Virtual Manager
- It handles all the communication between your Python code and ZVM
- You need to give it your ZVM address and login credentials
### What is Keycloak?
- It's the authentication system that Zerto uses
- You create a "client" (like a username) and get a "secret" (like a password)
- The ZVMLClient uses these to log into your ZVM
### What is SSL Verification?
- It's a security check to make sure you're connecting to the right server
- Usually set to `False` for Zerto (self-signed certificates)
## Common Issues & Solutions
### ❌ "Configuration file not found"
**Solution**: Copy `prerequisites/config.example.py` to `prerequisites/config.py`
### ❌ "Authentication failed"
**Solutions**:
- Check your ZVM_HOST is correct
- Verify your CLIENT_ID and CLIENT_SECRET
- Make sure your ZVM is running and accessible
### ❌ "SSL certificate" errors
**Solution**: Make sure `ZVM_SSL_VERIFY = False` in your config.py
### ❌ "Connection refused" or "Network unreachable"
**Solutions**:
- Check your ZVM IP address is correct
- Make sure you can ping the ZVM from your computer
- Check firewall settings
## Need Help?
1. Read the detailed comments in the code
2. Check the solution file
3. Review your `config.py` settings
4. Ask your Zerto administrator for help with credentials
## Next Steps
Proceed to Exercise 3: Site Discovery to start working with Zerto sites.
Once you successfully connect, proceed to **Exercise 3: Site Discovery** to start working with Zerto sites.
+97 -41
View File
@@ -1,20 +1,31 @@
#!/usr/bin/env python3
"""
Exercise 2: Authentication
Exercise 2: Authentication - Beginner-Friendly Instructions
This script demonstrates how to authenticate with Zerto API using Keycloak.
Prerequisites:
1. Install the zvml package in development mode:
cd /path/to/zvml-python-sdk
pip install -e .
2. Update prerequisites/config.py with your ZVM details
PREREQUISITES (Complete these first):
1. Make sure you have the zvml package installed (see main README)
2. Update prerequisites/config.py with your ZVM details:
- ZVM_HOST: Your Zerto Virtual Manager IP address or hostname
- CLIENT_ID: Your Keycloak client ID
- CLIENT_SECRET: Your Keycloak client secret
Your task:
1. Initialize ZVMLClient with Keycloak credentials
2. Test connection by retrieving local site information
3. Handle authentication and connection errors
WHAT YOU NEED TO DO:
In this exercise, you will:
1. Create a ZVMLClient object to connect to your ZVM
2. Test the connection by getting information about your local site
3. Handle any errors that might occur
If you need help, check the solution in the solution directory.
STEP-BY-STEP INSTRUCTIONS:
1. Look at the TODO comments below - they tell you exactly what to do
2. Replace the placeholder code with the actual code
3. Each step has hints and examples to help you
4. If you get stuck, check the solution file in the solution/ directory
WHAT IS A ZVMLClient?
- It's like a "remote control" for your Zerto Virtual Manager
- It handles all the communication with your ZVM
- You need to give it your ZVM address and login credentials
"""
import sys
@@ -23,61 +34,106 @@ import logging
import json
from pathlib import Path
# Add prerequisites to Python path
# Add prerequisites to Python path (this helps Python find your config file)
prerequisites_path = Path(__file__).parent.parent.parent.parent / "prerequisites"
sys.path.append(str(prerequisites_path))
# Import the SDK modules
# Import the Zerto SDK - this gives us the ZVMLClient class
from zvml import ZVMLClient
# Import configuration
# Import your configuration settings
try:
from config import (
ZVM_HOST,
ZVM_PORT,
ZVM_SSL_VERIFY,
CLIENT_ID,
CLIENT_SECRET
ZVM_HOST, # Your ZVM IP address (e.g., "192.168.1.100")
ZVM_PORT, # Usually 443 for HTTPS
ZVM_SSL_VERIFY, # True/False for SSL certificate verification
CLIENT_ID, # Your Keycloak client ID (e.g., "my-api-client")
CLIENT_SECRET # Your Keycloak client secret
)
except ImportError:
print("Error: Please copy config.example.py to config.py and update with your values")
print("❌ ERROR: Configuration file not found!")
print("Please copy config.example.py to config.py and update with your values")
print("Expected path:", prerequisites_path / "config.py")
sys.exit(1)
def main():
"""
Main function to demonstrate Zerto authentication.
Complete the following steps:
1. Initialize ZVMLClient with Keycloak credentials
2. Test connection by retrieving local site info
3. Handle authentication and connection errors
Main function - this is where your code goes!
Follow the step-by-step instructions below.
"""
# Set up logging with timestamp
# Set up logging so you can see what's happening
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s'
)
print("🚀 Starting Zerto Authentication Exercise")
print("=" * 50)
try:
# Step 1: Create a ZVMLClient instance
# TODO: Initialize the ZVMLClient with your ZVM host and credentials
# Hint: Use ZVMLClient(zvm_address=ZVM_HOST, client_id=CLIENT_ID,
# client_secret=CLIENT_SECRET, verify_certificate=ZVM_SSL_VERIFY)
client = None # Replace with actual client initialization
# ========================================
# STEP 1: Create a ZVMLClient instance
# ========================================
print("\n📝 STEP 1: Creating ZVMLClient...")
print("You need to replace the line 'client = None' with actual code.")
print("Look at the hint below for the correct syntax.")
# Step 2: Test the connection
# TODO: Try to get local site information to verify the connection
# Hint: Use client.localsite.get_local_site() and extract the Version
# Hint: Log the version using logging.info()
pass # Replace with actual connection test
# TODO: Replace this line with actual ZVMLClient creation
# HINT: Use this syntax:
# client = ZVMLClient(
# zvm_address=ZVM_HOST,
# client_id=CLIENT_ID,
# client_secret=CLIENT_SECRET,
# verify_certificate=ZVM_SSL_VERIFY
# )
#
# EXPLANATION:
# - zvm_address: Where your ZVM is located (from config.py)
# - client_id: Your Keycloak client ID (from config.py)
# - client_secret: Your Keycloak client secret (from config.py)
# - verify_certificate: Whether to check SSL certificates (from config.py)
# Step 3: Print connection status
# TODO: Display whether the connection was successful
# Hint: Use logging.info() to show the status
client = None # ← REPLACE THIS LINE WITH YOUR CODE
# ========================================
# STEP 2: Test the connection
# ========================================
print("\n📝 STEP 2: Testing connection...")
print("You need to test if the connection works by getting local site info.")
print("Look at the hint below for the correct syntax.")
# TODO: Add code to test the connection
# HINT: Use this syntax:
# local_site = client.localsite.get_local_site()
# version = local_site.get('Version')
# logging.info(f"Successfully connected to ZVM version: {version}")
#
# EXPLANATION:
# - client.localsite.get_local_site() gets information about your local ZVM
# - local_site.get('Version') extracts the ZVM version from the response
# - logging.info() displays a success message
# ← ADD YOUR CODE HERE
# ========================================
# STEP 3: Display success message
# ========================================
print("\n📝 STEP 3: Displaying success message...")
print("You need to add a final success message.")
# TODO: Add a success message
# HINT: Use this syntax:
# logging.info("🎉 Connection successful!")
#
# EXPLANATION:
# This confirms that everything worked correctly
# ← ADD YOUR CODE HERE
except Exception as e:
# TODO: Handle any authentication or connection errors
# Hint: Use logging.error() to log the error message
# This catches any errors that might occur
print(f"\n❌ ERROR: Something went wrong!")
print(f"Error details: {str(e)}")
logging.error(f"Authentication failed: {str(e)}")
sys.exit(1)
+106 -41
View File
@@ -1,19 +1,30 @@
#!/usr/bin/env python3
"""
Exercise 3: Site Discovery
Exercise 3: Site Discovery - Beginner-Friendly Instructions
This script demonstrates how to discover and work with Zerto virtualization sites.
Prerequisites:
1. Install the zvml package in development mode:
cd /path/to/zvml-python-sdk
pip install -e .
2. Update prerequisites/config.py with your ZVM details
PREREQUISITES (Complete these first):
1. ✅ Completed Exercise 2 (Authentication)
2. ✅ Make sure you have the zvml package installed
3. ✅ Updated prerequisites/config.py with your ZVM details
Your task:
1. List all available virtualization sites
2. Get and display local site information
WHAT YOU NEED TO DO:
In this exercise, you will:
1. Create a ZVMLClient to connect to your ZVM (same as Exercise 2)
2. Get a list of all available virtualization sites
3. Get detailed information about your local site
If you need help, check the solution in the solution directory.
STEP-BY-STEP INSTRUCTIONS:
1. Look at the TODO comments below - they tell you exactly what to do
2. Replace the placeholder code with the actual code
3. Each step has hints and examples to help you
4. If you get stuck, check the solution file in the solution/ directory
WHAT ARE VIRTUALIZATION SITES?
- A "site" in Zerto is a location where you have virtual machines
- Your "local site" is where your ZVM is running
- "Peer sites" are other locations you can replicate to/from
- Each site has information like name, type, version, etc.
"""
import sys
@@ -22,62 +33,116 @@ import logging
import json
from pathlib import Path
# Add prerequisites to Python path
# Add prerequisites to Python path (this helps Python find your config file)
prerequisites_path = Path(__file__).parent.parent.parent.parent / "prerequisites"
sys.path.append(str(prerequisites_path))
# Import the SDK modules
# Import the Zerto SDK - this gives us the ZVMLClient class
from zvml import ZVMLClient
# Import configuration
# Import your configuration settings
try:
from config import (
ZVM_HOST,
ZVM_PORT,
ZVM_SSL_VERIFY,
CLIENT_ID,
CLIENT_SECRET
ZVM_HOST, # Your ZVM IP address (e.g., "192.168.1.100")
ZVM_PORT, # Usually 443 for HTTPS
ZVM_SSL_VERIFY, # True/False for SSL certificate verification
CLIENT_ID, # Your Keycloak client ID (e.g., "my-api-client")
CLIENT_SECRET # Your Keycloak client secret
)
except ImportError:
print("Error: Please copy config.example.py to config.py and update with your values")
print("❌ ERROR: Configuration file not found!")
print("Please copy config.example.py to config.py and update with your values")
print("Expected path:", prerequisites_path / "config.py")
sys.exit(1)
def main():
"""
Main function to demonstrate site discovery.
Complete the following steps:
1. List all available virtualization sites
2. Get and display local site information
Main function - this is where your code goes!
Follow the step-by-step instructions below.
"""
# Set up logging with timestamp
# Set up logging so you can see what's happening
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s'
)
print("🚀 Starting Zerto Site Discovery Exercise")
print("=" * 50)
try:
# Step 1: Create a ZVMLClient instance
# TODO: Initialize the ZVMLClient with your ZVM host and credentials
# Hint: Use ZVMLClient(zvm_address=ZVM_HOST, client_id=CLIENT_ID,
# client_secret=CLIENT_SECRET, verify_certificate=ZVM_SSL_VERIFY)
client = None # Replace with actual client initialization
# ========================================
# STEP 1: Create a ZVMLClient instance
# ========================================
print("\n📝 STEP 1: Creating ZVMLClient...")
print("This is the same as Exercise 2 - you need to create a client to connect to ZVM.")
# Step 2: List all available sites
# TODO: Get the list of virtualization sites
# Hint: Use client.virtualization_sites.get_virtualization_sites()
# Hint: Log the number of sites found and their details using json.dumps()
pass # Replace with actual site listing
# TODO: Replace this line with actual ZVMLClient creation
# HINT: Use this syntax (same as Exercise 2):
# client = ZVMLClient(
# zvm_address=ZVM_HOST,
# client_id=CLIENT_ID,
# client_secret=CLIENT_SECRET,
# verify_certificate=ZVM_SSL_VERIFY
# )
#
# EXPLANATION:
# This creates a connection to your ZVM (same as Exercise 2)
# Step 3: Get and display local site information
# TODO: Get and display local site information
# Hint: Use client.localsite.get_local_site()
# Hint: Log the local site details using json.dumps()
pass # Replace with actual local site retrieval
client = None # ← REPLACE THIS LINE WITH YOUR CODE
# ========================================
# STEP 2: List all available sites
# ========================================
print("\n📝 STEP 2: Getting list of sites...")
print("You need to get a list of all virtualization sites available to your ZVM.")
# TODO: Add code to get the list of sites
# HINT: Use this syntax:
# sites = client.virtualization_sites.get_virtualization_sites()
#
# EXPLANATION:
# - client.virtualization_sites.get_virtualization_sites() gets all sites
# - This returns a list of site information
# ← ADD YOUR CODE HERE
# TODO: Add code to display the sites
# HINT: Use this syntax:
# if not sites:
# logging.warning("No sites found!")
# else:
# logging.info(f"Found {len(sites)} site(s):")
# logging.info(f'Sites Info: {json.dumps(sites, indent=4)}')
#
# EXPLANATION:
# - len(sites) counts how many sites were found
# - json.dumps(sites, indent=4) formats the site data nicely
# - logging.info() displays the information
# ← ADD YOUR CODE HERE
# ========================================
# STEP 3: Get local site information
# ========================================
print("\n📝 STEP 3: Getting local site details...")
print("You need to get detailed information about your local site.")
# TODO: Add code to get local site information
# HINT: Use this syntax:
# local_site = client.localsite.get_local_site()
# logging.info(f"Local site details: {json.dumps(local_site, indent=4)}")
#
# EXPLANATION:
# - client.localsite.get_local_site() gets info about your local ZVM
# - This includes version, name, type, and other details
# - json.dumps(local_site, indent=4) formats it nicely
# ← ADD YOUR CODE HERE
except Exception as e:
# TODO: Handle any site discovery errors
# Hint: Use logging.error() to log the error message
# This catches any errors that might occur
print(f"\n❌ ERROR: Something went wrong!")
print(f"Error details: {str(e)}")
logging.error(f"Site discovery failed: {str(e)}")
sys.exit(1)
@@ -1,19 +1,36 @@
#!/usr/bin/env python3
"""
Exercise 4: Resource Discovery
Exercise 4: Resource Discovery - Beginner-Friendly Instructions
This script demonstrates how to discover and work with resources in your Zerto environment.
Prerequisites:
1. Install the zvml package in development mode:
cd /path/to/zvml-python-sdk
pip install -e .
2. Update prerequisites/config.py with your ZVM details
PREREQUISITES (Complete these first):
1. ✅ Completed Exercise 3 (Site Discovery)
2. ✅ Make sure you have the zvml package installed
3. ✅ Updated prerequisites/config.py with your ZVM details
Your task:
1. Discover local site resources (VMs)
2. Work with peer site resources (datastores, hosts, folders, networks)
WHAT YOU NEED TO DO:
In this exercise, you will:
1. Create a ZVMLClient to connect to your ZVM (same as previous exercises)
2. Get a list of all available sites
3. Identify your local site and a peer site
4. Discover different types of resources:
- Local site: Virtual Machines (VMs)
- Peer site: Datastores, Hosts, Folders, Networks
If you need help, check the solution in the solution directory.
STEP-BY-STEP INSTRUCTIONS:
1. Look at the TODO comments below - they tell you exactly what to do
2. Replace the placeholder code with the actual code
3. Each step has hints and examples to help you
4. If you get stuck, check the solution file in the solution/ directory
WHAT ARE RESOURCES?
- **VMs**: Virtual machines that can be protected/replicated
- **Datastores**: Storage locations where VMs are stored
- **Hosts**: Physical servers that run the VMs
- **Folders**: Organizational containers for VMs
- **Networks**: Network connections for VMs
- **Local Site**: Your current ZVM location
- **Peer Site**: Another location you can replicate to/from
"""
import sys
@@ -22,104 +39,173 @@ import logging
import json
from pathlib import Path
# Add prerequisites to Python path
# Add prerequisites to Python path (this helps Python find your config file)
prerequisites_path = Path(__file__).parent.parent.parent.parent / "prerequisites"
sys.path.append(str(prerequisites_path))
# Import the SDK modules
# Import the Zerto SDK - this gives us the ZVMLClient class
from zvml import ZVMLClient
# Import configuration
# Import your configuration settings
try:
from config import (
ZVM_HOST,
ZVM_PORT,
ZVM_SSL_VERIFY,
CLIENT_ID,
CLIENT_SECRET
ZVM_HOST, # Your ZVM IP address (e.g., "192.168.1.100")
ZVM_PORT, # Usually 443 for HTTPS
ZVM_SSL_VERIFY, # True/False for SSL certificate verification
CLIENT_ID, # Your Keycloak client ID (e.g., "my-api-client")
CLIENT_SECRET # Your Keycloak client secret
)
except ImportError:
print("Error: Please copy config.example.py to config.py and update with your values")
print("❌ ERROR: Configuration file not found!")
print("Please copy config.example.py to config.py and update with your values")
print("Expected path:", prerequisites_path / "config.py")
sys.exit(1)
def main():
"""
Main function to demonstrate resource discovery.
Complete the following steps:
1. Discover local site resources (VMs)
2. Work with peer site resources (datastores, hosts, folders, networks)
Main function - this is where your code goes!
Follow the step-by-step instructions below.
"""
# Set up logging with timestamp
# Set up logging so you can see what's happening
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s'
)
print("🚀 Starting Zerto Resource Discovery Exercise")
print("=" * 50)
try:
# Step 1: Create a ZVMLClient instance
# TODO: Initialize the ZVMLClient with your ZVM host and credentials
# Hint: Use ZVMLClient(zvm_address=ZVM_HOST, client_id=CLIENT_ID,
# client_secret=CLIENT_SECRET, verify_certificate=ZVM_SSL_VERIFY)
client = None # Replace with actual client initialization
# ========================================
# STEP 1: Create a ZVMLClient instance
# ========================================
print("\n📝 STEP 1: Creating ZVMLClient...")
print("This is the same as previous exercises - you need to create a client to connect to ZVM.")
# Step 2: Identify local and peer sites
# Step 2.1: List all available sites
# TODO: Get the list of available sites
# Hint: Use client.virtualization_sites.get_virtualization_sites()
# Hint: Log the number of sites found and their details using json.dumps()
pass # Replace with actual site listing
# TODO: Replace this line with actual ZVMLClient creation
# HINT: Use this syntax (same as previous exercises):
# client = ZVMLClient(
# zvm_address=ZVM_HOST,
# client_id=CLIENT_ID,
# client_secret=CLIENT_SECRET,
# verify_certificate=ZVM_SSL_VERIFY
# )
# Step 2.2: Get local and peer site identifiers
# TODO: Get local site identifier
# Hint: Use client.localsite.get_local_site()
# Hint: Extract the SiteIdentifier from the response
local_site_identifier = None # Replace with actual local site identifier
client = None # ← REPLACE THIS LINE WITH YOUR CODE
# TODO: Get peer site identifier
# Hint: Find the first site that is not the local site
# Hint: Extract the SiteIdentifier from that site
peer_site_identifier = None # Replace with actual peer site identifier
# ========================================
# STEP 2: Identify local and peer sites
# ========================================
print("\n📝 STEP 2.1: Getting list of sites...")
print("You need to get a list of all available sites (same as Exercise 3).")
# Step 3: Get local site resources
# Step 3.1: Get local site VMs
# TODO: Get VMs for the local site
# Hint: Use client.virtualization_sites.get_virtualization_site_vms()
# Hint: Pass the local_site_identifier as site_identifier parameter
# Hint: Log the VMs information using json.dumps()
pass # Replace with actual VM retrieval
# TODO: Add code to get the list of sites
# HINT: Use this syntax:
# sites = client.virtualization_sites.get_virtualization_sites()
#
# EXPLANATION:
# This gets all sites available to your ZVM
# Step 3.2: Get peer site datastores
# TODO: Get datastores for the peer site
# Hint: Use client.virtualization_sites.get_virtualization_site_datastores()
# Hint: Pass the peer_site_identifier as site_identifier parameter
# Hint: Log the datastores information using json.dumps()
pass # Replace with actual datastore retrieval
# ← ADD YOUR CODE HERE
# Step 3.3: Get peer site hosts
# TODO: Get hosts for the peer site
# Hint: Use client.virtualization_sites.get_virtualization_site_hosts()
# Hint: Pass the peer_site_identifier as site_identifier parameter
# Hint: Log the hosts information using json.dumps()
pass # Replace with actual host retrieval
print("\n📝 STEP 2.2: Getting local site identifier...")
print("You need to get the identifier for your local site.")
# Step 3.4: Get peer site folders
# TODO: Get folders for the peer site
# Hint: Use client.virtualization_sites.get_virtualization_site_folders()
# Hint: Pass the peer_site_identifier as site_identifier parameter
# Hint: Log the folders information using json.dumps()
pass # Replace with actual folder retrieval
# TODO: Add code to get local site identifier
# HINT: Use this syntax:
# local_site_identifier = client.localsite.get_local_site().get('SiteIdentifier')
#
# EXPLANATION:
# - client.localsite.get_local_site() gets your local site info
# - .get('SiteIdentifier') extracts the unique identifier
# Step 3.5: Get peer site networks
# TODO: Get networks for the peer site
# Hint: Use client.virtualization_sites.get_virtualization_site_networks()
# Hint: Pass the peer_site_identifier as site_identifier parameter
# Hint: Log the networks information using json.dumps()
pass # Replace with actual network retrieval
local_site_identifier = None # ← REPLACE THIS LINE WITH YOUR CODE
print("\n📝 STEP 2.3: Getting peer site identifier...")
print("You need to find a peer site (any site that's not your local site).")
# TODO: Add code to get peer site identifier
# HINT: Use this syntax:
# peer_site = next((site for site in sites if site.get('SiteIdentifier') != local_site_identifier), None)
# peer_site_identifier = peer_site.get('SiteIdentifier')
#
# EXPLANATION:
# - This finds the first site that's not your local site
# - next() gets the first matching site from the list
# - .get('SiteIdentifier') extracts the unique identifier
peer_site_identifier = None # ← REPLACE THIS LINE WITH YOUR CODE
# ========================================
# STEP 3: Get local site resources
# ========================================
print("\n📝 STEP 3.1: Getting local site VMs...")
print("You need to get all virtual machines from your local site.")
# TODO: Add code to get local site VMs
# HINT: Use this syntax:
# local_vms = client.virtualization_sites.get_virtualization_site_vms(site_identifier=local_site_identifier)
#
# EXPLANATION:
# This gets all VMs that can be protected/replicated from your local site
# ← ADD YOUR CODE HERE
# ========================================
# STEP 4: Get peer site resources
# ========================================
print("\n📝 STEP 4.1: Getting peer site datastores...")
print("You need to get datastores from the peer site.")
# TODO: Add code to get peer site datastores
# HINT: Use this syntax:
# peer_datastores = client.virtualization_sites.get_virtualization_site_datastores(site_identifier=peer_site_identifier)
#
# EXPLANATION:
# Datastores are storage locations where VMs can be stored on the peer site
# ← ADD YOUR CODE HERE
print("\n📝 STEP 4.2: Getting peer site hosts...")
print("You need to get hosts from the peer site.")
# TODO: Add code to get peer site hosts
# HINT: Use this syntax:
# peer_hosts = client.virtualization_sites.get_virtualization_site_hosts(site_identifier=peer_site_identifier)
#
# EXPLANATION:
# Hosts are physical servers that can run VMs on the peer site
# ← ADD YOUR CODE HERE
print("\n📝 STEP 4.3: Getting peer site folders...")
print("You need to get folders from the peer site.")
# TODO: Add code to get peer site folders
# HINT: Use this syntax:
# peer_folders = client.virtualization_sites.get_virtualization_site_folders(site_identifier=peer_site_identifier)
#
# EXPLANATION:
# Folders are organizational containers for VMs on the peer site
# ← ADD YOUR CODE HERE
print("\n📝 STEP 4.4: Getting peer site networks...")
print("You need to get networks from the peer site.")
# TODO: Add code to get peer site networks
# HINT: Use this syntax:
# peer_networks = client.virtualization_sites.get_virtualization_site_networks(site_identifier=peer_site_identifier)
#
# EXPLANATION:
# Networks are network connections that VMs can use on the peer site
# ← ADD YOUR CODE HERE
except Exception as e:
# TODO: Handle any resource discovery errors
# Hint: Use logging.error() to log the error message
# This catches any errors that might occur
print(f"\n❌ ERROR: Something went wrong!")
print(f"Error details: {str(e)}")
logging.error(f"Resource discovery failed: {str(e)}")
sys.exit(1)
+247 -88
View File
@@ -1,28 +1,39 @@
#!/usr/bin/env python3
"""
Exercise 5: VPG Operations - Template
Exercise 5: VPG Operations - Beginner-Friendly Instructions
This script demonstrates how to create and configure VPGs in your Zerto environment.
Prerequisites:
1. Install the zvml package in development mode:
cd /path/to/zvml-python-sdk
pip install -e .
2. Update prerequisites/config.py with your ZVM details
PREREQUISITES (Complete these first):
1. ✅ Completed Exercise 4 (Resource Discovery)
2. ✅ Make sure you have the zvml package installed
3. ✅ Updated prerequisites/config.py with your ZVM details
4. ✅ Have some unprotected VMs available in your local site
Usage:
python create_vpg.py --vm-names "vm1" "vm2" "vm3" [--vpg-name "My-VPG"]
WHAT YOU NEED TO DO:
In this exercise, you will:
1. Create a ZVMLClient to connect to your ZVM
2. Parse command line arguments (VM names and VPG name)
3. Find VMs by their names in your local site
4. Get peer site resources (datastores, folders, networks, hosts)
5. Create a VPG configuration with all necessary settings
6. Create the VPG
7. Add VMs to the VPG
8. Optionally remove a VM from the VPG
Your task:
1. Implement the find_vms_by_names function to locate VMs by their names
2. Complete the VPG configuration with appropriate settings
3. Add the found VMs to the VPG
4. Implement VM removal functionality
STEP-BY-STEP INSTRUCTIONS:
1. Look at the TODO comments below - they tell you exactly what to do
2. Replace the placeholder code with the actual code
3. Each step has hints and examples to help you
4. If you get stuck, check the solution file in the solution/ directory
The script should:
- Create a new VPG with basic settings
- Configure journal, recovery, and network settings
- Add specified VMs to the VPG
- Allow removing VMs from the VPG
WHAT IS A VPG?
- **VPG** = Virtual Protection Group
- It's a group of VMs that are protected together
- All VMs in a VPG have the same protection settings
- You can replicate VMs from one site to another using VPGs
USAGE EXAMPLE:
python create_vpg.py --vm-names "vm1" "vm2" "vm3" --vpg-name "My-VPG"
"""
import sys
@@ -36,112 +47,183 @@ import urllib3
# Suppress SSL warnings
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
# Add prerequisites to Python path
# Add prerequisites to Python path (this helps Python find your config file)
prerequisites_path = Path(__file__).parent.parent.parent.parent / "prerequisites"
sys.path.append(str(prerequisites_path))
# Import the SDK modules
# Import the Zerto SDK - this gives us the ZVMLClient class
from zvml import ZVMLClient
# Import configuration
# Import your configuration settings
try:
from config import (
ZVM_HOST,
ZVM_PORT,
ZVM_SSL_VERIFY,
CLIENT_ID,
CLIENT_SECRET
ZVM_HOST, # Your ZVM IP address (e.g., "192.168.1.100")
ZVM_PORT, # Usually 443 for HTTPS
ZVM_SSL_VERIFY, # True/False for SSL certificate verification
CLIENT_ID, # Your Keycloak client ID (e.g., "my-api-client")
CLIENT_SECRET # Your Keycloak client secret
)
except ImportError:
print("Error: Please copy config.example.py to config.py and update with your values")
print("❌ ERROR: Configuration file not found!")
print("Please copy config.example.py to config.py and update with your values")
print("Expected path:", prerequisites_path / "config.py")
sys.exit(1)
def parse_arguments():
"""Parse command line arguments."""
# TODO: Implement argument parsing
# Required arguments:
# --vm-names: List of VM names to add to the VPG
# Optional arguments:
# --vpg-name: Name of the VPG to create (default: "Test-VPG-Python")
pass
"""
Parse command line arguments.
TODO: Implement argument parsing
HINT: Use this syntax:
parser = argparse.ArgumentParser(description='Create VPG and add specified VMs')
parser.add_argument('--vm-names', nargs='+', required=True,
help='List of VM names to add to the VPG')
parser.add_argument('--vpg-name', default="Test-VPG-Python",
help='Name of the VPG to create (default: Test-VPG-Python)')
return parser.parse_args()
EXPLANATION:
- argparse helps you get command line arguments
- --vm-names: List of VM names (required)
- --vpg-name: Name for the VPG (optional, has default)
"""
pass # ← REPLACE WITH YOUR CODE
def find_vms_by_names(client, site_identifier, vm_names):
"""
Find VMs by their names in the specified site.
Args:
client: ZVMLClient instance
site_identifier: Identifier of the site to search in
vm_names: List of VM names to find
Returns:
tuple: (list of found VMs, list of not found VM names)
TODO: Implement the function to:
1. Get all unprotected VMs from the site
2. Create a dictionary for easy lookup
3. Find requested as an argument VMs
4. Return found and not found VMs
1. Get all VMs from the site using client.virtualization_sites.get_virtualization_site_vms()
2. Create a dictionary for easy lookup: {vm.get('VmName'): vm for vm in vms}
3. Find requested VMs and return found/not found lists
HINT: Use this syntax:
vms = client.virtualization_sites.get_virtualization_site_vms(site_identifier=site_identifier)
vm_dict = {vm.get('VmName'): vm for vm in vms}
found_vms = []
not_found = []
for vm_name in vm_names:
if vm_name in vm_dict:
found_vms.append(vm_dict[vm_name])
else:
not_found.append(vm_name)
return found_vms, not_found
"""
pass
pass # ← REPLACE WITH YOUR CODE
def remove_vm_from_vpg(client, vpg_name, vm):
"""
Remove a VM from the VPG.
Args:
client: ZVMLClient instance
vpg_name: Name of the VPG
vm: VM object to remove
TODO: Implement the function to:
1. Get VM identifier
2. Call the appropriate API to remove the VM
3. Log the operation
1. Get VM name from vm object
2. Call client.vpgs.remove_vm_from_vpg() to remove the VM
HINT: Use this syntax:
vm_name = vm.get('VmName')
client.vpgs.remove_vm_from_vpg(vpg_name=vpg_name, vm_name=vm_name)
"""
pass
pass # ← REPLACE WITH YOUR CODE
def main():
"""
Main function to demonstrate VPG creation.
TODO: Implement the following steps:
1. Parse command line arguments
2. Create ZVMLClient instance
3. Identify local and peer sites
4. Get peer site resources (datastores, folders, networks, hosts)
5. Create VPG configuration
6. Create VPG
7. Find and add VMs to VPG
8. Implement interactive VM removal
Main function - this is where your code goes!
Follow the step-by-step instructions below.
"""
# Set up logging
# Set up logging so you can see what's happening
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s'
)
print("🚀 Starting Zerto VPG Operations Exercise")
print("=" * 50)
try:
# TODO: Step 1: Parse command line arguments
# ========================================
# STEP 1: Parse command line arguments
# ========================================
print("\n📝 STEP 1: Parsing command line arguments...")
print("You need to call the parse_arguments() function you created above.")
# TODO: Add code to parse arguments
# HINT: Use this syntax:
# args = parse_arguments()
#
# EXPLANATION:
# This gets the VM names and VPG name from command line
# TODO: Step 2: Create ZVMLClient instance
# client = ZVMLClient(...)
# ← ADD YOUR CODE HERE
# TODO: Step 3: Identify local and peer sites
# local_site = client.localsite.get_local_site()
# ========================================
# STEP 2: Create ZVMLClient instance
# ========================================
print("\n📝 STEP 2: Creating ZVMLClient...")
print("This is the same as previous exercises.")
# TODO: Add code to create ZVMLClient
# HINT: Use this syntax:
# client = ZVMLClient(
# zvm_address=ZVM_HOST,
# client_id=CLIENT_ID,
# client_secret=CLIENT_SECRET,
# verify_certificate=ZVM_SSL_VERIFY
# )
# ← ADD YOUR CODE HERE
# ========================================
# STEP 3: Identify local and peer sites
# ========================================
print("\n📝 STEP 3: Getting site information...")
print("You need to get local and peer site identifiers.")
# TODO: Add code to get sites and site identifiers
# HINT: Use this syntax:
# sites = client.virtualization_sites.get_virtualization_sites()
# local_site = client.localsite.get_local_site()
# local_site_identifier = local_site.get('SiteIdentifier')
# peer_site = next((site for site in sites if site.get('SiteIdentifier') != local_site_identifier), None)
# peer_site_identifier = peer_site.get('SiteIdentifier')
# TODO: Step 4: Get peer site resources
# peer_datastores = client.virtualization_sites.get_virtualization_site_datastores(...)
# peer_folders = client.virtualization_sites.get_virtualization_site_folders(...)
# peer_networks = client.virtualization_sites.get_virtualization_site_networks(...)
# peer_hosts = client.virtualization_sites.get_virtualization_site_hosts(...)
# ← ADD YOUR CODE HERE
# TODO: Step 5: Create VPG configuration
# ========================================
# STEP 4: Get peer site resources
# ========================================
print("\n📝 STEP 4: Getting peer site resources...")
print("You need to get datastores, folders, networks, and hosts from the peer site.")
# TODO: Add code to get peer site resources
# HINT: Use this syntax:
# peer_datastores = client.virtualization_sites.get_virtualization_site_datastores(site_identifier=peer_site_identifier)
# target_datastore = peer_datastores[0] # Use first available
#
# peer_folders = client.virtualization_sites.get_virtualization_site_folders(site_identifier=peer_site_identifier)
# target_folder = peer_folders[0] # Use first available
#
# peer_networks = client.virtualization_sites.get_virtualization_site_networks(site_identifier=peer_site_identifier)
# target_network = peer_networks[0] # Use first available
#
# peer_hosts = client.virtualization_sites.get_virtualization_site_hosts(site_identifier=peer_site_identifier)
# target_host = peer_hosts[0] # Use first available
# ← ADD YOUR CODE HERE
# ========================================
# STEP 5: Create VPG configuration
# ========================================
print("\n📝 STEP 5: Creating VPG configuration...")
print("You need to create the basic, journal, recovery, and network settings.")
# TODO: Add code to create VPG configuration
# HINT: Use this syntax:
# basic = {
# "Name": "Your VPG Name",
# "Name": args.vpg_name,
# "VpgType": "Remote",
# "RpoInSeconds": 300,
# "JournalHistoryInHours": 24,
@@ -150,21 +232,98 @@ def main():
# "ProtectedSiteIdentifier": local_site_identifier,
# "RecoverySiteIdentifier": peer_site_identifier
# }
#
# journal = {} # Keep default settings
#
# recovery = {
# "DefaultHostIdentifier": target_host.get('HostIdentifier'),
# "DefaultDatastoreIdentifier": target_datastore.get('DatastoreIdentifier'),
# "DefaultFolderIdentifier": target_folder.get('FolderIdentifier')
# }
#
# networks = {
# "Failover": {
# "Hypervisor": {
# "DefaultNetworkIdentifier": target_network.get('NetworkIdentifier')
# }
# },
# "FailoverTest": {
# "Hypervisor": {
# "DefaultNetworkIdentifier": target_network.get('NetworkIdentifier')
# }
# }
# }
# TODO: Step 6: Create VPG
# vpg_id = client.vpgs.create_vpg(...)
# ← ADD YOUR CODE HERE
# TODO: Step 7: Find and add VMs to VPG
# found_vms, not_found = find_vms_by_names(...)
# ========================================
# STEP 6: Create VPG
# ========================================
print("\n📝 STEP 6: Creating the VPG...")
print("You need to call the create_vpg method with your configuration.")
# TODO: Add code to create VPG
# HINT: Use this syntax:
# vpg_id = client.vpgs.create_vpg(basic=basic, journal=journal, recovery=recovery, networks=networks, sync=True)
#
# EXPLANATION:
# This creates the VPG with all your settings
# ← ADD YOUR CODE HERE
# ========================================
# STEP 7: Find and add VMs to VPG
# ========================================
print("\n📝 STEP 7: Finding and adding VMs...")
print("You need to find the VMs and add them to the VPG.")
# TODO: Add code to find VMs
# HINT: Use this syntax:
# found_vms, not_found = find_vms_by_names(client, local_site_identifier, args.vm_names)
#
# EXPLANATION:
# This finds the VMs you specified in the command line
# ← ADD YOUR CODE HERE
# TODO: Add code to add VMs to VPG
# HINT: Use this syntax:
# for vm in found_vms:
# # Add VM to VPG
# vm_name = vm.get('VmName')
# vm_id = vm.get('VmIdentifier')
# vm_payload = {
# "VmIdentifier": vm_id,
# "Recovery": {
# "HostIdentifier": target_host.get('HostIdentifier'),
# "DatastoreIdentifier": target_datastore.get('DatastoreIdentifier'),
# "FolderIdentifier": target_folder.get('FolderIdentifier')
# }
# }
# task_id = client.vpgs.add_vm_to_vpg(args.vpg_name, vm_list_payload=vm_payload)
# TODO: Step 8: Implement interactive VM removal
# ← ADD YOUR CODE HERE
# ========================================
# STEP 8: Interactive VM removal (optional)
# ========================================
print("\n📝 STEP 8: Interactive VM removal...")
print("You can optionally remove the last VM from the VPG.")
# TODO: Add code for interactive VM removal
# HINT: Use this syntax:
# if found_vms:
# # Ask user if they want to remove the last VM
# # If yes, remove it
# last_vm = found_vms[-1]
# vm_name = last_vm.get('VmName')
# response = input(f"Remove VM {vm_name} from VPG? (yes/no): ").lower()
# if response in ['yes', 'y']:
# remove_vm_from_vpg(client, args.vpg_name, last_vm)
# ← ADD YOUR CODE HERE
except Exception as e:
# This catches any errors that might occur
print(f"\n❌ ERROR: Something went wrong!")
print(f"Error details: {str(e)}")
logging.error(f"VPG operation failed: {str(e)}")
sys.exit(1)
+182 -113
View File
@@ -1,28 +1,37 @@
#!/usr/bin/env python3
"""
Exercise 6: Failover Testing - Template
Exercise 6: Failover Testing - Beginner-Friendly Instructions
This script demonstrates how to perform a failover test on a VPG.
Prerequisites:
1. Install the zvml package in development mode:
cd /path/to/zvml-python-sdk
pip install -e .
2. Update prerequisites/config.py with your ZVM details
PREREQUISITES (Complete these first):
1. ✅ Completed Exercise 5 (VPG Operations)
2. ✅ Make sure you have the zvml package installed
3. ✅ Updated prerequisites/config.py with your ZVM details
4. ✅ Have a VPG created and running (from Exercise 5)
Usage:
python failover.py --vpg-name "My-VPG"
WHAT YOU NEED TO DO:
In this exercise, you will:
1. Create a ZVMLClient to connect to your ZVM
2. Parse command line arguments (VPG name)
3. Find a VPG by its name
4. Start a failover test on the VPG
5. Monitor the test progress
6. Optionally stop the test
Your task:
1. Implement VPG lookup by name using get_vpgs()
2. Start a failover test using failover_test() method
3. Monitor test progress using get_vpg_test_status()
4. Stop the test using stop_vpg_test() method when requested
STEP-BY-STEP INSTRUCTIONS:
1. Look at the TODO comments below - they tell you exactly what to do
2. Replace the placeholder code with the actual code
3. Each step has hints and examples to help you
4. If you get stuck, check the solution file in the solution/ directory
The script should:
- Find the VPG by name and verify it exists
- Start a failover test with default settings
- Monitor the test progress and status
- Allow stopping the test when requested
WHAT IS A FAILOVER TEST?
- **Failover Test**: Tests if your VMs can be successfully started at the recovery site
- It creates test VMs at the peer site to verify everything works
- The test VMs are isolated and don't affect production
- You can stop the test at any time to clean up the test VMs
USAGE EXAMPLE:
python failover.py --vpg-name "My-VPG"
"""
import sys
@@ -37,159 +46,219 @@ import urllib3
# Suppress SSL warnings
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
# Add prerequisites to Python path
# Add prerequisites to Python path (this helps Python find your config file)
prerequisites_path = Path(__file__).parent.parent.parent.parent / "prerequisites"
sys.path.append(str(prerequisites_path))
# Import the SDK modules
# Import the Zerto SDK - this gives us the ZVMLClient class
from zvml import ZVMLClient
# Import configuration
# Import your configuration settings
try:
from config import (
ZVM_HOST,
ZVM_PORT,
ZVM_SSL_VERIFY,
CLIENT_ID,
CLIENT_SECRET
ZVM_HOST, # Your ZVM IP address (e.g., "192.168.1.100")
ZVM_PORT, # Usually 443 for HTTPS
ZVM_SSL_VERIFY, # True/False for SSL certificate verification
CLIENT_ID, # Your Keycloak client ID (e.g., "my-api-client")
CLIENT_SECRET # Your Keycloak client secret
)
except ImportError:
print("Error: Please copy config.example.py to config.py and update with your values")
print("❌ ERROR: Configuration file not found!")
print("Please copy config.example.py to config.py and update with your values")
print("Expected path:", prerequisites_path / "config.py")
sys.exit(1)
def parse_arguments():
"""Parse command line arguments."""
# TODO: Implement argument parsing
# Required argument:
# --vpg-name: Name of the VPG to test
pass
"""
Parse command line arguments.
TODO: Implement argument parsing
HINT: Use this syntax:
parser = argparse.ArgumentParser(description='Perform failover test on a VPG')
parser.add_argument('--vpg-name', required=True,
help='Name of the VPG to test')
return parser.parse_args()
EXPLANATION:
- argparse helps you get command line arguments
- --vpg-name: Name of the VPG to test (required)
"""
pass # ← REPLACE WITH YOUR CODE
def find_vpg_by_name(client, vpg_name):
"""
Find a VPG by its name using get_vpgs() method.
Find a VPG by its name.
Args:
client: ZVMLClient instance
vpg_name: Name of the VPG to find
TODO: Implement the function to find a VPG by name
HINT: Use this syntax:
vpg = client.vpgs.list_vpgs(vpg_name=vpg_name)
return vpg if vpg else None
Returns:
dict: VPG object if found, None otherwise
TODO: Implement the function to:
1. Call client.vpgs.get_vpgs() to get all VPGs
2. Find the VPG with matching name
3. Log the VPG details if found
4. Return the VPG object or None
EXPLANATION:
- client.vpgs.list_vpgs() gets VPGs with a specific name
- Returns the VPG if found, None if not found
"""
pass
pass # ← REPLACE WITH YOUR CODE
def start_failover_test(client, vpg_name):
"""
Start a failover test for the specified VPG using failover_test() method.
Start a failover test for the specified VPG.
Args:
client: ZVMLClient instance
vpg_name: Name of the VPG to test
TODO: Implement the function to start a failover test
HINT: Use this syntax:
response = client.vpgs.failover_test(
vpg_name=vpg_name,
sync=True # Wait for the test to start
)
return response
Returns:
str: Test identifier (task_id)
TODO: Implement the function to:
1. Call client.vpgs.failover_test() with sync=True
2. Log the test initiation
3. Return the task_id
EXPLANATION:
- client.vpgs.failover_test() starts a failover test
- sync=True means wait for the test to start before returning
- Returns the response from the API
"""
pass
pass # ← REPLACE WITH YOUR CODE
def monitor_test_progress(client, vpg_name, test_id):
"""
Monitor the progress of a failover test using get_vpg_test_status().
Monitor the progress of a failover test.
Args:
client: ZVMLClient instance
vpg_name: Name of the VPG
test_id: Test identifier (task_id)
TODO: Implement the function to monitor test progress
HINT: Use this syntax:
test_status = client.vpgs.get_vpg_test_status(vpg_name, test_id)
status = test_status.get('Status')
progress = test_status.get('Progress', 0)
Returns:
bool: True if test completed successfully, False otherwise
logging.info(f"Test status: {status} (Progress: {progress}%)")
TODO: Implement the function to:
1. Call client.vpgs.get_vpg_test_status() to get test status
2. Log the status and progress
3. Return True for 'Succeeded', False for 'Failed' or 'Stopped'
4. Return False if test is still running
if status == 'Succeeded':
return True
elif status in ['Failed', 'Stopped']:
return False
return False # Test is still running
EXPLANATION:
- client.vpgs.get_vpg_test_status() gets the current test status
- Returns True if test succeeded, False if failed/stopped/still running
"""
pass
pass # ← REPLACE WITH YOUR CODE
def stop_failover_test(client, vpg_name, test_id):
def stop_failover_test(client, vpg_name):
"""
Stop a running failover test using stop_vpg_test() method.
Stop a running failover test.
Args:
client: ZVMLClient instance
vpg_name: Name of the VPG
test_id: Test identifier (task_id)
TODO: Implement the function to stop a failover test
HINT: Use this syntax:
response = client.vpgs.stop_failover_test(vpg_name=vpg_name)
TODO: Implement the function to:
1. Call client.vpgs.stop_vpg_test() with sync=True
2. Wait for the stop operation to complete
3. Log the stop operation status
EXPLANATION:
- client.vpgs.stop_failover_test() stops the running test
- This cleans up the test VMs at the recovery site
"""
pass
pass # ← REPLACE WITH YOUR CODE
def main():
"""
Main function to demonstrate failover testing.
TODO: Implement the following steps:
1. Parse command line arguments for VPG name
2. Create ZVMLClient instance
3. Find the VPG by name using find_vpg_by_name()
4. Start failover test using start_failover_test()
5. Monitor test progress and handle stop request:
- Monitor progress using monitor_test_progress()
- If test completes successfully, exit
- If user requests to stop, call stop_failover_test()
Main function - this is where your code goes!
Follow the step-by-step instructions below.
"""
# Set up logging
# Set up logging so you can see what's happening
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s'
)
print("🚀 Starting Zerto Failover Testing Exercise")
print("=" * 50)
try:
# TODO: Step 1: Parse command line arguments
# ========================================
# STEP 1: Parse command line arguments
# ========================================
print("\n📝 STEP 1: Parsing command line arguments...")
print("You need to call the parse_arguments() function you created above.")
# TODO: Add code to parse arguments
# HINT: Use this syntax:
# args = parse_arguments()
#
# EXPLANATION:
# This gets the VPG name from command line
# TODO: Step 2: Create ZVMLClient instance
# client = ZVMLClient(...)
# ← ADD YOUR CODE HERE
# TODO: Step 3: Find the VPG
# ========================================
# STEP 2: Create ZVMLClient instance
# ========================================
print("\n📝 STEP 2: Creating ZVMLClient...")
print("This is the same as previous exercises.")
# TODO: Add code to create ZVMLClient
# HINT: Use this syntax:
# client = ZVMLClient(
# zvm_address=ZVM_HOST,
# client_id=CLIENT_ID,
# client_secret=CLIENT_SECRET,
# verify_certificate=ZVM_SSL_VERIFY
# )
# ← ADD YOUR CODE HERE
# ========================================
# STEP 3: Find the VPG
# ========================================
print("\n📝 STEP 3: Finding the VPG...")
print("You need to find the VPG by its name.")
# TODO: Add code to find VPG
# HINT: Use this syntax:
# vpg = find_vpg_by_name(client, args.vpg_name)
# if not vpg:
# logging.error(f"VPG '{args.vpg_name}' not found!")
# sys.exit(1)
# TODO: Step 4: Start failover test
# test_id = start_failover_test(client, args.vpg_name)
# TODO: Step 5: Monitor test progress and handle stop request
# while True:
# success = monitor_test_progress(client, args.vpg_name, test_id)
# if success:
# logging.info("Test completed successfully")
# break
#
# # Check if user wants to stop the test
# response = input("\nWould you like to stop the test? (yes/no): ").lower()
# if response in ['yes', 'y']:
# stop_failover_test(client, args.vpg_name, test_id)
# break
# EXPLANATION:
# This checks if the VPG exists before trying to test it
# ← ADD YOUR CODE HERE
# ========================================
# STEP 4: Start failover test
# ========================================
print("\n📝 STEP 4: Starting failover test...")
print("You need to start a failover test on the VPG.")
# TODO: Add code to start failover test
# HINT: Use this syntax:
# response = start_failover_test(client, args.vpg_name)
#
# time.sleep(10) # Wait before next status check
# EXPLANATION:
# This starts the failover test and waits for it to begin
# ← ADD YOUR CODE HERE
# ========================================
# STEP 5: Handle test stop request
# ========================================
print("\n📝 STEP 5: Handling test stop request...")
print("You can optionally stop the test.")
# TODO: Add code for interactive test stopping
# HINT: Use this syntax:
# response = input("\nWould you like to stop the test? (yes/no): ").lower()
# if response in ['yes', 'y']:
# stop_failover_test(client, args.vpg_name)
#
# EXPLANATION:
# This asks the user if they want to stop the test and cleans up if yes
# ← ADD YOUR CODE HERE
except Exception as e:
# This catches any errors that might occur
print(f"\n❌ ERROR: Something went wrong!")
print(f"Error details: {str(e)}")
logging.error(f"Failover test failed: {str(e)}")
sys.exit(1)