-
Notifications
You must be signed in to change notification settings - Fork 0
/
fsdrs.py
179 lines (149 loc) · 7.26 KB
/
fsdrs.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
import ssl
import time
import yaml
from pyVim.connect import SmartConnect, Disconnect
from pyVmomi import vim
class vCenterConnector:
def __init__(self, config_file):
self.config_file = config_file
self.service_instance = None
def connect(self):
with open(self.config_file, 'r') as f:
config = yaml.safe_load(f)
host = config['host']
username = config['username']
password = config['password']
context = None
if hasattr(ssl, "_create_unverified_context"):
context = ssl._create_unverified_context()
try:
self.service_instance = SmartConnect(host=host,
user=username,
pwd=password,
sslContext=context)
return True
except Exception as e:
print("Unable to connect to vCenter:", str(e))
return False
def disconnect(self):
try:
if self.service_instance:
Disconnect(self.service_instance)
print("Disconnected from vCenter")
except Exception as e:
print("Error disconnecting from vCenter:", str(e))
def get_vm_metrics(vcenter):
vm_metrics = {}
try:
content = vcenter.RetrieveContent()
container_view = content.viewManager.CreateContainerView(content.rootFolder,
[vim.VirtualMachine],
True)
vms = container_view.view
for vm in vms:
if vm.runtime.powerState == vim.VirtualMachinePowerState.poweredOn:
summary = vm.summary
cpu_usage = summary.quickStats.overallCpuUsage
memory_usage = summary.quickStats.guestMemoryUsage
vm_metrics[vm.name] = (cpu_usage, memory_usage)
return vm_metrics
except Exception as e:
print(f"Error retrieving VM metrics: {str(e)}")
return None
def get_host_metrics(vcenter):
host_metrics = {}
try:
content = vcenter.RetrieveContent()
container_view = content.viewManager.CreateContainerView(content.rootFolder,
[vim.HostSystem],
True)
hosts = container_view.view
for host in hosts:
summary = host.summary
cpu_utilization = summary.quickStats.overallCpuUsage
cpu_capacity = host.hardware.cpuInfo.hz / 1000000 # Convert Hz to MHz
memory_utilization = summary.quickStats.overallMemoryUsage
memory_capacity = host.hardware.memorySize / (1024 * 1024) # Convert bytes to megabytes
host_metrics[host.name] = (cpu_capacity, memory_capacity)
return host_metrics
except Exception as e:
print(f"Error retrieving host metrics: {str(e)}")
return None
def migrate_vm_to_host(vm_name, host_name, service_instance):
try:
content = service_instance.RetrieveContent()
vm_obj = None
host_obj = None
# Find the VM object by name
container = content.viewManager.CreateContainerView(content.rootFolder, [vim.VirtualMachine], True)
for item in container.view:
if item.name == vm_name:
vm_obj = item
break
# Find the host object by name
host_container = content.viewManager.CreateContainerView(content.rootFolder, [vim.HostSystem], True)
for item in host_container.view:
if item.name == host_name:
host_obj = item
break
# Perform VM migration
if vm_obj and host_obj:
task = vm_obj.Migrate(host=host_obj, priority=vim.VirtualMachine.MovePriority.highPriority)
task_result = task.waitForTask()
if task_result == vim.TaskInfo.State.success:
print(f"Successfully migrated VM {vm_name} to host {host_name}")
else:
print(f"Failed to migrate VM {vm_name} to host {host_name}. Task result: {task_result}")
else:
print(f"Failed to find VM {vm_name} or host {host_name}")
except Exception as e:
print(f"Error migrating VM {vm_name} to host {host_name}: {str(e)}")
def main():
vcenter_config_file = "vcenter01_config.yaml"
vcenter_connector = vCenterConnector(vcenter_config_file)
if vcenter_connector.connect():
try:
# Get initial host metrics
host_metrics = get_host_metrics(vcenter_connector.service_instance)
if not host_metrics:
print("Failed to retrieve host metrics. Exiting.")
return
# Perform what-if analysis and migrate VMs one by one with a 1-minute interval
vm_metrics = get_vm_metrics(vcenter_connector.service_instance)
if not vm_metrics:
print("Failed to retrieve VM metrics. Exiting.")
return
while vm_metrics:
# Initialize variables for tracking best host
best_host = None
lowest_host_utilization = float('inf') # Initialize to positive infinity
# Iterate over VMs to find the next VM to migrate
for vm, (vm_cpu_usage, vm_memory_usage) in vm_metrics.items():
print(f"\nWhat-if analysis for VM: {vm}")
# Calculate the best host for the current VM
for host, (cpu_capacity, memory_capacity) in host_metrics.items():
new_host_cpu_utilization = cpu_capacity + vm_cpu_usage
new_host_memory_utilization = memory_capacity + vm_memory_usage
host_utilization = max(new_host_cpu_utilization / cpu_capacity, new_host_memory_utilization / memory_capacity)
if host_utilization < lowest_host_utilization and host != vm_metrics[vm]: # Skip if the VM is already on the best host
best_host = host
lowest_host_utilization = host_utilization
if best_host:
# Migrate VM to the best host
migrate_vm_to_host(vm, best_host, vcenter_connector.service_instance)
print(f"Migrated VM {vm} to host {best_host}. Waiting 1 minute before recalculating host balance.")
time.sleep(60) # Wait for 1 minute before recalculating host balance
# Remove the migrated VM from the metrics
del vm_metrics[vm]
# Update host metrics after migration
host_metrics = get_host_metrics(vcenter_connector.service_instance)
if not host_metrics:
print("Failed to retrieve host metrics after migration. Exiting.")
return
break # Move to the next VM after migration
else:
print(f"No suitable host found for VM {vm}")
finally:
vcenter_connector.disconnect()
if __name__ == "__main__":
main()