robotframework-demo/Project/task4/Script/SC0_Common/00_Initial/Vsphere.py

412 lines
12 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/python3
# encoding:utf-8
"""
created by jd 2018-03-05
"""
import io
import os
import sys
import atexit
#import requests
import ssl
from pyVmomi import vim
from pyVmomi import vmodl
from pyVim import connect
from pyVim.connect import SmartConnect
from pyVim.task import WaitForTask
from pysphere import VIServer
import importlib
server = VIServer()
ssl._create_default_https_context = ssl._create_unverified_context
def get_physical_cdrom(host):
for lun in host.configManager.storageSystem.storageDeviceInfo.scsiLun:
if lun.lunType == 'cdrom':
return lun
return None
def find_free_ide_controller(vm):
for dev in vm.config.hardware.device:
if isinstance(dev, vim.vm.device.VirtualIDEController):
# If there are less than 2 devices attached, we can use it.
if len(dev.device) < 2:
return dev
return None
def find_device(vm, device_type):
result = []
for dev in vm.config.hardware.device:
if isinstance(dev, device_type):
result.append(dev)
return result
def new_cdrom_spec(controller_key, backing):
connectable = vim.vm.device.VirtualDevice.ConnectInfo()
connectable.allowGuestControl = True
connectable.startConnected = True
cdrom = vim.vm.device.VirtualCdrom()
cdrom.controllerKey = controller_key
cdrom.key = -1
cdrom.connectable = connectable
cdrom.backing = backing
return cdrom
def upload_file_to_datastore(self_host,self_user,self_pwd,self_datastore,self_remote_file,self_local_file):
"""从本地上传文件到datastore指定目录
:param self_host:ESXI IP地址
:param self_user:用户名
:param self_pwd:用户密码
:param self_datastore:ESXI datastore名称
:param self_remote_file:远程文件名称
:param self_local_file:本地文件名称
:return:None
| upload_file_to_datastore | self_host | self_user | self_pwd | self_datastore | self_remote_file | self_local_file |
"""
try:
service_instance = None
sslContext = None
verify_cert = None
sslContext = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
sslContext.verify_mode = ssl.CERT_NONE
verify_cert = False
# disable urllib3 warnings
if hasattr(requests.packages.urllib3, 'disable_warnings'):
requests.packages.urllib3.disable_warnings()
try:
service_instance = connect.SmartConnect(host=self_host,
user=self_user,
pwd=self_pwd,
port=443,
sslContext=sslContext)
except IOError as e:
pass
if not service_instance:
print("Could not connect to the specified host using specified "
"username and password")
raise SystemExit(-1)
# Ensure that we cleanly disconnect in case our code dies
atexit.register(connect.Disconnect, service_instance)
content = service_instance.RetrieveContent()
session_manager = content.sessionManager
# Get the list of all datacenters we have available to us
datacenters_object_view = content.viewManager.CreateContainerView(
content.rootFolder,
[vim.Datacenter],
True)
# Find the datastore and datacenter we are using
datacenter = None
datastore = None
for dc in datacenters_object_view.view:
datastores_object_view = content.viewManager.CreateContainerView(
dc,
[vim.Datastore],
True)
for ds in datastores_object_view.view:
if ds.info.name == self_datastore:
datacenter = dc
datastore = ds
if not datacenter or not datastore:
print("Could not find the datastore specified")
raise SystemExit(-1)
# Clean up the views now that we have what we need
datastores_object_view.Destroy()
datacenters_object_view.Destroy()
# Build the url to put the file - https://hostname:port/resource?params
if not self_remote_file.startswith("/"):
remote_file = "/" + self_remote_file
else:
remote_file = self_remote_file
resource = "/folder" + remote_file
params = {"dsName": datastore.info.name,
"dcPath": datacenter.name}
http_url = "https://" + self_host + ":443" + resource
# Get the cookie built from the current session
client_cookie = service_instance._stub.cookie
# Break apart the cookie into it's component parts - This is more than
# is needed, but a good example of how to break apart the cookie
# anyways. The verbosity makes it clear what is happening.
cookie_name = client_cookie.split("=", 1)[0]
cookie_value = client_cookie.split("=", 1)[1].split(";", 1)[0]
cookie_path = client_cookie.split("=", 1)[1].split(";", 1)[1].split(
";", 1)[0].lstrip()
cookie_text = " " + cookie_value + "; $" + cookie_path
# Make a cookie
cookie = dict()
cookie[cookie_name] = cookie_text
# Get the request headers set up
headers = {'Content-Type': 'application/octet-stream'}
# Get the file to upload ready, extra protection by using with against
# leaving open threads
with open(self_local_file, "rb") as f:
# Connect and upload the file
request = requests.put(http_url,
params=params,
data=f,
headers=headers,
cookies=cookie,
verify=verify_cert)
except vmodl.MethodFault as e:
print(("Caught vmodl fault : " + e.msg))
raise SystemExit(-1)
def sphere_login(host, user, password):
"""通过用户名密码登录指定的ESXi
:param host:ESXi的host ip
:param user:ESXi的用户名
:param password:ESXi的密码
:return:None
| sphere login | host | user | password |
"""
server.connect(host, user, password, trace_file="debug.txt")
if(server.is_connected()):
print('exsi is connected.')
return True
else:
print('error:exsi server can not connected')
return False
pass
def vm_poweron(path):
"""通过虚拟机路径打开对应虚拟机
:param path:虚拟机配置文件所在路径
:return:None
| vm poweron | path |
"""
vm = server.get_vm_by_path(path)
if vm.get_status() == 'POWERED OFF':
task = vm.power_on(sync_run=False)
task.wait_for_state(['error', 'success'], timeout=60)
if task.get_state() == 'error':
print(task.get_error_message())
pass
def vm_poweron_name(name):
"""通过虚拟机名称打开对应虚拟机
:参数为虚拟机名称
:return:None
| vm poweron | name |
"""
vm = server.get_vm_by_name(name)
if vm.get_status() == 'POWERED OFF':
task = vm.power_on(sync_run=False)
task.wait_for_state(['error', 'success'], timeout=60)
if task.get_state() == 'error':
print(task.get_error_message())
pass
def vm_poweroff(path):
"""通过虚拟机路径关闭对应虚拟机
:param path:虚拟机配置文件所在路径
:return:None
| vm poweroff | path |
"""
vm = server.get_vm_by_path(path)
if vm.get_status() != 'POWERED OFF':
task = vm.power_off(sync_run=False)
task.wait_for_state(['error', 'success'], timeout=60)
if task.get_state() == 'error':
print(task.get_error_message())
pass
def vm_poweroff_name(name):
"""通过虚拟机名称关闭对应虚拟机
:参数为虚拟机名称
:return:None
| vm poweroff | name |
"""
vm = server.get_vm_by_name(name)
if vm.get_status() != 'POWERED OFF':
task = vm.power_off(sync_run=False)
task.wait_for_state(['error', 'success'], timeout=60)
if task.get_state() == 'error':
print(task.get_error_message())
pass
def vm_shutdown_name(name):
"""通过虚拟机名称注销用户并关闭对应虚拟机
:参数为虚拟机名称
:return:None
| vm poweroff | name |
"""
vm = server.get_vm_by_name(name)
if vm.get_status() != 'POWERED OFF':
vm.shutdown_guest()
pass
else:
print('VM has been poweroff.')
def vm_revert_snapshot(path, snapshot_name):
"""通过快照名恢复虚拟机路径指定的虚拟机
:param path:虚拟机配置文件所在路径
:param snapshot_name:快照名
:return:None
| vm revert snapshot | path | snapshot_name |
"""
vm = server.get_vm_by_path(path)
snapshot_list = vm.get_snapshots()
for snapshot in snapshot_list:
print(snapshot.get_name())
print(snapshot.get_description())
if snapshot_name in snapshot.get_name():
task = vm.revert_to_named_snapshot(snapshot.get_name(), sync_run=False)
print('revert snapshot %s' % snapshot.get_name())
task.wait_for_state(['error', 'success'], timeout=60)
if task.get_state() == 'error':
print(task.get_error_message())
break
pass
def download_file(name, guest_name, guest_password, filepath, dirpath):
#从虚拟机上拷贝文件到本机指定位置下(虚拟机必须安装vmtools)
#name:虚拟机名字
#guest_name:虚拟机用户名
#guest_password:用户密码
#filepath:虚拟机上文件路径
#dirpath:本机目标文件路径
#| vm poweroff | name | guest_name | guest_password | filepath | dirpath |
#return:none,失败弹出原因
vm = server.get_vm_by_name(name)
vm.login_in_guest(guest_name, guest_password)
if vm.get_status() == 'POWERED ON':
vm.get_file(filepath, dirpath, True)
def sphere_logoff():
"""登出指定的ESXi
:return:None
| sphere logoff |
"""
if server.is_connected():
server.disconnect()
pass
def upload_file(system_type, name, guest_name, guest_password, filepath, dirpath):
"""从虚拟机指定位置下运行程序(虚拟机必须安装vmtools)
:param system_type:操作系统类型
:param name:虚拟机名字
:param guest_name:虚拟机用户名
:param guest_password:用户密码
:param filepath:虚拟机上文件路径
:param dirpath:本机目标文件路径
:return:None
| upload file | system_type | name | guest_name | guest_password | filepath | dirpath |
"""
if system_type == "windows":
importlib.reload(sys)
sys.setdefaultencoding('gbk')
vm = server.get_vm_by_name(name)
vm.login_in_guest(guest_name, guest_password)
if vm.get_status() == 'POWERED ON':
vm.send_file(filepath, dirpath, True)
def run_process(name, guest_name, guest_password, program_path, program_args, program_cwd):
"""从虚拟机指定位置下运行程序(虚拟机必须安装vmtools)
:param name:虚拟机名字
:param guest_name:虚拟机用户名
:param guest_password:用户密码
:param program_path:程序的绝对地址
:param program_args:程序的参数列表
:param program_cwd:程序的工作目录
:return:None
| run process | name | guest_name | guest_password | program_path | program_args | program_cwd |
"""
vm = server.get_vm_by_name(name)
vm.login_in_guest(guest_name, guest_password)
if vm.get_status() == 'POWERED ON':
vm.start_process(program_path,args=[program_args],env="",cwd=program_cwd)
def rm_cdrom(host, user, password, name):
"""卸载指定虚拟机ISO
:param host:EXSI IP
:param user:EXSI用户名
:param password:EXSI密码
:param name:虚拟机名字
:return:None
| rm cdrom | host | user | password | name |
"""
sslContext = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
sslContext.verify_mode = ssl.CERT_NONE
verify_cert = False
# disable urllib3 warnings
if hasattr(requests.packages.urllib3, 'disable_warnings'):
requests.packages.urllib3.disable_warnings()
try:
si = connect.SmartConnect(host=host, user=user,pwd=password,port=443,sslContext=sslContext)
except IOError as e:
pass
#si = SmartConnect(host=args.host, user=args.user, pwd=args.password)
dc = si.content.rootFolder.childEntity[0]
vm = si.content.searchIndex.FindChild(dc.vmFolder, name)
if vm is None:
raise Exception('Failed to find VM %s in datacenter %s' %
(dc.name, name))
controller = find_free_ide_controller(vm)
if controller is None:
raise Exception('Failed to find a free slot on the IDE controller')
cdrom = None
cdrom_lun = get_physical_cdrom(vm.runtime.host)
if cdrom_lun is not None:
backing = vim.vm.device.VirtualCdrom.AtapiBackingInfo()
backing.deviceName = cdrom_lun.deviceName
deviceSpec = vim.vm.device.VirtualDeviceSpec()
deviceSpec.device = new_cdrom_spec(controller.key, backing)
deviceSpec.operation = vim.vm.device.VirtualDeviceSpec.Operation.add
configSpec = vim.vm.ConfigSpec(deviceChange=[deviceSpec])
WaitForTask(vm.Reconfigure(configSpec))
cdroms = find_device(vm, vim.vm.device.VirtualCdrom)
cdrom = [x for x in cdroms if type(x.backing) == type(backing) and x.backing.deviceName == cdrom_lun.deviceName][0]
else:
cdroms = find_device(vm, vim.vm.device.VirtualCdrom)
if len(cdroms) != 0:
cdrom = cdroms[0]
print('Skipping physical CD-Rom test as no device present.')
op = vim.vm.device.VirtualDeviceSpec.Operation
if cdrom is not None: # Remove it
deviceSpec = vim.vm.device.VirtualDeviceSpec()
deviceSpec.device = cdrom
deviceSpec.operation = op.remove
configSpec = vim.vm.ConfigSpec(deviceChange=[deviceSpec])
WaitForTask(vm.Reconfigure(configSpec))