授之以渔-运维平台应用模块二(Vmware控制台篇)

Vmware控制台: 为了方便管理vmware,尽量摆脱vSphere,目前实现了对虚拟机的增、删、改(硬件配置)、快照管理、Console控制台、克隆等功能,本文只详细的介绍下Console功能。先上一张效果图:

image.png

一、 环境准备

二、食用方法

代码如下:

# -*- 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证书即可。

image.png
image.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
禁止转载,如需转载请通过简信或评论联系作者。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,386评论 6 479
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,939评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,851评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,953评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,971评论 5 369
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,784评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,126评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,765评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,148评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,744评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,858评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,479评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,080评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,053评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,278评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,245评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,590评论 2 343

推荐阅读更多精彩内容