Files
cloudpods/pkg/hostman/guestfs/fsdriver/winscripts.go
T
2019-09-26 22:56:09 +08:00

521 lines
15 KiB
Go

// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package fsdriver
const WinScriptChangePassword = `
$username = $args[0]
$passwd = $args[1]
$loghash = $args[2]
$logpath = $args[3]
Function ChangePassword($u, $p) {
$admin = [adsi]("WinNT://./$($u), user")
$succ = 0
$tried = 0
$max_tries = 10
while (($succ -eq 0) -and ($tried -lt $max_tries)) {
Try {
$admin.psbase.invoke("SetPassword", $p)
$admin.psbase.CommitChanges()
$succ = 1
} Catch {
Start-Sleep -s 1
}
$tried = $tried + 1
}
}
if ($username -and $passwd) {
if ($logpath) {
"starting $loghash" | Out-File $logpath -Append -Encoding Default
ChangePassword $username $passwd 2>&1 | Out-File $logpath -Append -Encoding Default
} else {
ChangePassword $username $passwd 2>&1 | Out-Null
}
}
`
const WinScriptMountDisk = `
var MTW_GLOBAL_FSO = new ActiveXObject('Scripting.FileSystemObject');
var MTW_SCRIPT_PATH = mtw_gen_script_path();
var MTW_DEBUG_STREAM = null;
function mtw_create_shell() {
return new ActiveXObject('WScript.Shell');
}
function mtw_gen_script_path() {
var fso = MTW_GLOBAL_FSO;
var folder = fso.GetSpecialFolder(2); // TemporaryFolder
var folder_path = folder + '';
var script_name = [];
if (!/[\\\/]$/.test(folder_path)) {
folder_path += '\\';
}
for (var i = 0; i < 5; i++) {
script_name.push(mtw_gen_random_str(6));
}
return folder_path + script_name.join('-');
}
function mtw_gen_random_str(length) {
var offset, result = [];
var charcode_base = 'A'.charCodeAt(0);
for (var i = 0; i < length; i++) {
offset = Math.floor(Math.random() * 26);
result.push(String.fromCharCode(charcode_base + offset));
}
return result.join('');
}
function mtw_prepare_debug(file_path) {
var fso = new ActiveXObject('Scripting.FileSystemObject');
var stream = fso.OpenTextFile(file_path, 8, true); // 8: ForAppending
stream.WriteLine('');
stream.WriteLine('================ ' + new Date() + ' ================');
stream.WriteLine('');
MTW_DEBUG_STREAM = stream;
}
function mtw_append_debug(cmd_lines, result_lines) {
var i, len, stream = MTW_DEBUG_STREAM;
if (!stream) return;
stream.WriteLine('');
stream.WriteLine('---------- script:');
for (i = 0, len = cmd_lines.length; i < len; i++) {
stream.WriteLine(cmd_lines[i]);
}
stream.WriteLine('---------- result:');
for (i = 0, len = result_lines.length; i < len; i++) {
stream.WriteLine(result_lines[i]);
}
}
function mtw_execute_diskpart(cmd_lines) {
var result_lines = [];
var fso = MTW_GLOBAL_FSO;
var stream, shell, exec_cmd;
cmd_lines.push('exit');
stream = fso.CreateTextFile(MTW_SCRIPT_PATH, true);
for (var i = 0, len = cmd_lines.length; i < len; i++) {
stream.WriteLine(cmd_lines[i]);
}
stream.close();
shell = mtw_create_shell();
exec_cmd = shell.Exec('diskpart /s ' + MTW_SCRIPT_PATH);
while (exec_cmd.Status == 0) {
WScript.Sleep(100);
}
stream = exec_cmd.StdOut;
while (!stream.AtEndOfStream) {
result_lines.push(stream.ReadLine());
}
fso.DeleteFile(MTW_SCRIPT_PATH);
mtw_append_debug(cmd_lines, result_lines);
return result_lines;
}
function mtw_get_disk_list() {
var result_lines, line, match, disk_no;
var disk_list = [];
result_lines = mtw_execute_diskpart(['list disk']);
for (var i = 0, len = result_lines.length; i < len; i++) {
line = result_lines[i];
/*
Disk ### Status Size Free Dyn Gpt
-------- ------------- ------- ------- --- ---
Disk 0 Online 20 GB 0 B
Disk 1 Offline 10 GB 0 B
*/
match = line.match(/\s([1-9])\s\D+\s[1-9]\d*\s+[GMK]B\s+\d+\s+[GMK]?B/);
if (match) {
disk_no = match[1];
disk_list.push({
'disk_no': disk_no,
'partition_list': mtw_get_partition_list(disk_no)
});
}
}
return disk_list;
}
function mtw_get_partition_list(disk_no) {
var result_lines, line, match, partition_no;
var partition_list = [];
result_lines = mtw_execute_diskpart([
'select disk=' + disk_no,
'list partition'
]);
for (var i = 0, len = result_lines.length; i < len; i++) {
line = result_lines[i];
/*
Partition ### Type Size Offset
------------- ---------------- ------- -------
Partition 1 Primary 9 GB 1024 KB
*/
match = line.match(/\s(\d)\s\D+\s[1-9]\d*\s+[GMK]B\s+\d+\s+[GMK]?B/);
if (match) {
partition_no = match[1];
partition_list.push({
'partition_no': partition_no,
'partition_type': mtw_get_partition_type(disk_no, partition_no)
});
}
}
return partition_list;
}
var MTW_PARTITION_TYPE_NODATA = 'nodata';
var MTW_PARTITION_TYPE_INVALID = 'invalid';
function mtw_get_partition_type(disk_no, partition_no) {
var result_lines, line, match;
var possible_type_list = [];
result_lines = mtw_execute_diskpart([
'select disk=' + disk_no,
'select partition=' + partition_no,
'detail partition'
]);
for (var i = 0, len = result_lines.length; i < len; i++) {
line = result_lines[i];
/*
Partition 1
Type : 06
Hidden: No
Active: No
Offset in Bytes: 1048576
Volume ### Ltr Label Fs Type Size Status Info
---------- --- ----------- ----- ---------- ------- --------- --------
* Volume 3 RAW Partition 9 GB Healthy
*/
match = line.match(/:\s*([0-9a-f]{2})\b/i);
if (match) {
possible_type_list.push(match[1]);
}
}
switch (possible_type_list.length) {
case 0:
return MTW_PARTITION_TYPE_NODATA;
case 1:
return possible_type_list[0];
default:
break;
}
return MTW_PARTITION_TYPE_INVALID;
}
function mtw_get_volume_list(disk_no) {
var result_lines, line, match;
var sep_line_exist = false;
var volume_list = [];
result_lines = mtw_execute_diskpart([
'select disk=' + disk_no,
'detail disk'
]);
for (var i = 0, len = result_lines.length; i < len; i++) {
line = result_lines[i];
/*
Red Hat VirtIO SCSI Disk Device
Disk ID: 0004B605
Type : SCSI
Status : Online
Path : 0
Target : 0
LUN ID : 0
Location Path : PCIROOT(0)#PCI(0600)#SCSI(P00T00L00)
Current Read-only State : No
Read-only : No
Boot Disk : No
Pagefile Disk : No
Hibernation File Disk : No
Crashdump Disk : No
Clustered Disk : No
Volume ### Ltr Label Fs Type Size Status Info
---------- --- ----------- ----- ---------- ------- --------- --------
Volume 3 RAW Partition 9 GB Healthy
*/
if (!sep_line_exist) {
match = line.match(/-+\s+-+\s+-+\s+-+/);
if (match) {
sep_line_exist = true;
}
} else {
match = line.match(/\s(\d)\s.+\s\d+\s+[GMK]?B/);
if (match) {
volume_list.push({'volume_no': match[1]});
}
}
}
return volume_list;
}
function mtw_assign_volume_letter(volume_no_set, letter_offset) {
var result_lines, line, match, i, len;
var volume_no, letter, charcode, charcode_max, letter_set;
var volume_map = {}, volume_shift_list = [], cmd_lines = [];
result_lines = mtw_execute_diskpart(['list volume']);
for (i = 0, len = result_lines.length; i < len; i++) {
line = result_lines[i];
/*
Volume ### Ltr Label Fs Type Size Status Info
---------- --- ----------- ----- ---------- ------- --------- --------
Volume 0 D CD-ROM 0 B No Media
Volume 1 ???? NTFS Partition 100 MB Healthy System
Volume 2 C NTFS Partition 19 GB Healthy Boot
Volume 3 RAW Partition 9 GB Healthy
*/
match = line.match(/\s(\d)\s+([D-Z])\s.+\d+\s+[GMK]?B/i);
if (match) {
volume_no = match[1];
letter = match[2].toUpperCase();
if (volume_map.hasOwnProperty(letter)) {
return false;
}
volume_map[letter] = volume_no;
}
}
charcode = 'D'.charCodeAt(0);
charcode += letter_offset;
letter_set = String.fromCharCode(charcode);
if (volume_map.hasOwnProperty(letter_set) && volume_map[letter_set] == volume_no_set) {
return true;
}
charcode_max = 'Z'.charCodeAt(0);
while (true) {
letter = String.fromCharCode(charcode);
if (!volume_map.hasOwnProperty(letter)) {
break;
}
if (charcode >= charcode_max) {
return false;
}
volume_shift_list.push({
'volume_no': volume_map[letter],
'charcode_next': charcode + 1
});
charcode++;
}
if (volume_shift_list.length > 0) {
volume_shift_list.sort(function(a, b) {
return b.charcode_next - a.charcode_next;
});
for (i = 0, len = volume_shift_list.length; i < len; i++) {
volume_no = volume_shift_list[i].volume_no;
charcode = volume_shift_list[i].charcode_next;
cmd_lines.push(
'select volume=' + volume_no,
'assign letter=' + String.fromCharCode(charcode),
'select partition 1',
'format fs ntfs quick'
);
}
}
cmd_lines.push(
'select volume=' + volume_no_set,
'assign letter=' + letter_set,
'select partition 1',
'format fs ntfs quick'
);
mtw_execute_diskpart(cmd_lines);
return true;
}
function mtw_wait_loop(total_ms, step_ms, callback) {
while (true) {
if (callback()) {
break;
}
if (total_ms < step_ms) {
break;
}
total_ms -= step_ms;
WScript.Sleep(step_ms);
}
}
function mtw_get_disk_list_wait() {
var disk_list_ret = [];
/* http://support.microsoft.com/kb/870912 */
mtw_wait_loop(5000, 500, function() {
var i, j, disk_list, disk, partition;
disk_list = mtw_get_disk_list();
for (i = 0; i < disk_list.length; i++) {
disk = disk_list[i];
for (j = 0; j < disk.partition_list.length; j++) {
partition = disk.partition_list[j];
if (partition.partition_type == MTW_PARTITION_TYPE_NODATA) {
return false;
}
}
}
disk_list_ret = disk_list;
return true;
});
return disk_list_ret;
}
function mtw_get_volume_list_wait(disk_no) {
var volume_list_ret = [];
mtw_wait_loop(5000, 500, function() {
var volume_list = mtw_get_volume_list(disk_no);
if (volume_list.length > 0) {
volume_list_ret = volume_list;
return true;
}
return false;
});
return volume_list_ret;
}
function mtw_mount_disk() {
var disk_list, disk_list_mounted, disk, partition, volume_list;
var do_mount, do_create, do_delete;
var cmd_lines, letter_offset = 0;
disk_list = mtw_get_disk_list_wait();
disk_list_mounted = [];
for (var i = 0, len = disk_list.length; i < len; i++) {
disk = disk_list[i];
partition = null;
do_mount = do_create = do_delete = false;
if (disk.partition_list.length == 0) {
do_mount = true;
do_create = true;
} else if (disk.partition_list.length == 1) {
partition = disk.partition_list[0];
switch (partition.partition_type) {
case '06': // DOS 3.31+ 16-bit FAT (over 32M)
case '07': // Windows NT NTFS
do_mount = true;
break;
case '83': // Linux native partition
do_mount = true;
do_delete = true;
do_create = true;
break;
default:
break;
}
}
if (!do_mount) {
continue;
}
cmd_lines = [
'select disk=' + disk.disk_no,
'online disk',
'attributes disk clear readonly'
];
mtw_execute_diskpart(cmd_lines);
if (do_create) {
cmd_lines = ['select disk=' + disk.disk_no];
if (partition && do_delete) {
cmd_lines.push(
'select partition=' + partition.partition_no,
'delete partition'
);
}
cmd_lines.push('create partition primary');
mtw_execute_diskpart(cmd_lines);
}
disk_list_mounted.push(disk);
}
for (i = 0, len = disk_list_mounted.length; i < len; i++) {
disk = disk_list_mounted[i];
if (i == 0) {
volume_list = mtw_get_volume_list_wait(disk.disk_no);
} else {
volume_list = mtw_get_volume_list(disk.disk_no);
}
if (volume_list.length == 1) {
mtw_assign_volume_letter(volume_list[0].volume_no, letter_offset);
letter_offset += 1;
}
}
}
function mtw_extend_c() {
cmd_lines = [
'select volume c',
'extend',
];
mtw_execute_diskpart(cmd_lines);
mtw_append_debug(["extend c"], ["success"]);
}
function mtw_main() {
var exec_helper, args = WScript.Arguments, debug_path = '';
for (var i = 0, len = args.length; i < len; i++) {
if (args(i) == '--debug') {
if (i < len) {
i += 1;
debug_path = args(i);
}
}
}
if (debug_path) {
mtw_prepare_debug(debug_path);
}
/* http://support.microsoft.com/kb/937252 */
exec_helper = mtw_create_shell().Exec('diskpart');
try {
mtw_extend_c();
} catch (e) {
mtw_append_debug(["extend c"], ["failed"]);
}
try {
mtw_mount_disk();
} catch (e) {
// nothing
}
exec_helper.StdIn.WriteLine('exit');
while (exec_helper.Status == 0) {
WScript.Sleep(100);
}
}
mtw_main();
`