function() {
var vpsName = form("vpsName") || "NewVPS";
var system = (form("system") || "alpine").toLowerCase();
var cpu = ~~form("cpu") || 1;
var mem = ~~form("mem") || 1;
if(/^[^\w \-\.]$/.test(vpsName)) return { err: "虚拟机名称不能包含特殊字符" };
if(!sys.source[system]) return { err: "不支持的系统类型" };
// 判断此名称的虚拟机是否创建过了
var vps = wmi().execQuery("select * from CIM_System where ElementName='" + vpsName + "'");
if(vps.Count) return { err: "虚拟机名称【" + vpsName + "】已被使用" };
// 创建硬盘是异步操作,先创建硬盘镜像
var rs = this.vhdcreate(vpsName, system);
if(rs.err) return { err: rs.err, step: "创建硬盘" };
// 创建虚拟机
rs = this.vpscreate(vpsName);
if(rs.err) return { err: rs.err, step: "创建虚拟机" };
// 挂载硬盘到虚拟机
var vpsid = wmi().Get(rs.ResultingSystem).Name;
rs = this.vpsattachvhd(vpsid, sys.dir.vhdRoot + "\\Free\\" + vpsName + ".vhdx");
if(rs.err) return { err: rs.err, step: "挂载硬盘" };
// 挂载网络适配器
rs = this.vpsattacheth(vpsid, "Default Switch");
if(rs.err) return { err: rs.err, step: "挂载网络适配器" };
// 开机
rs = this.startup(vpsid);
if(rs.err) return { err: rs.err, step: "开机" };
return { msg: "虚拟机【" + vpsName + "】创建成功,默认密码为:zf" };
}
function() {
var vpsName = form("vpsName");
if(/^[^\w \-\.]$/.test(vpsName)) return { err: "虚拟机名称不能包含特殊字符" };
var vps = wmi().execQuery("select * from CIM_ComputerSystem where ElementName='" + vpsName + "'");
if(vps.Count < 1) return { err: "虚拟机【" + vpsName + "】不存在" };
vps = vps.ItemIndex(0);
var vss = wmi().Get("Msvm_VirtualSystemSettingData.InstanceID='Microsoft:" + vps.Name + "'");
if(vss.Version != "8.3") return { err: "此虚拟机暂时只能由管理员删除。" };
if(vps.EnabledState != 3) {
vps.RequestStateChange(4);
return { err: "已尝试关闭虚拟机【" + vps.Name + "】,请稍后重试。" };
}
var vsms = wmi().execQuery("select * from Msvm_VirtualSystemManagementService").ItemIndex(0);
// 先删除虚拟机会导致虚拟硬盘文件被占用,所以先删虚拟硬盘。
var fso = new ActiveXObject("Scripting.FileSystemObject");
fso.DeleteFile(sys.dir.vhdRoot + "\\Free\\" + vpsName + ".vhdx");
vsms.DestroySystem(vps.Path_.Path);
return { msg: "虚拟机【" + vpsName + "】删除完成" };
}
function() {
return { msg: "此方法会自动创建一个空虚拟机,已关闭此接口" };
var rs = wmi().instancesOf("Msvm_VirtualSystemManagementService");
if(!rs.Count) return { err: "未找到服务" };
rs = wmiToArr(rs, "Caption, DefineSystem, Description, StatusDescriptions, InstallDate")[0];
rs.InstallDate = parseTime(rs.InstallDate);
return rs;
}
function(jobPath) {
if(!jobPath) jobPath = form("jobPath");
try{ var job = wmi().Get(jobPath); }
catch(err) { return { err: err.message }; }
return { Name: job.Name, StatusDescriptions: job.StatusDescriptions };
}
function() {
// 获取网络参数
var network = wmi().instancesOf("Msvm_GuestNetworkAdapterConfiguration");
var cfg = new Object;
for(var i = 0; i < network.Count; i++) {
var adp = network.ItemIndex(i);
var vpsid = adp.InstanceID.split("\\")[1];
cfg[vpsid] = adp.IPAddresses.join(", ");
}
var rs = wmi().execQuery("select * from CIM_System where Caption='虚拟机'");
// 得到虚拟机列表(名称,安装时间,运行状态,开机时间毫秒数)
rs = wmiToArr(rs, "Name, ElementName, InstallDate, EnabledState, OnTimeInMilliseconds");
var status = [ "", "", "运行中", "已关机" ];
for(var i = 0; i < rs.length; i++) {
rs[i].IP = cfg[rs[i].Name] || "-";
rs[i].StateDescription = status[rs[i].EnabledState];
rs[i].InstallDate = parseTime(rs[i].InstallDate);
if(rs[i].OnTimeInMilliseconds > 0) {
rs[i].BootTime = new Date(sys.sTime - rs[i].OnTimeInMilliseconds).getVarDate();
}
};
return rs;
}
function(vpsName) {return { err: "抱歉,系统资源不够了。" };
if(!vpsName) vpsName = form("vpsName") || "NewVPS";
var vsms = wmi().instancesOf("Msvm_VirtualSystemManagementService").ItemIndex(0);
var newVM = wmi().Get("Msvm_VirtualSystemSettingData").SpawnInstance_();
newVM.ElementName = vpsName;
newVM.Version = "8.3"; // 坑:非管理员权限时,版本号必填且格式必须正确,否则 4096 错误
newVM.ConfigurationDataRoot = sys.dir.vpsRoot; // 坑:操作账号必须有读写权限,否则第二次请求报 4096
var inParam = vsms.Methods_("DefineSystem").InParameters.SpawnInstance_();
inParam.SystemSettings = newVM.GetText_(2); // 需要去官方文档查询参数名
var outParam = vsms.ExecMethod_("DefineSystem", inParam);
var code = outParam.ReturnValue;
if(code != 0) return { code: code, err: "请检查 VPS 参数" };
newVM = wmi().Get(outParam.ResultingSystem); // 得到新创建的虚拟机
return { Name: newVM.Name, ElementName: newVM.ElementName, ResultingSystem: outParam.ResultingSystem };
}
function(vhdName, system) {
if(!vhdName) vhdName = form("vhdName") || "NewVHD";
if(!system) system = (form("system") || "alpine").toLowerCase();
system = sys.source[system];
if(!system) return { err: "不支持的系统" };
var rs = wmi().Get("Msvm_VirtualHardDiskSettingData").SpawnInstance_();
rs.Format = 3; // 2: VHD, 3: VHDX, 4: VHDSet
rs.Type = 4; // 2: 固定大小, 3: 动态, 4: 差分硬盘
rs.ParentPath = sys.dir.vhdRoot + system;
rs.Path = sys.dir.vhdRoot + "\\Free\\" + vhdName + ".vhdx";
var ims = wmi().instancesOf("Msvm_ImageManagementService").ItemIndex(0);
var inParam = ims.Methods_("CreateVirtualHardDisk").InParameters.SpawnInstance_();
inParam.VirtualDiskSettingData = rs.GetText_(2);
var outParam = ims.ExecMethod_("CreateVirtualHardDisk", inParam);
// 如果返回 32773,那就是参数错误。异步操作,会返回4096。
if(outParam.ReturnValue != 4096) return { code: outParam.ReturnValue, err: "请检查硬盘参数" };
var job = wmi().Get(outParam.Job);
return { InstanceID: job.InstanceID, Description: job.Description, StatusDescriptions: job.StatusDescriptions };
}
function(vmName, vhdPath) {
if(!vmName) vmName = form("vmName");
if(!vhdPath) vhdPath = form("vhdPath");
dbg().trace([ vmName, vhdPath ]);
// 查找 IDE 存储控制器
var ide = wmi().execQuery("select * from Msvm_ResourceAllocationSettingData where ResourceType=5 and InstanceID like 'Microsoft:" + vmName + "%' and Address=0");
if(!ide.Count) return { err: "未找到 IDE0 存储控制器" };
// 向IDE控制器添加驱动器
var drv = wmi().Get("Msvm_ResourceAllocationSettingData").SpawnInstance_(); // 坑:文档上是 CIM,实际必须用Msvm
drv.AddressOnParent = "0"; // IDE0 的 0 号插槽
drv.ResourceType = 17; // 硬盘驱动器
drv.ResourceSubType = "Microsoft:Hyper-V:Synthetic Disk Drive"; // 坑:Type 和 SubType 两个都必须提供!
drv.Parent = ide.ItemIndex(0).Path_.Path;
var hyper = wmi().instancesOf("Msvm_VirtualSystemManagementService").ItemIndex(0);
var inParam = hyper.Methods_("AddResourceSettings").InParameters.SpawnInstance_();
var vps = wmi().execQuery("select * from CIM_ComputerSystem where Name='" + vmName + "'");
inParam.AffectedConfiguration = vps.ItemIndex(0).Path_.Path;
inParam.ResourceSettings = [ drv.GetText_(2) ];
var outParam = hyper.ExecMethod_("AddResourceSettings", inParam);
if(outParam.ReturnValue == 4096) return { code: outParam.ReturnValue, err: "硬盘驱动器参数可能有问题。", Job: outParam.Job };
if(outParam.ReturnValue) return { code: outParam.ReturnValue, err: "添加驱动器失败" };
// 向硬盘驱动添加虚拟硬盘
var vhd = wmi().Get("Msvm_ResourceAllocationSettingData").SpawnInstance_();
vhd.ResourceType = 31;
vhd.ResourceSubType = "Microsoft:Hyper-V:Virtual Hard Disk";
vhd.HostResource = [ vhdPath ];
vhd.Parent = outParam.ResultingResourceSettings[0];
inParam = hyper.Methods_("AddResourceSettings").InParameters.SpawnInstance_();
inParam.AffectedConfiguration = vps.ItemIndex(0).Path_.Path;
inParam.ResourceSettings = [ vhd.GetText_(2) ];
outParam = hyper.ExecMethod_("AddResourceSettings", inParam);
if(outParam.ReturnValue == 4096) return { code: outParam.ReturnValue, err: "硬盘映像参数可能有问题。", Job: outParam.Job };
if(outParam.ReturnValue) return { code: outParam.ReturnValue, err: "添加硬盘映像失败" };
return { code: 0, msg: "硬盘附加成功" };
}
function(vpsName, switchName) {
if(!vpsName) vpsName = form("vpsName");
if(!switchName) switchName = form("switchName") || "Default Switch";
var vps = wmi().execQuery("select * from CIM_ComputerSystem where Name='" + vpsName + "'");
if(!vps.Count) return { err: "没有找到虚拟机" };
var sw = wmi().execQuery("select * from Msvm_VirtualEthernetSwitch where ElementName='" + switchName + "'");
if(!sw.Count) return { err: "没有找到交换机" };
var vsms = wmi().InstancesOf("Msvm_VirtualSystemManagementService").ItemIndex(0); // 用于操作虚拟机的工具
// 装网卡
var sep = wmi().Get("Msvm_SyntheticEthernetPortSettingData.InstanceID='Microsoft:Definition\\6A45335D-4C3A-44B7-B61F-C9808BBDF8ED\\Default'");
var inParam = vsms.Methods_("AddResourceSettings").InParameters.SpawnInstance_();
inParam.AffectedConfiguration = vps.ItemIndex(0).Path_.Path;
inParam.ResourceSettings = [ sep.GetText_(2) ];
var outParam = vsms.ExecMethod_("AddResourceSettings", inParam);
var code = outParam.ReturnValue;
if(code == 4096) return { code: 4096, err: "正在操作", Job: outParam.Job };
if(code != 0) return { err: "以太网适配器参数可能有错", code: outParam.ReturnValue };
// 插网线
var cfg = wmi().Get("Msvm_EthernetPortAllocationSettingData.InstanceID='Microsoft:Definition\\72027ECE-E44A-446E-AF2B-8D8C4B8A2279\\Default'");
cfg.Parent = outParam.ResultingResourceSettings[0];
cfg.HostResource = [ sw.ItemIndex(0).Path_.Path ];
var code = vsms.AddResourceSettings(vps.ItemIndex(0).Path_.Path, [ cfg.GetText_(2) ]);
if(code != 0) return { err: "网卡设置参数可能有错", code: code };
return { msg: "以太网适配器附加成功", Path: cfg.Parent };
}
function(vmName) {
if(!vmName) vmName = form("vmName");
var vps = wmi().execQuery("select * from CIM_System where Name='" + vmName + "'");
if(!vps.Count) return { err: "没有找到虚拟机" };
var state = vps.ItemIndex(0).EnabledState;
if(state != 3) return { code: 0, err: "当前状态[" + state + "]暂时不支持开机" };
var code = vps.ItemIndex(0).RequestStateChange(2);
if(code != 4096) return { err: "操作失败", code: code };
return { code: code, msg: "命令发送成功" };
}
function(vmName, force) {
if(!vmName) vmName = form("vmName");
if(!force) force = form("force");
var vps = wmi().execQuery("select * from CIM_System where Name='" + vmName + "'");
if(!vps.Count) return { err: "没有找到虚拟机" };
var state = vps.ItemIndex(0).EnabledState;
if(state != 2) return { code: 0, err: "当前状态[" + state + "]暂时不支持关机" };
var code = vps.ItemIndex(0).RequestStateChange(force == 1 ? 3 : 4);
if(code != 4096) return { err: "操作失败", code: code };
return { code: code, msg: "命令发送成功" };
}
function() {
var rs = wmi().execQuery("select * from CIM_ResourceAllocationSettingData where InstanceID like 'Microsoft:E006EC0E-E761-4583-A554-B1F8644E436C%'");
var arr = wmiToArr(rs, "Access Address AddressOnParent AllocationUnits AutomaticAllocation AutomaticDeallocation CachingMode Caption Connection ConsumerVisibility Description ElementName HostExtentName HostExtentNameFormat HostExtentNameNamespace HostExtentStartingAddress HostResource HostResourceBlockSize IgnoreFlushes InstanceID IOPSAllocationUnits IOPSLimit IOPSReservation Limit MappingBehavior OtherHostExtentNameFormat OtherHostExtentNameNamespace OtherResourceType Parent PersistentReservationsSupported PoolID Reservation ResourceSubType ResourceType SnapshotId StorageQoSPolicyID VirtualQuantity VirtualQuantityUnits VirtualResourceBlockSize Weight WriteHardeningMethod");
return arr;
}