Running into some challenges with deploying an OVA. Been beating my head against the wall for a couple days and need to call in some help.
The goal is to deploy an OVA to a vcenter. Keep in mind this is a lab environment so there are self signed certs. Ideally i would like to create a flag that i can toggle depending on the environment its run in.
The script runs and connects - however when it goes to upload it looks like it wants to upload however it just times out and cancels itself.
The error that my script outputs is the following:
Traceback (most recent call last):
File "/workspaces/nestedlabs/test_combine.py", line 105, in <module>
deploy_ova(si, ova_url, cluster_name, datastore_name, vm_name, vm_config)
File "/workspaces/nestedlabs/test_combine.py", line 71, in deploy_ova
session.put(url, data=file, timeout=7)
File "/home/vscode/.local/lib/python3.10/site-packages/requests/sessions.py", line 649, in put
return self.request("PUT", url, data=data, **kwargs)
File "/home/vscode/.local/lib/python3.10/site-packages/requests/sessions.py", line 589, in request
resp = self.send(prep, **send_kwargs)
File "/home/vscode/.local/lib/python3.10/site-packages/requests/sessions.py", line 703, in send
r = adapter.send(request, **kwargs)
File "/home/vscode/.local/lib/python3.10/site-packages/requests/adapters.py", line 517, in send
raise SSLError(e, request=request)
requests.exceptions.SSLError: HTTPSConnectionPool(host='10.10.100.10', port=443): Max retries exceeded with url: /nfc/520bbbb4-6b20-d263-041d-6492c679159a/disk-0.vmdk (Caused by SSLError(SSLEOFError(8, 'EOF occurred in violation of protocol (_ssl.c:2396)')))
The script i have so far is the following. The ips and passwords have been changed - they are bogus for this post.
from pyVmomi import vim
from pyVim.connect import SmartConnect, Disconnect
import ssl
import requests
import tempfile
import shutil
import tarfile
import os
import time
class WebHandle(object):
def __init__(self, url):
self.url = url
r = requests.get(url, stream=True, verify=False)
if r.status_code != 200:
raise FileNotFoundError(url)
self.file_handle = tempfile.NamedTemporaryFile(suffix='.ova', delete=False)
shutil.copyfileobj(r.raw, self.file_handle)
self.file_handle.flush()
self.file_handle.seek(0)
def __enter__(self):
return self.file_handle
def __exit__(self, exc_type, exc_value, traceback):
self.file_handle.close()
os.unlink(self.file_handle.name)
def deploy_ova(si, ova_url, cluster_name, datastore_name, vm_name, vm_config):
with WebHandle(ova_url) as ova_file:
tar = tarfile.open(fileobj=ova_file)
ovf_file = [f for f in tar.getnames() if f.endswith('.ovf')][0]
ovf_descriptor = tar.extractfile(ovf_file).read().decode()
content = si.RetrieveContent()
cluster = next((c for c in content.rootFolder.childEntity[0].hostFolder.childEntity if c.name == cluster_name), None)
resource_pool = cluster.resourcePool if cluster else content.rootFolder.childEntity[0].host[0].parent.resourcePool
datastore = next((ds for ds in (cluster.datastore if cluster else content.rootFolder.childEntity[0].host[0].datastore) if ds.name == datastore_name), None)
vm_folder = content.rootFolder.childEntity[0].vmFolder
# Create the customization properties
property_mappings = [
vim.KeyValue(key='guestinfo.hostname', value=vm_config['hostname']),
vim.KeyValue(key='guestinfo.ipaddress', value=vm_config['ipaddress']),
vim.KeyValue(key='guestinfo.netmask', value=vm_config['netmask']),
vim.KeyValue(key='guestinfo.gateway', value=vm_config['gateway']),
vim.KeyValue(key='guestinfo.dns', value=vm_config['dns']),
vim.KeyValue(key='guestinfo.ntp', value=vm_config['ntp']),
# vim.KeyValue(key='guestinfo.ssh', value='true'),
vim.KeyValue(key='guestinfo.password', value=vm_config['password']),
# Add other properties here...
]
spec_params = vim.OvfManager.CreateImportSpecParams(entityName=vm_name, propertyMapping=property_mappings)
manager = content.ovfManager
import_spec = manager.CreateImportSpec(ovf_descriptor, resource_pool, datastore, spec_params)
lease = resource_pool.ImportVApp(import_spec.importSpec, vm_folder)
while lease.state == vim.HttpNfcLease.State.initializing:
time.sleep(1)
if lease.state == vim.HttpNfcLease.State.error:
print("Lease error: ", lease.error)
return
session = requests.Session()
session.verify = False
for device_url in lease.info.deviceUrl:
file_path = next((f for f in import_spec.fileItem if f.deviceId == device_url.importKey), None).path
file = tar.extractfile(file_path)
url = device_url.url.replace('*', '10.10.100.12') # Replace with the correct IP
session.put(url, data=file, timeout=7)
lease.HttpNfcLeaseComplete()
vm = lease.info.entity
task = vm.PowerOn()
while task.info.state == vim.TaskInfo.State.running:
time.sleep(1)
print(f"Deployed {vm_name} successfully!")
# Connect to the vCenter server
ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
ssl_context.check_hostname = False
ssl_context.verify_mode = ssl.CERT_NONE
si = SmartConnect(host="10.10.100.12", user="administrator@vsphere.local", pwd="Password1234", sslContext=ssl_context)
# Deploy the OVA
ova_url = 'https://10.10.100.147/public-archives/download/Test/Nested_ESXi6.5u3_Appliance_Template_v1.ova'
cluster_name = 'Test1'
datastore_name = 'datastore1'
vm_name = 'YourVM'
vm_config = {
'hostname': 'your-hostname',
'ipaddress': '10.100.100.240',
'netmask': '255.255.255.0',
'gateway': '10.100.100.1',
'dns': '10.100.100.111',
'ntp': '4.2.2.2',
# 'ssh': 'True',
'syslog': '10.100.100.111',
'password': 'WhatAPassWord!!',
# Add other properties here...
}
deploy_ova(si, ova_url, cluster_name, datastore_name, vm_name, vm_config)
# Disconnect from the vCenter server
Disconnect(si)