一、背景

vmware环境,特别是Horizon环境,对时间的一致性要求非常严苛,如果出现时间不一致,会导致身份验证失败,数据库主备复制一次,消息通信jms异常,组件之间通信异常,互相认证失败等各种莫名报错,故保证环境时间一致是维稳一个vmware虚拟换基础环境的关键,本文概述了如果借助VMware PowerCli执行ps批量脚本,批处理配置NTP时间,批处理配置虚拟机与esxi主机时间一致。

powerCli软件安装参见:

二、powerCli脚本

1、批处理配置ESXi主机NTP

#连接VC
$VC='10.179.x.x'
$NTPServer='10.132.x.x'
$UName='administrator@vsphere.local'
$UPass='yourpass'
Connect-VIServer -Server $VC -User $UName -Password $UPass
 
#更改主机时间
Foreach($HostIP in Get-VMHost){
	$esxcli = Get-EsxCli -VMHost $HostIP -V2
	$arguments = $esxcli.system.time.set.CreateArgs()
	$arguments.year = $(Get-Date -Format 'yyyy')
	$arguments.month = $(Get-Date -Format 'MM')
	$arguments.day = $(Get-Date -Format 'dd')
	$arguments.hour = $(Get-Date -Format 'HH')-8
	$arguments.min = $(Get-Date -Format 'mm')
	$esxcli.system.time.set.Invoke($arguments)
}
#设置NTP
Foreach($HostIP in Get-VMHost){
	Add-VmHostNtpServer -NtpServer "120.25.115.20" -VMHost $HostIP
	Add-VmHostNtpServer -NtpServer "ntp1.aliyun.com" -VMHost $HostIP
	Get-VMHostService -VMHost $HostIP | where { $_.Key -eq "ntpd" } | Start-VMHostService
	Get-VMHostService -VMHost $HostIP | where { $_.Key -eq "ntpd" } | Set-VMHostService -Policy "on" -Confirm:$false
}
#查询主机时间
Foreach($HostIP in Get-VMHost){
	$esxcli = Get-EsxCli -VMHost $HostIP -V2
	$esxcli.system.time.get.Invoke()

部分修改:

esxi安装的windows时间不对 esxi 时间日期不对_esxi安装的windows时间不对

执行效果:

esxi安装的windows时间不对 esxi 时间日期不对_NTP_02


2、批处理配置vm与esxi主机同步:

esxi安装的windows时间不对 esxi 时间日期不对_NTP_03


效果:

esxi安装的windows时间不对 esxi 时间日期不对_NTP_04

3、批量获取vc下所有esxi主机的时间:

$vmhostlist = get-vmhost
foreach ($vmhost in $vmhostlist){
    $esxcli = Get-EsxCli -VMHost $vmhost
    Write-Host "$vmhost" $esxcli.system.time.get() | Out-File esxi_time.txt
}

esxi安装的windows时间不对 esxi 时间日期不对_esxi时间配置_05


4、使用指定模板批量创建虚拟机

#定义参数
param(
[string]$VMname,[string]$vmhostname,[string]$datastore,
[string]$template
)

#在命令窗口中添加powercli模块
try{
add-pssnapin vmware.vimautomation.core -ErrorAction SilentlyContinue
}
catch{}

#连接Vsphere
Connect-VIServer -server Vsphere -Protocol https -User user -Password password

foreach ($i in 1..5)
{
$fullname = $VMname +"-"+ $i
new-vm -name $fullname -template $template -host $vmhostname -datastore $datastore
}

disconnect-viserver -confirm:$false

执行文件:

.\scriptfile.ps1 VMname vmhost datastore template   #不声明参数时,必须按照param指定的顺序输入参数

或者

.\screptfile.ps1 -VMname  vmname  -template template -vmhostname vmhost -datastore datastore   #对参数声明时,参数顺序可随意变动

【代码示例2】:

New-vm -vmhost esxi_name -Name SVR01 -Template WIN2008R2_Template -Datastore datastore1 -OSCustomizationspec WIN2008R2_Template

New-vm -vmhost esxi_name -Name SVR02 -Template WIN2008R2_Template -Datastore datastore1 -OSCustomizationspec WIN2008R2_Template

New-vm -vmhost esxi_name -Name SVR03 -Template WIN2008R2_Template -Datastore datastore1 -OSCustomizationspec WIN2008R2_Template

New-vm -vmhost esxi_name -Name SVR04 -Template WIN2008R2_Template -Datastore datastore1 -OSCustomizationspec WIN2008R2_Template

New-vm -vmhost esxi_name -Name SVR05 -Template WIN2008R2_Template -Datastore
datastore1 -OSCustomizationspec WIN2008R2_Template

说明:将上述文件保存为.ps1文件之后,在命令行下执行:

-vmhost:VM生成的目标ESXi主机;
-Name:生成的VM的名字;
-Template:用于生成VM的模板主机;
-Datastore:生成的虚拟机的存放数据存储;
-OSCustomizationspec:定制化部署VM的prep目录;

esxi安装的windows时间不对 esxi 时间日期不对_esxi安装的windows时间不对_06

5、批量重启正在运行具有名字相似可以进行匹配的的虚拟机

#在命令窗口中添加powercli模块
try{
add-pssnapin vmware.vimautomation.core -ErrorAction SilentlyContinue
}
catch{}

#连接Vsphere
Connect-VIServer -server Vsphere -Protocol https -User user -Password password

#定义正则表达式
$matchname="^[a-zA-Z]+\d{5}([a-zA-Z]{1,4})?(\w)?([a-zA-Z]{3})?(\d+)?"

#重启匹配的虚拟机
Get-Cluster -Name cluster |Get-VM |where {$_.Name -match $matchname -and $_.PowerState -eq "PoweredOn"} | Restart-VM -RunAsync

disconnect-viserver -confirm:$false

6、批量获取 VMX 并注册到 VC 清单中

场景说明:
1)存储迁移,VM 计划性停机,需要批量的把 VM 注册到新机房的计算资源池中。
2)找出没有注册到VC指定位置中的非活动 VM

【代码示例】:

#获取集群内的 Datastore
$Datastoreinfo =  Get-Datastore -Nmae 'DatastoreName' | %{Get-View $_.Id}

$DsBrowser = Get-View $Datastoreinfo.browser

$SearchSpec = New-Object VMware.Vim.HostDatastoreBrowserSearchSpec
$SearchSpec.matchpattern = "*.vmx"
$DsPath = "[" + $Datastoreinfo.Name + "]"

$SearchResult = $DsBrowser.SearchDatastoreSubFolders($DsPath, $SearchSpec) | where {$_.FolderPath -notmatch ".snapshot"} | %{$.FolderPath + ($_.File | select Path).Path}


#注册vm
New-VM -Name $VMname -VMFilePath $VMXpath -ResourcePool $vmhost -Location $VMFolder -RunAsync

7、对vm批量关机(一般界面也可以完成)

【操作步骤】:

1:链接前,先禁用无证书 提示(有证书的忽略此处)。
2:获取所有 加电的主机
3:遍历主机的ToolsStatus ,也就是 tools 状态
4:如果tools 状态不为 toolsNotInstalled 的,则关闭客户机否则关机。
5:5秒后,获取所有加电主机。
6:如果数量不为0,则返回第2步,否则 向主机发送关机指令。

【代码示例】:

$TextUtf8 = New-Object -typename System.Text.UTF8Encoding
Write-Host
Write-Host "      安装tools的关闭系统,没安装tools的关闭电源"
Write-Host "      vCnter关机要 4-6 分钟"
Write-Host
pause
 
$EsxiHost = "127.0.0.1"
$EsxiUser = "root"
$EsxiPassWd = "Passwd@yhc18"
Write-Host " 正在连接 服务器 。。。 。。。"
$ConnIgnore = Set-PowerCLIConfiguration -InvalidCertificateAction Ignore -confirm:$false
$ConnectVIServer = Connect-VIServer -Server $EsxiHost -username $EsxiUser -Password $EsxiPassWd
 
while(1 -eq 1){   
    $PowerOnVm = get-vm | where {$_.PowerState -eq "PoweredOn"}
    $PowerOnNum=$PowerOnVm.count
    if($PowerOnVm.count -gt 0){        
        cls
        Write-Host "ID" . "vmName" "ToolsStatus" "(正在运行中)"
        $index = 0       
        $PowerOnVm | foreach{
            $index++
             if($_.extensiondata.guest.ToolsStatus -ne "toolsNotInstalled"){
                Write-Host $index.    $_.Name    "    on"
             }else{
                Write-Host $index.    $_.Name    "    off"
             }
        }
        Write-Host "------------------------------------------"
        $index2=0
        $PowerOnVm | foreach{              
            if($_.extensiondata.guest.ToolsStatus -ne "toolsNotInstalled"){
                $index2++;
                Write-Host "$index2/$PowerOnNum"  "关闭客户机" $_.Name
                $stopGuest = Get-Vm -Name $_.Name |stop-VMGuest -confirm:$false -ErrorAction SilentlyContinue
                Start-Sleep -Seconds 3
            }else{
                $index2++;
                Write-Host "$index2/$PowerOnNum"  "关闭机器" $_.Name
                $stopGuest = Get-Vm -Name $_.Name |stop-VM -confirm:$false -ErrorAction SilentlyContinue
                Start-Sleep -Seconds 3                
            }
        }
    }else{
        $PowerOnHosts = Get-VMHost| Where {$_.Name -eq $EsxiHost} | Stop-VMHost -confirm:$false -Force:$true
        cls
        echo "虚拟机已关机完毕,发送Esxi关机指令,等待Esxi主机关机"
        pause
        break #跳出循环       
    }
    Start-Sleep -Seconds 5
}

8、从csv读取批量创建vm:

#Specify path of .csv file to import VM settings 
$CSVPath = "C:\NewVMList.csv" 

$CSVFILE = Import-CSV $CSVPath 

$VMhost = Get-vmhost "$($CSVFile.VMHost)" 
$PortGroup = Get-VirtualPortgroup -name "$($CSVFile.VLAN)" -VMhost $VMhost 

New-VM -Name "$($CSVFile.Name)" -MemoryGB "$($CSVFile.MemoryGB)" -NumCPU "$($CSVFile.NumCPU)" -portgroup $Portgroup -DiskGB "$($CSVFile.C_System)"