欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

蓝鲸智能云支持虚拟机交付(II)--虚拟机管理(VSPHERE)--1.原子前端开发

最编程 2024-04-25 07:55:13
...
vim vsphere_vm_create.js
(function(){
    $.atoms.vsphere_vm_create = [
        {
            tag_code: "vsphere_vm_name",
            type: "input",
            attrs: {
                name: gettext("虚拟机名"),
                placeholder: gettext("新建虚拟机名"),
                hookable: true,
                validation: [
                    {
                        type: "required"
                    }
                ]
            }
        },
        {
            tag_code: "vsphere_vm_ip",
            type: "input",
            attrs: {
                name: gettext("虚拟机IP"),
                placeholder: gettext("虚拟机IP"),
                hookable: true,
                validation: [
                    {
                        type: "required"
                    }
                ]
            }
        },
        {
            tag_code: "vsphere_template_name",
            type: "radio",
            attrs: {
                name: gettext("模板名称"),
                items: [
                    {value: "template_root", name: "root"},
                ],
                default: "root",
                hookable: true,
                validation: [
                    {
                        type: "required"
                    }
                ]
            }
        },
        {
            tag_code: "vsphere_datacenter_name",
            type: "radio",
            attrs: {
                name: gettext("数据中心"),
                items: [
                    {value: "idc", name: "idc"},
                ],
                default: "idc",
                hookable: true,
                validation: [
                    {
                        type: "required"
                    }
                ]
            }
        },
        {
            tag_code: "vsphere_cluster_name",
            type: "radio",
            attrs: {
                name: gettext("集群名"),
                items: [
                    {value: "online", name: "online"},
                    {value: "offline", name: "offline"},
                ],
                default: "offline",
                hookable: true,
                validation: [
                    {
                        type: "required"
                    }
                ]
            }
        },
        {
            tag_code: "vsphere_folder_name",
            type: "input",
            attrs: {
                name: gettext("存放位置"),
                placeholder: gettext("虚拟机存放位置"),
                hookable: true,
                validation: [
                    {
                        type: "required"
                    }
                ]
            }
        },
        {
            tag_code: "vsphere_datastore_name",
            type: "select",
            attrs: {
                name: gettext("存储器名"),
                placeholder: gettext("存储器名"),
                items: [
                    {text: "test1.datastore1", value: "test1.datastore1"},
                    {text: "test2.datastore1", value: "test2.datastore1"},
                ],           
                hookable: true,
                validation: [
                    {
                        type: "required"
                    }
                ]
            }
        },

    ]
})();

我们通过前端输入相应的参数,如下:

前段展示
2.原子后端开发

(1)虚拟机创建

虚拟机创建主要分三部分:
a.虚拟机克隆,我们根据pyvmomi的clone_vm.py 进行修改;
b.自定义规范修改ip、主机名,也需要通过pyvmomi进行修改;
c.启动虚拟机,自定义规范后的虚拟机是关机状态的,我们需要重新开机
以上几步可参考vmware自定义规范定制虚拟机(二)-pyvmomi

需要根据实际情况修改vcenter连接参数

'''
vsphere 基础函数
'''
#vsphere vcenter连接参数
host = "10.10.5.88"
user = "admin@vsphere.local"
password = "xxxxxxxxxx"
port = 443
no_ssl = True
power_on = False
resource_pool = False
vsphere_datastorecluster_name = False

def wait_for_task(task):
    """ wait for a vCenter task to finish """
    task_done = False
    while not task_done:
        if task.info.state == 'success':
            return task.info.result

        if task.info.state == 'error':
            print("go to vCenter")
            return task.info.result
            task_done = True     

def get_obj(content, vimtype, name):
    """
    Return an object by name, if name is None the
    first found object is returned
    """
    obj = None
    container = content.viewManager.CreateContainerView(
        content.rootFolder, vimtype, True)
    for c in container.view:
        if name:
            if c.name == name:
                obj = c
                break
        else:
            obj = c
            break

    return obj

def ip_assign(vm, vm_ip, vm_name):
    """设置IP地址"""
    adaptermap = vim.vm.customization.AdapterMapping()
    adaptermap.adapter = vim.vm.customization.IPSettings()
    adaptermap.adapter.ip = vim.vm.customization.FixedIp()
    adaptermap.adapter.ip.ipAddress = vm_ip
    adaptermap.adapter.subnetMask = "255.255.255.0"
    adaptermap.adapter.gateway = "192.168.3.1"
    #adaptermap.adapter.dnsDomain = "localhost"
    """dns设置"""
    globalip = vim.vm.customization.GlobalIPSettings()
    globalip.dnsServerList = "114.114.114.114"
    """设置主机名"""
    ident = vim.vm.customization.LinuxPrep()
    #ident.domain = "localhost"
    ident.hostName = vim.vm.customization.FixedName()
    ident.hostName.name = vm_name
    customspec = vim.vm.customization.Specification()
    customspec.nicSettingMap = [adaptermap]
    customspec.globalIPSettings = globalip
    customspec.identity = ident
    print "Reconfiguring VM Networks . . ."
    #task = get_obj([vim.VirtualMachine],vm).Customize(spec=customspec)
    task = vm.Customize(spec=customspec)
    wait_for_task(task)
    
    return True

def clone_vm(
        content, template, vm_name, si,
        datacenter_name, vm_folder, datastore_name,
        cluster_name, resource_pool, power_on, datastorecluster_name):
    """
    Clone a VM from a template/VM, datacenter_name, vm_folder, datastore_name
    cluster_name, resource_pool, and power_on are all optional.
    """

    # if none git the first one
    datacenter = get_obj(content, [vim.Datacenter], datacenter_name)

    if vm_folder:
        destfolder = get_obj(content, [vim.Folder], vm_folder)
    else:
        destfolder = datacenter.vmFolder

    if datastore_name:
        datastore = get_obj(content, [vim.Datastore], datastore_name)
    else:
        datastore = get_obj(
            content, [vim.Datastore], template.datastore[0].info.name)

    # if None, get the first one
    cluster = get_obj(content, [vim.ClusterComputeResource], cluster_name)

    if resource_pool:
        resource_pool = get_obj(content, [vim.ResourcePool], resource_pool)
    else:
        resource_pool = cluster.resourcePool

    vmconf = vim.vm.ConfigSpec()

    if datastorecluster_name:
        podsel = vim.storageDrs.PodSelectionSpec()
        pod = get_obj(content, [vim.StoragePod], datastorecluster_name)
        podsel.storagePod = pod

        storagespec = vim.storageDrs.StoragePlacementSpec()
        storagespec.podSelectionSpec = podsel
        storagespec.type = 'create'
        storagespec.folder = destfolder
        storagespec.resourcePool = resource_pool
        storagespec.configSpec = vmconf

        try:
            rec = content.storageResourceManager.RecommendDatastores(
                storageSpec=storagespec)
            rec_action = rec.recommendations[0].action[0]
            real_datastore_name = rec_action.destination.name
        except:
            real_datastore_name = template.datastore[0].info.name

        datastore = get_obj(content, [vim.Datastore], real_datastore_name)

    # set relospec
    relospec = vim.vm.RelocateSpec()
    relospec.datastore = datastore
    relospec.pool = resource_pool

    clonespec = vim.vm.CloneSpec()
    clonespec.location = relospec
    clonespec.powerOn = power_on

    print("cloning VM...")
    task = template.Clone(folder=destfolder, name=vm_name, spec=clonespec)

    #返回结果函数,用于判断任务是否完成
    return wait_for_task(task)

以上我们根据克隆虚拟机、自定义规范、启动虚拟机整合pyvmomi中的函数到我们的后端原子中,也就是说我们虚拟机创建基础函数

(2)标准运维后端原子

现在我们把pyvmomi的函数正式整合到标准运维原子中,完整代码如下:

# -*- coding: utf-8 -*-
'''
vsphere虚拟机管理
'''
from pipeline.conf import settings
from pipeline.core.flow.activity import Service
from pipeline.component_framework.component import Component
from pyVmomi import vim
from pyVim.connect import SmartConnect, SmartConnectNoSSL, Disconnect
import atexit
import argparse
import getpass
import logging
import json
import time

logger = logging.getLogger("root")

__group_name__ = u"虚拟机管理(VSPHERE)"

#vsphere vcenter连接参数
host = "10.10.5.88"
user = "admin@vsphere.local"
password = "xxxxxxxxxxx"
port = 443
no_ssl = True
power_on = False
resource_pool = False
vsphere_datastorecluster_name = False

'''
vsphere 基础函数
'''
def wait_for_task(task):
    """ wait for a vCenter task to finish """
    task_done = False
    while not task_done:
        if task.info.state == 'success':
            return task.info.result

        if task.info.state == 'error':
            print("go to vCenter")
            return task.info.result
            task_done = True     

def get_obj(content, vimtype, name):
    """
    Return an object by name, if name is None the
    first found object is returned
    """
    obj = None
    container = content.viewManager.CreateContainerView(
        content.rootFolder, vimtype, True)
    for c in container.view:
        if name:
            if c.name == name:
                obj = c
                break
        else:
            obj = c
            break

    return obj

def ip_assign(vm, vm_ip, vm_name):
    """设置IP地址"""
    adaptermap = vim.vm.customization.AdapterMapping()
    adaptermap.adapter = vim.vm.customization.IPSettings()
    adaptermap.adapter.ip = vim.vm.customization.FixedIp()
    adaptermap.adapter.ip.ipAddress = vm_ip
    adaptermap.adapter.subnetMask = "255.255.255.0"
    adaptermap.adapter.gateway = "192.168.3.1"
    #adaptermap.adapter.dnsDomain = "localhost"
    """dns设置"""
    globalip = vim.vm.customization.GlobalIPSettings()
    globalip.dnsServerList = "114.114.114.114"
    """设置主机名"""
    ident = vim.vm.customization.LinuxPrep()
    #ident.domain = "localhost"
    ident.hostName = vim.vm.customization.FixedName()
    ident.hostName.name = vm_name
    customspec = vim.vm.customization.Specification()
    customspec.nicSettingMap = [adaptermap]
    customspec.globalIPSettings = globalip
    customspec.identity = ident
    print "Reconfiguring VM Networks . . ."
    #task = get_obj([vim.VirtualMachine],vm).Customize(spec=customspec)
    task = vm.Customize(spec=customspec)
    wait_for_task(task)
    
    return True

def clone_vm(
        content, template, vm_name, si,
        datacenter_name, vm_folder, datastore_name,
        cluster_name, resource_pool, power_on, datastorecluster_name):
    """
    Clone a VM from a template/VM, datacenter_name, vm_folder, datastore_name
    cluster_name, resource_pool, and power_on are all optional.
    """

    # if none git the first one
    datacenter = get_obj(content, [vim.Datacenter], datacenter_name)

    if vm_folder:
        destfolder = get_obj(content, [vim.Folder], vm_folder)
    else:
        destfolder = datacenter.vmFolder

    if datastore_name:
        datastore = get_obj(content, [vim.Datastore], datastore_name)
    else:
        datastore = get_obj(
            content, [vim.Datastore], template.datastore[0].info.name)

    # if None, get the first one
    cluster = get_obj(content, [vim.ClusterComputeResource], cluster_name)

    if resource_pool:
        resource_pool = get_obj(content, [vim.ResourcePool], resource_pool)
    else:
        resource_pool = cluster.resourcePool

    vmconf = vim.vm.ConfigSpec()

    if datastorecluster_name:
        podsel = vim.storageDrs.PodSelectionSpec()
        pod = get_obj(content, [vim.StoragePod], datastorecluster_name)
        podsel.storagePod = pod

        storagespec = vim.storageDrs.StoragePlacementSpec()
        storagespec.podSelectionSpec = podsel
        storagespec.type = 'create'
        storagespec.folder = destfolder
        storagespec.resourcePool = resource_pool
        storagespec.configSpec = vmconf

        try:
            rec = content.storageResourceManager.RecommendDatastores(
                storageSpec=storagespec)
            rec_action = rec.recommendations[0].action[0]
            real_datastore_name = rec_action.destination.name
        except:
            real_datastore_name = template.datastore[0].info.name

        datastore = get_obj(content, [vim.Datastore], real_datastore_name)

    # set relospec
    relospec = vim.vm.RelocateSpec()
    relospec.datastore = datastore
    relospec.pool = resource_pool

    clonespec = vim.vm.CloneSpec()
    clonespec.location = relospec
    clonespec.powerOn = power_on

    print("cloning VM...")
    task = template.Clone(folder=destfolder, name=vm_name, spec=clonespec)

    #返回结果函数,用于判断任务是否完成
    return wait_for_task(task)


class VsphereVMCreateService(Service):
    __need_schedule__ = False

    def execute(self, data, parent_data):
        vsphere_vm_name = data.get_one_of_inputs('vsphere_vm_name')
        vsphere_vm_ip = data.get_one_of_inputs('vsphere_vm_ip')
        vsphere_template_name = data.get_one_of_inputs('vsphere_template_name')
        vsphere_folder_name = data.get_one_of_inputs('vsphere_folder_name')
        vsphere_datacenter_name = data.get_one_of_inputs('vsphere_datacenter_name')
        vsphere_cluster_name = data.get_one_of_inputs('vsphere_cluster_name')
        vsphere_datastore_name = data.get_one_of_inputs('vsphere_datastore_name')

        args = {
            "host": host,
            "user": user,
            "password": password,
            "port": port,
            "no_ssl": no_ssl,
            "power_on": power_on,
            "vm_name": vsphere_vm_name,
            "template": vsphere_template_name,
            "datacenter_name": vsphere_datacenter_name,
            "cluster_name": vsphere_cluster_name,
            "vm_folder": vsphere_folder_name,
            "datastore_name": vsphere_datastore_name,
            "datastorecluster_name": vsphere_datastorecluster_name,
            "resource_pool": resource_pool
        }

        try:
            si = None
            if args['no_ssl']:
                si = SmartConnectNoSSL(
                    host=args['host'],
                    user=args['user'],
                    pwd=args['password'],
                    port=args['port'])
            else:
                si = SmartConnect(
                    host=args.host,
                    user=args.user,
                    pwd=args.password,
                    port=args.port)
            # disconnect this thing
            atexit.register(Disconnect, si)
        
            content = si.RetrieveContent()
            template = None
            
            template = get_obj(content, [vim.VirtualMachine], args['template'])

            if template:
                task_info_result = clone_vm(
                    content, template, args['vm_name'], si,
                    args['datacenter_name'], args['vm_folder'],
                    args['datastore_name'], args['cluster_name'],
                    args['resource_pool'], args['power_on'], args['datastorecluster_name'])          
                #if args.opaque_network:
                #此功能关闭
                #    vm = get_obj(content, [vim.VirtualMachine], args.vm_name)
                #    add_nic(si, vm, args.opaque_network)


                
                if task_info_result:
                    print task_info_result
                    
                    #自定义规范定制虚拟机
                    vm = get_obj(content, [vim.VirtualMachine], args['vm_name'])
                    task_info_result = ip_assign(vm, vsphere_vm_ip, args['vm_name'])
                    if task_info_result:
                        #启动自定义后的虚拟机
                        print "PowerOn vm..."
                        vm.PowerOn()
                        #启动完毕,等待50s完全启动
                        time.sleep(50)

                        data.set_outputs('vm_ip', vsphere_vm_ip)
                        return True
                    else:
                        print task_info_result
                        data.set_outputs('ex_data', u"自定义虚拟机错误")
                        return False
                else:
                    print task_info_result
                    data.set_outputs('ex_data', u"克隆虚拟机指定的参数错误或虚拟机名已重复")
                    return False
            else:
                data.set_outputs('ex_data', u"虚拟机模板没有找到")
                return False
            
        except Exception as e:
            data.set_outputs('ex_data', e)
            logger.exception(e)          
            return False

    def outputs_format(self):
        return [
            self.OutputItem(name=(u'虚拟机IP'), key='vm_ip', type='str'),
            self.OutputItem(name=(u'报错信息'), key='ex_data', type='str')
        ]

class VsphereVMCreateComponent(Component):
    name = u'创建虚拟机'
    code = 'vsphere_vm_create'
    bound_service = VsphereVMCreateService
    form = settings.STATIC_URL + 'custom_atoms/vsphere/vsphere_vm_create.js'

以上过程要注意:
a.日志打印,帮助我们解决问题;
b.ex_data,前端错误提示;
c.启动虚拟机,需要等待完全启动后,才能会后面原子提供服务;