Vmware控制台: 为了方便管理vmware,尽量摆脱vSphere,目前实现了对虚拟机的增、删、改(硬件配置)、快照管理、Console控制台、克隆等功能,本文只详细的介绍下Console功能。先上一张效果图:
一、 环境准备
- pyvmomi对应你的python版本,下载地址https://github.com/vmware/pyvmomi/releases
- 保证python环境大于2.7.11
二、食用方法
代码如下:
# -*- coding: utf8 -*-
from pyVmomi import vim,vmodl
from pyVim.connect import SmartConnect, Disconnect
import atexit
import sys
import time
import ssl
class VCenter:
def __init__(self):
self.pyVmomi = __import__("pyVmomi")
self.vcenter_server = '1.1.1.1'
self.vcenter_username = 'test'
self.vcenter_password = 'test'
self.port = 443
self.isDHCP=False,
self.vm_ip='10.7.42.91',
self.subnet= '255.255.255.0',
self.gateway= '10.7.42.40',
self.dns= ['company.com', 'company.com'],
self.domain= 'esx10g.company.com'
def add_nic(vm, network):
spec = vim.vm.ConfigSpec()
# add Switch here
dev_changes = []
switch_spec = vim.vm.device.VirtualDeviceSpec()
switch_spec.operation = vim.vm.device.VirtualDeviceSpec.Operation.add
switch_spec.device = vim.vm.device.VirtualVmxnet3()
switch_spec.device.backing = vim.vm.device.VirtualEthernetCard.NetworkBackingInfo()
switch_spec.device.backing.useAutoDetect = False
switch_spec.device.backing.deviceName = network.name
switch_spec.device.backing.network = network
switch_spec.device.connectable = vim.vm.device.VirtualDevice.ConnectInfo()
switch_spec.device.connectable.startConnected = True
switch_spec.device.connectable.connected = True
dev_changes.append(switch_spec)
spec.deviceChange = dev_changes
output = vm.ReconfigVM_Task(spec=spec)
time.sleep(2)
print output.info
def connect_to_vcenter(self):
context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
context.verify_mode = ssl.CERT_NONE
self.service_instance = SmartConnect(
host = self.vcenter_server,
user = self.vcenter_username,
pwd = self.vcenter_password,
port = self.port,
sslContext = context)
self.content = self.service_instance.RetrieveContent()
atexit.register(Disconnect, self.service_instance)
def wait_for_task(self, task, actionName='job', hideResult=False):
while task.info.state == (self.pyVmomi.vim.TaskInfo.State.running or self.pyVmomi.vim.TaskInfo.State.queued):
time.sleep(2)
if task.info.state == self.pyVmomi.vim.TaskInfo.State.success:
if task.info.result is not None and not hideResult:
out = '%s completed successfully, result: %s' % (actionName, task.info.result)
print out
else:
out = '%s completed successfully.' % actionName
print out
elif task.info.state == self.pyVmomi.vim.TaskInfo.State.error:
out = 'Error - %s did not complete successfully: %s' % (actionName, task.info.error)
raise ValueError(out)
return task.info.result
def answer_vm_question(self,vm):
choices = vm.runtime.question.choice.choiceInfo
default_option = None
choice = ""
if vm.runtime.question.choice.defaultIndex is not None:
ii = vm.runtime.question.choice.defaultIndex
default_option = choices[ii]
choice = None
while choice not in [o.key for o in choices]:
print "VM power on is paused by this question:\n\n"
for option in choices:
print "\t %s: %s " % (option.key, option.label)
if default_option is not None:
print "default (%s): %s\n" % (default_option.label,
default_option.key)
choice = raw_input("\nchoice number: ").strip()
print "..."
return choice
def poweroff(self, si, vm):
task = vm.PowerOff()
actionName = 'job'
while task.info.state not in [self.pyVmomi.vim.TaskInfo.State.success or self.pyVmomi.vim.TaskInfo.State.error]:
time.sleep(2)
if task.info.state == self.pyVmomi.vim.TaskInfo.State.success:
out = '%s completed successfully.' % actionName
print out
elif task.info.state == self.pyVmomi.vim.TaskInfo.State.error:
out = 'Error - %s did not complete successfully: %s' % (actionName, task.info.error)
raise ValueError(out)
return
def poweron(self, si, vm):
task = vm.PowerOn()
actionName = 'job'
answers = {}
while task.info.state not in [self.pyVmomi.vim.TaskInfo.State.success or self.pyVmomi.vim.TaskInfo.State.error]:
if vm.runtime.question is not None:
question_id = vm.runtime.question.id
if question_id not in answers.keys():
answers[question_id] = self.answer_vm_question(vm)
vm.AnswerVM(question_id, answers[question_id])
time.sleep(2)
if task.info.state == self.pyVmomi.vim.TaskInfo.State.success:
out = '%s completed successfully.' % actionName
print out
elif task.info.state == self.pyVmomi.vim.TaskInfo.State.error:
out = 'Error - %s did not complete successfully: %s' % (actionName, task.info.error)
raise ValueError(out)
return
def set_dvs_mtu(self, dvs, mtu):
dvs_config_spec = self.pyVmomi.vim.VmwareDistributedVirtualSwitch.ConfigSpec()
dvs_config_spec.configVersion = dvs.config.configVersion
dvs_config_spec.maxMtu = int(mtu)
task = dvs.ReconfigureDvs_Task(dvs_config_spec)
self.wait_for_task(task)
print "Successfully reconfigured DVS %s with mtu %s" %(dvs.name, mtu)
return dvs
def get_dvs_portgroup(self, vimtype, portgroup_name, dvs_name):
obj = None
container = self.content.viewManager.CreateContainerView(self.content.rootFolder, vimtype, True)
for c in container.view:
if c.name == portgroup_name:
if c.config.distributedVirtualSwitch.name == dvs_name:
obj = c
break
return obj
def list_obj(self, vimtype):
container = self.content.viewManager.CreateContainerView(self.content.rootFolder, vimtype, True)
return container.view
def get_obj(self, vimtype, name):
obj = None
container = self.content.viewManager.CreateContainerView(self.content.rootFolder, vimtype, True)
for c in container.view:
if c.name == name:
obj = c
break
return obj
def get_folder(self, folder_name=''):
"""获取文件夹"""
folder_list = []
if folder_name == '':
listOBJ = self.list_obj([vim.Folder])
else:
listOBJ = self.get_obj([vim.Folder],folder_name)
for each in listOBJ:
folder_list.append(each)
return folder_list
def get_vcenters(self):
"""获取所有数据中心"""
listOBJ = self.list_obj([vim.Datacenter])
vcenters_list = []
for each in listOBJ:
vcenters_list.append(each)
return each
def get_vcenters_alarm(self):
"""获取所有数据中心报警"""
listOBJ = self.list_obj([vim.Datacenter])
vcenters_alarm_dict = {}
for i in listOBJ[0].triggeredAlarmState:
vcenters_alarm_dict[i.entity.name] = i.alarm.info.name.decode()
return vcenters_alarm_dict
def get_datastore(self, datastore_name=''):
"""获取存储"""
datastore_list = []
if datastore_name == '':
listOBJ = self.list_obj([vim.Datastore])
else:
listOBJ = self.get_obj([vim.Datastore],datastore_name)
for each in listOBJ:
datastore_list.append(each.name)
return datastore_list
def get_clusters(self,clusters_name=''):
"""获取所有的集群"""
clusters_list = []
if clusters_name == '':
listOBJ = self.list_obj([vim.ClusterComputeResource])
else:
listOBJ = self.get_obj([vim.ClusterComputeResource],clusters_name)
for each in listOBJ:
clusters_list.append(each.name)
return clusters_list
def get_resource_pool(self,resource_pool_name=''):
"""获取所有的资源池"""
resource_pool_list = []
if resource_pool_name == '':
listOBJ = self.list_obj([vim.ResourcePool])
else:
listOBJ = self.get_obj([vim.ResourcePool],resource_pool_name)
for each in listOBJ:
resource_pool_list.append(each.name)
return resource_pool_list
def get_hosts(self):
"""获取所有的宿主机"""
listOBJ = self.list_obj([vim.HostSystem])
index = 0
for each in listOBJ:
tupleVNic=sys._getframe().f_code.co_name, index, each.config.network.vnic
for eachvnic in tupleVNic[2]:
index = index + 1
print sys._getframe().f_code.co_name, \
index, \
each, \
eachvnic.portgroup, \
eachvnic.spec.mac, \
eachvnic.spec.ip.ipAddress, eachvnic.spec.ip.subnetMask
def get_pnic(self):
"""获取所有的上行口"""
listOBJ = self.list_obj([vim.HostSystem])
index = 0
for each in listOBJ:
tuplePNic=sys._getframe().f_code.co_name, index, each.config.network.pnic
for eachpnic in tuplePNic[2]:
index = index + 1
print sys._getframe().f_code.co_name, index, each, eachpnic.device
def get_vswitchs(self):
"""获取所有的交换机(包括标准交换机和分布式交换机)"""
listOBJ = self.list_obj([vim.HostSystem])
index = 0
for each in listOBJ:
tupleVswitch = sys._getframe().f_code.co_name, index, each.config.network.vswitch
for eachsw in tupleVswitch[2]:
index = index + 1
print sys._getframe().f_code.co_name, index, eachsw.name
def get_portgroups(self):
"""获取所有的交换机端口组(包括标准交换机和分布式交换机)"""
listOBJ = self.list_obj([vim.Network])
index = 0
for each in listOBJ:
index = index + 1
print sys._getframe().f_code.co_name, index, each
def get_vns(self):
"""获取所有的虚拟网络(包括标准交换机端口组和分布式交换机端口组)"""
listOBJ = self.list_obj([vim.Network])
index = 0
for each in listOBJ:
index = index + 1
print sys._getframe().f_code.co_name, index, each
def get_dvswitchs(self):
"""获取所有的分布式交换机"""
listOBJ = self.list_obj([vim.DistributedVirtualSwitch])
index = 0
for each in listOBJ:
index = index + 1
print sys._getframe().f_code.co_name,index,each
def get_dvportgroups(self):
"""获取所有的分布式交换机端口组"""
listOBJ = self.list_obj([vim.DistributedVirtualSwitch])
index = 0
for each in listOBJ:
for eachportgroup in each.portgroup:
index = index + 1
print sys._getframe().f_code.co_name,index,eachportgroup
def get_vnic(self):
"""获取所有的虚拟网卡"""
listOBJ = self.list_obj([vim.VirtualMachine])
index = 0
for each in listOBJ:
index = index + 1
vmdeviceList = each.config.hardware.device
for eachdevice in vmdeviceList:
index = index + 1
if isinstance(eachdevice, vim.vm.device.VirtualEthernetCard ):
if isinstance( eachdevice.backing,vim.vm.device.VirtualEthernetCard.DistributedVirtualPortBackingInfo ):
print sys._getframe().f_code.co_name,\
index, \
eachdevice.deviceInfo.label, \
eachdevice.macAddress, \
eachdevice.deviceInfo.summary, \
eachdevice.backing.port.portgroupKey
else:
print sys._getframe().f_code.co_name,\
index, \
eachdevice.deviceInfo.label, \
eachdevice.macAddress, \
eachdevice.backing.deviceName, \
eachdevice.backing.network
def get_allvms(self):
"""获取所有的虚机"""
listOBJ = self.list_obj([vim.VirtualMachine])
index = 0
for each in listOBJ:
index = index + 1
print sys._getframe().f_code.co_name,index,each.name
def print_vm_info(self, virtual_machine, depth=1):
"""打印虚机信息"""
maxdepth = 10
if hasattr(virtual_machine, 'childEntity'):
if depth > maxdepth:
return
vmList = virtual_machine.childEntity
for c in vmList:
self.print_vm_info(c, depth + 1)
return
summary = virtual_machine.summary
print "Name : ", summary.config.name
print "Path : ", summary.config.vmPathName
print "Guest : ", summary.config.guestFullName
annotation = summary.config.annotation
if annotation:
print "Annotation : ", annotation
print "State : ", summary.runtime.powerState
if summary.guest is not None:
ip_address = summary.guest.ipAddress
if ip_address:
print "IP : ", ip_address
if summary.runtime.question is not None:
print "Question : ", summary.runtime.question.text
print ""
def get_acquireTicket(self,virtual_machine):
"""获取主机Console授权"""
acquireTickets_dict = {}
listOBJ = self.get_obj([vim.VirtualMachine],virtual_machine)
try:
acquireTickets = listOBJ.AcquireTicket('webmks')
except Exception as err:
print 'acquireTickets_err:',err
acquireTickets_dict['host'] = acquireTickets.host
acquireTickets_dict['port'] = acquireTickets.port
acquireTickets_dict['ticket'] = acquireTickets.ticket
print acquireTickets_dict
return acquireTickets_dict
def get_hosts_exsi_version(self,virtual_machine):
"""获得主机Esxi版本"""
try:
hosts_name = self.get_obj([vim.VirtualMachine],virtual_machine).summary.runtime.host
for i in self.list_obj([vim.HostSystem]):
if i == hosts_name:
hosts_ip = i.name
listOBJ = self.get_obj([vim.HostSystem],hosts_ip)
try:
exsi_version = listOBJ.summary.config.product.fullName
except Exception as err:
print err
exsi_version = ''
except Exception as err:
print err
exsi_version = ''
return exsi_version
捡一些重要的说:包含了添加网卡、获取所有虚拟机、获取集群、获取存储、获取主机Console授权、获取虚拟交换机、获取宿主机、获取宿主机Esxi版本、获取Vcenter、获取Vcenter所有报警、获取虚拟机存放文件夹等等
在下面的Console功能中,我们需要到的功能有:获取宿主机Esxi版本、获取主机Console授权,后端代码如下:
vcenter = VCenter()
vcenter.connect_to_vcenter()
vm_exsi_version = ss.get_hosts_exsi_version(vm) //获取宿主机的Esxi版本,进行判断,目前只支持 Exsi 6.x
vm_console_info = ss.get_acquireTicket(vm) //获取一些Console授权的信息
vm_console_host = vm_console_info['host']
vm_console_port = vm_console_info['port']
vm_console_ticket = vm_console_info['ticket']
前端通过html5+Websokct,部分代码如下:
<link rel="stylesheet" type="text/css" href="css/wmks-all.css"/>
<script type="text/javascript" src="jquery.min.js"></script>
<script type="text/javascript" src="jquery-ui.min.js"></script>
<script type="text/javascript" src="wmks.min.js" type="text/javascript"></script>
<div id="wmksContainer" style="position:absolute;width:100%;height:100%"></div>
<script> var wmks = WMKS.createWMKS("wmksContainer",{}) .register(WMKS.CONST.Events.CONNECTION_STATE_CHANGE, function(event,data){ if(data.state == WMKS.CONST.ConnectionState.CONNECTED) { console.log("connection state change : connected"); } }); wmks.connect("wss://{{ vm_console_host }}:{{ vm_console_port }}/ticket/{{ vm_console_ticket }}");
这里踩过的坑:
很有可能打开之后无法链接到wss://宿主机IP/ticket/xxxxxxxxxxx,原因是该网站的证书不被浏览器支持。可以先在浏览器打开https://宿主机IP,并信任ssl证书即可。