本帖最后由 leavelost 于 2017-1-23 00:12 编辑
【写在前面】
因为是求助帖,所以全篇无图,都是纯手工码字。
记录自己的折腾过程,也希望大家提出不同的意见思路,
更希望论坛大神能够解答小弟的疑惑~先行谢过!
【背景】
本人非挨踢从业人员,更别提编程能力了,以下内容全部来自谷哥、度娘,在此感谢辛勤付出的原作者们~!
【目前方案】
- N54L装的是黑裙,7*24小时开机。
- Homeserver装的是Freenas,只在备份N54L数据时才开机。
- UPS,型号是APC-BX650,同时为N54L及Homeserver提供电力,但是只有一个usb通讯口,所以接在了24小时开机的N54L上面。
【替代方案】
因为Homeserver的配置比N54L高了好多,只做存储有点于心不忍,所以准备调换一下2台机器的角色。
- N54L装Freenas9.10.2-U1,只在备份Homeserver数据时才开机。
- Homeserver用U盘装Esxi6.0,挂一个480G的SSD,里面装黑裙(挂载主板Lsi芯片直通的机械硬盘),再装一些尝鲜的系统,7*24开机
- UPS只有一个通讯口,所以必须接在7*24的机器上,也就是ESXI上面。
但是APC官方没有提供这款UPS对ESXI的支持(其实普通的UPS都不带这种支持),所以才有了这篇文章。。。
【方案改进】
- 原理:通过搜索,找到了三种能够1台UPS控制多台主机的软件方案,APCUPSD,Winpower,NUT(network ups tool),基本原理很简单,所有电脑的电源都接在UPS上,然后分别在主机(与UPS通讯的机器)和客户机上安装上述软件中的一款,当没有市电的时候,UPS转用内部电池,并通过通讯接口向主机发送信号,主机接收到UPS的信号后,通知客户机关机,等所有的客户机关机后,主机最后执行关闭本机和关闭UPS的操作,整个断电关机过程完毕。而且当客户机是ESXI时,只要ESXI中的VM安装了VMtool,就可以做到安全关闭VM——安全关闭ESXI——通知主机。
- 选择:由于Freenas内置了NUT,而NUT对其他两种软件的兼容不好(虽然有APCUPSD-controlled devices这个驱动,但是撸主我不会设置。。。),所以追求完美的我,果断放弃了前2种软件,专攻NUT的“研究”。
- 研究:原理说了整套方案以一台主机为核心,主机可以是安装了任意操作系统的“电脑”,所以也就包括了Homeserver上ESXI里的VM,但是因为Esxi系统里VM的嵌套,开关机顺序的问题,需要比较复杂的脚本才能做到:直通VM1的UPS断电——UPS通知VM1——VM1通知ESXI——ESXI依次关闭所有VM——UPS断电关闭,所以机智的我选择用一个低功耗的树莓派来充当UPS主机。
- 结果:UPS通讯接口连接树莓派,UPS提供电源给N54L,Homeserver,树莓派,交换机(如果断网主机就没办法通知和接收客户机信号了)
撸主很顺利的完成了链接1的内容,断电后树莓派立刻通知Freenas关机,但是NUT默认设置是等到UPS发出低电量警告后,再通知主机关机、UPS关闭,所以撸主等了整整15分钟,树莓派才关机并关闭了UPS。
【问题疑惑】
- 根据链接2、3的教程,撸主没能成功关闭ESXI,希望感兴趣的坛友能尝试一下~
想到能在ESXI里添加脚本,来达到树莓派远程通知ESXI依次关闭VM,最后关闭ESXI自己的功能,
第一步,因为ESXI安装目录下不能存放非ESXI文件,所以将连接中的脚本powerdown-esxi6.sh保
存在SSD上(ESXI装在U盘里的)实测通过Xshell连上ESXI,执行powerdown-esxi6.sh,
可以安全做到依次关闭VM,最后ESXI关机。
- #!/bin/ash
- # title: powerdown-esxi6.sh
- # version: 0.5
- # date: october 09, 2011
- # author: herwarth heitmann
- # edit by: massimo vannucci
- #variables
- PATH=/bin:/sbin:/usr/bin:/usr/sbin
- VIMSH_WRAPPER=vim-cmd
- VM_FILE=vm_list
- INTERVAL=60
- MAXLOOP=3
- #DATE=`date "+%Y-%m-%d %H:%M:%S"`
- # To enable logging, set the following variable to 1
- LOG_ENABLED=1
- LOG_FILE=/vmfs/volumes/sandisk480g/powerdown-esxi6.log
- # Remember that >> after echo, redirect and append to file
- # Set the log file
- if [ $LOG_ENABLED -eq 1 ]; then
- echo -e "\n\n\n"`date "+%Y-%m-%d %H:%M:%S"` "\t\tExecuting powerdown-esxi5.sh" >> $LOG_FILE
- fi
- #check if parameter given
- case "$1" in
- "") LASTACTION=shutdown
- ;;
- reboot) LASTACTION=reboot
- ;;
- vmonly) LASTACTION=vmonly
- ;;
- *) echo "usage $0 <|vmonly|reboot>"
- exit 1
- ;;
- esac
- #retrieve all VmId for VM(s) registered under ESXi host
- ${VIMSH_WRAPPER} vmsvc/getallvms >> $LOG_FILE
- ${VIMSH_WRAPPER} vmsvc/getallvms | awk '{print $1}' | grep -v 'Annotation' | grep -v 'Vmid' > $VM_FILE
- #first time initialisation
- ERROR=0
- FIRSTRUN=1
- LOOP=0
- #we want to run the loop at least 1 time! and loop until no more errors occur
- while [ $ERROR -ne 0 -o $FIRSTRUN -eq 1 ]; do
- LOOP=$(($LOOP+1))
- if [ $FIRSTRUN -eq 0 ]; then
- if [ $LOG_ENABLED -eq 1 ]; then
- echo -e `date "+%Y-%m-%d %H:%M:%S"` "\t\tGive virtual machines time to shutdown..." >> $LOG_FILE
- else
- echo "Give virtual machines time to shutdown..."
- fi
- sleep $INTERVAL
- fi
- #exit loop if $LOOP gets bigger than $MAXLOOP
- if [ $LOOP -gt $MAXLOOP ]; then
- echo "Maximum loops reached!"
- break
- fi
- FIRSTRUN=0
- ERROR=0
- for VM_LINE in $(cat ${VM_FILE}); do
- STATE=$(${VIMSH_WRAPPER} vmsvc/power.getstate ${VM_LINE} | grep -v 'runtime')
- if [ "$STATE" = "Powered off" -o "$STATE" = "Suspended" ]; then
- if [ $LOG_ENABLED -eq 1 ]; then
- echo -e `date "+%Y-%m-%d %H:%M:%S"` "\t\tVM with ID: ${VM_LINE} is: $STATE, skipping..." >> $LOG_FILE
- else
- echo "VM with ID: ${VM_LINE} is: $STATE, skipping..."
- fi
- else
- #try to do proper shutdown if VMware Tools are installed
- if [ $LOG_ENABLED -eq 1 ]; then
- echo -e `date "+%Y-%m-%d %H:%M:%S"` "\t\tVM with ID: ${VM_LINE:} is: $STATE, trying guest shutdown..." >> $LOG_FILE
- else
- echo "VM with ID: ${VM_LINE} is: $STATE, trying guest shutdown..."
- fi
- ${VIMSH_WRAPPER} vmsvc/power.shutdown "${VM_LINE}" > /dev/null 2>&1
- #if it fails to shutdown, we know there are no VMware Tools installed
- if [ $? -eq 1 ]; then
- #hard power off
- if [ $LOG_ENABLED -eq 1 ]; then
- echo -e `date "+%Y-%m-%d %H:%M:%S"` "\t\tGuest shutdown not working, hard powering off" >> $LOG_FILE
- else
- echo -e "\tGuest shutdown not working, hard powering off"
- fi
- ${VIMSH_WRAPPER} vmsvc/power.off "${VM_LINE}" > /dev/null 2>&1
- else
- if [ $LOG_ENABLED -eq 1 ]; then
- echo -e `date "+%Y-%m-%d %H:%M:%S"` "\t\tSuccessfully initiated shutdown of ${VM_LINE}" >> $LOG_FILE
- else
- echo -e "\t\tSuccessfully initiated shutdown of ${VM_LINE}"
- fi
- fi
- ERROR=$(($ERROR+1))
- fi
- done
- done
- # clean up temporary file
- rm -f $VM_FILE
- #execute last action
- case "$LASTACTION" in
- shutdown) #shutdown ESXi host
- if [ $LOG_ENABLED -eq 1 ]; then
- echo -e `date "+%Y-%m-%d %H:%M:%S"` "\t\tShutting down ESXi host..." >> $LOG_FILE
- fi
- /sbin/poweroff
- ;;
- reboot) #reboot ESXi host
- if [ $LOG_ENABLED -eq 1 ]; then
- echo -e `date "+%Y-%m-%d %H:%M:%S"` "\t\tRebooting ESXi host..." >> $LOG_FILE
- fi
- /sbin/reboot
- ;;
- vmonly) #do nothing! only VMs needed to be shutdown
- if [ $LOG_ENABLED -eq 1 ]; then
- echo -e `date "+%Y-%m-%d %H:%M:%S"` "\t\tDo nothing with ESXi host..." >> $LOG_FILE
- fi
- ;;
- esac
- exit 0
复制代码 第二步,现在来到树莓派上,参考:https://gist.github.com/gschora/a10f0692e6e691aa1af8
建立一个新文件notifyme,赋予可执行属性,内容如下:
- #! /bin/bash
- WALL=wall
- #在树莓派命令行中显示“123abc”,已确认此脚本被正确执行
- echo "123abc" | ${WALL}
- #通过ssh连接ESXI,并执行之前已经在SSD中建立的ESXI关机脚本
- ssh root@192.168.2.50 "nohup /vmfs/volumes/sandisk480g/powerdown-esxi6.sh > /dev/null 2>&1 &"
复制代码 因为之前已经将ESXI和树莓派的密钥配对了,所以在树莓派上执行notifyme后,树莓派中命令行显示
“123abc”,后台远程登陆ESXI(自动登陆,无需输入ESXI账号密码),
并执行ESXI上ssd中的powerdown-esxi6.sh,
ESXI开始依次关闭VM,然后关闭自己,到目前为止一些顺利~
第三步,根据NUT的文档:http://networkupstools.org/docs/user-manual.chunked/ar01s07.html
可以设置当UPS使用内置电池供电时,即ONBATT这个状态,调用执行在upsmon.conf中预先设的命令,
而我调用的就是刚才建立的notfiyme命令,现在实验一下,断开UPS的市电,树莓派上显示on battery
接着显示“123abc”(表明已经正确调用notifyme了),但是。。。远程的ESXI并没有树莓派登陆的日志
更不用提执行ssd中的关机脚本了。。。
更新第三步,原来linux的权限太规范了~,NUT在执行脚本的时候是用nut这个用户,而nut用户默认没有bin的权限,我也没有将nut用户的公钥传到esxi主机上,现 在完成以上2个操作后,当树莓派上的ups没有市电进入时,esxi也可以顺利的完全关机了~下一阶段试着改变NUT的默认设置,让它可以在ups供电几分钟后关闭ups,而不是等到电池快耗尽了才关闭
再次感谢@helhades @xudaiqing 两位~
|