Hyper-V 管理平台 API 文档

【VPS 列表页面】
ResourceType: { 5: IDE, 10: 网络适配器, 17: 硬盘驱动器, 31: 硬盘, 33: 以太网连接设置 }
NewVps: 新建虚拟机
@form { vpsName, system, cpu, mem }
内存 mem 单位为 GB
[检视源码]
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" };
}
DropVps: 删除虚拟机
@form { vpsName }
此 vpsName 为虚拟机友好名称
[检视源码]
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 + "】删除完成" };
}
ServiceStatus: 服务运行状态
@form { }
[检视源码]
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;
}
JobQuery: 查询任务
@form { jobPath }
[检视源码]
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 };
}
VpsList: VPS 列表
@form { }
[检视源码]
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;
}
VpsCreate: 第二种创建虚拟机的方式
@form { vpsName }
此 vpsName 为友好名称
[检视源码]
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 };
}
VHDCreate: 新建 VHD
@form { vhdName, system }
[检视源码]
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 };
}
VpsAttachVhd: 挂载 VHD
@form { vmName, vhdPath }
vmName 为虚拟机 GUID
[检视源码]
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: "硬盘附加成功" };
}
VpsAttachEth: 挂载网卡
@form { vpsName, switchName }
vpsName 为 虚拟机 GUID
switchName 默认为“Default Switch”
[检视源码]
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 };
}
StartUp: 虚拟机开机
@form { vmName }
vmName 为虚拟机 GUID
[检视源码]
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: "命令发送成功" };
}
Shutdown: 虚拟机关机
@form { vmName, force }
vmName 为虚拟机 GUID
force=1时 强制关机
[检视源码]
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: "命令发送成功" };
}
TestList: 测试数组
@form { }
[检视源码]
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;
}
参数录入
执行
取消