【虚拟机管理】批量创建Vsphere虚拟机脚本

1 环境准备

2 编辑ps1脚本

  • 通过脚本调用csv参数表,批量循环创建
#导入表格变量 2)模板网卡名 2)模板账号密码
        $vms = Import-CSV ./VM.csv  
        $templatenic = 'ens192'
        $templateuser = '模板账号'
        $templatepass = '模板密码'
#测试变量语句
$cmd = 'cmdecho111111111111111111111111'

#连接Vcenter认证信息
Connect-VIServer -Protocol https -User 'administrator@你的SSO_NAME.cn' -Password  '你的Vcenter密码' -Server Vcenter_IP

#循环取值 
foreach ($vm in $vms){

#主机名,不是OS主机名
      $VMName = $vm.Name
#网络
      $Network = $vm.Network
#虚拟cpu
      $Cpu = $vm.Cpu
#内存单位GB
      $Memory = $vm.Memory
#虚拟机备注
      $Notes = $vm.Usage
#新增磁盘
      $Disk = $vm.DISK
#使用的模板
      $Template = Get-Template $vm.Template
#所在ESXI物理主机IP
      $VMHost = Get-VMHost $vm.PhysicalHost
#使用的存储名
      $Datastore = Get-Datastore $vm.Datastore    
#放到哪个文件夹中
      New-Folder -Name $vm.Esxidir -Location VM 

        #等待5s
      Start-Sleep -s 5  
#使用上面的变量创建虚拟机     
      New-VM -Name $VMName -Template $Template -VMHost $VMHost -NetworkName $Network -Datastore $Datastore -RunAsync -Location $vm.Esxidir
      #等待30s
      Start-Sleep -s 30

#设置内存 CPU 备注      
      Get-VM -Name $VMName|Set-VM  -NumCPU $Cpu -MemoryGB $Memory -Notes $Notes -Confirm:$false
      Start-Sleep -s 5

#如果$DISK值不为0,就创建一个磁盘(厚制备延迟置0)
      if ($Disk -gt 0)
       { Get-VM -Name $VMName  | New-HardDisk -CapacityGB $Disk -Persistence persistent }

      Start-Sleep -s 5

#启动虚拟机      
      Get-VM $VMName| Start-VM
      Start-Sleep -s 20   

     #变量测试语句  
     #$vmcfg='echo '+$cmd+' >  /tmp/test.txt &&  echo '+$cmd+' &&  \
     #echo 123testetste'

#系统初始化脚本:1)主机名2)网卡配置 
     $vmcfg='hostnamectl set-hostname  '+$VMName+' ;bash        && \
          sed -i "/^IPADDR/c\IPADDR='+$vm.IPV4+'" /etc/sysconfig/network-scripts/ifcfg-'+$templatenic+'   && \
          sed -i "/^NETMASK/c\NETMASK='+$vm.NetMask+'" /etc/sysconfig/network-scripts/ifcfg-'+$templatenic+'       && \
          sed -i "/^GATEWAY/c\GATEWAY='+$vm.IPV4GW+'" /etc/sysconfig/network-scripts/ifcfg-'+$templatenic+'        && \
          sed -i "/^DNS1/c\DNS1=223.5.5.5" /etc/sysconfig/network-scripts/ifcfg-'+$templatenic+'          && \
          echo "DNS2=223.6.6.6" >> /etc/sysconfig/network-scripts/ifcfg-'+$templatenic+'                  && \
          echo "DNS3=119.29.29.29" >> /etc/sysconfig/network-scripts/ifcfg-'+$templatenic+'               && \
          cat /etc/sysconfig/network-scripts/ifcfg-'+$templatenic+'                                       && \
          /etc/init.d/network restart' 

        #使用模板的账号密码登录新建的虚拟机OS并执行sh脚本
        Get-VM $VMName | Invoke-VMScript -ScriptText $vmcfg -GuestUser $templateuser -GuestPassword  $templatepass
}

3 编辑参数变量表

  • 具体参数对应可在ps脚本中查找
    file

4 使用Go http实现上传csv表文件到Linux服务器

  • 代码需要修改IP为服务器IP后在编译成二进制包,nohup到后台运行即可
  • 默认上传到 /tmp 目录下,可以根据实际情况修改,注意这里的csv文件名是固定值 "VM.csv"
package main

import (
        "crypto/rand"
        "fmt"
        "html/template"
        "io/ioutil"
        "log"
        "net/http"
        "os"
        "path/filepath"
)
//文件限制2MB
const maxUploadSize = 2 * 1024 * 1024 // 2 mb
var uploadPath = os.TempDir()

func main() {
        http.HandleFunc("/upload", uploadFileHandler())

        fs := http.FileServer(http.Dir(uploadPath))
        http.Handle("/files/", http.StripPrefix("/files", fs))

        log.Print("Server started on 你自己的服务器IP:8083, use /upload for uploading files and /files/{fileName} for downloading")
        log.Fatal(http.ListenAndServe(":8083", nil))
}

func uploadFileHandler() http.HandlerFunc {
        return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
                if r.Method == "GET" {
                        t, _ := template.ParseFiles("upload.gtpl")
                        t.Execute(w, nil)
                        return
                }
                if err := r.ParseMultipartForm(maxUploadSize); err != nil {
                        fmt.Printf("Could not parse multipart form: %v\n", err)
                        renderError(w, "CANT_PARSE_FORM", http.StatusInternalServerError)
                        return
                }

                file, fileHeader, err := r.FormFile("uploadFile")
                if err != nil {
                        renderError(w, "INVALID_FILE", http.StatusBadRequest)
                        return
                }
                defer file.Close()

                fileSize := fileHeader.Size
                fmt.Printf("File size (bytes): %v\n", fileSize)

                if fileSize > maxUploadSize {
                        renderError(w, "FILE_TOO_BIG", http.StatusBadRequest)
                        return
                }
                fileBytes, err := ioutil.ReadAll(file)
                if err != nil {
                        renderError(w, "INVALID_FILE", http.StatusBadRequest)
                        return
                }

          //这个csv表格设置为你自己的名字
                fileName := "VM.csv"  
                newFileName := fileName
                newPath := filepath.Join(uploadPath, newFileName)
                fmt.Printf("FileType: %s, File: %s\n", newPath)

                newFile, err := os.Create(newPath)
                if err != nil {
                        renderError(w, "CANT_WRITE_FILE", http.StatusInternalServerError)
                        return
                }
                defer newFile.Close() 
                if _, err := newFile.Write(fileBytes); err != nil || newFile.Close() != nil {
                        renderError(w, "CANT_WRITE_FILE", http.StatusInternalServerError)
                        return
                }
                w.Write([]byte(fmt.Sprintf("SUCCESS - use /files/%v to access the file", newFileName)))
        })
}

func renderError(w http.ResponseWriter, message string, statusCode int) {
        w.WriteHeader(statusCode)
        w.Write([]byte(message))
}

func randToken(len int) string {
        b := make([]byte, len)
        rand.Read(b)
        return fmt.Sprintf("%x", b)
}
  • 网页模板代码 upload.gtpl
  <html>
  <head>
          <title>Upload file</title>
  </head>
  <body>
  <form enctype="multipart/form-data" action="http://你的服务器IP:8083/upload" method="post">
          <input type="file" name="uploadFile" />
          <input type="submit" value="upload" />
  </form>
  </body>
  </html>
  • 访问地址与效果

http://IP:8083/upload

file

5 使用jenkins发布任务

  • 编辑文件后通过网页api上传到linux服务器的/tmp/ 目录下后使用jenkins执行后台任务
  • 流水线参考
pipeline {
    agent any 

    stages {
        stage('构建') {
            parallel{
                stage('构建步骤-1-test') { 
                    steps { 
                        sh 'echo 开始构建步骤_1 ...' 
                    }
                }
                stage('创建虚拟机中') { 
                    steps { 

                        sh 'ssh root@你的服务器IP "cd /data/psh-create-host/many-create &&  yes|cp  -r -f   /tmp/VM.csv  /data/psh-create-host/many-create && pwsh /data/psh-create-host/many-create/VM.ps1 >> create.log "'
                    }
                }
            }
        }
        stage('测试'){
            steps {
                sh 'echo 开始测试 ...' 
            }
        }
        stage('发布') {
            steps {
                sh 'echo 开始发布 ...' 
            }
        }
    }
  }
  • 效果图
    file
转载请注明-MrZ-个人博客
THE END
分享
二维码
海报
【虚拟机管理】批量创建Vsphere虚拟机脚本
1 环境准备 一台Linux服务器,已经部署好jenkins、powershell-for-Linux以及powerCLI插件 jenkins优化:已配置ssh到宿主机的免密功能 代码文件 http://git.mrzsir.cn/mrzsir/create-vh.git 2 编辑ps1脚本 通过……
<<上一篇
下一篇>>