Merge pull request #1014 in YUNIONIO/onecloud from ~WANYAOQI/onecloud:feature/wyq/host-server-v2 to release/2.6.0

* commit '20dab1154d04a0e06e7386d3c1678e414c87fda0':
  win driver
This commit is contained in:
邱剑
2019-01-31 10:25:34 +08:00
15 changed files with 1166 additions and 55 deletions
+1 -1
View File
@@ -1422,7 +1422,7 @@ func (s *SBaremetalServer) DoDeploy(term *ssh.Client, data jsonutils.JSONObject,
if resetPassword && len(password) == 0 {
password = seclib.RandomPassword(12)
}
deployInfo := guestfs.NewDeployInfo(publicKey, deploys, password, isInit, true, o.Options.LinuxDefaultRootUser)
deployInfo := guestfs.NewDeployInfo(publicKey, deploys, password, isInit, true, o.Options.LinuxDefaultRootUser, o.Options.WindowsDefaultAdminUser)
return s.deployFs(term, deployInfo)
}
+2
View File
@@ -26,6 +26,8 @@ type BaremetalOptions struct {
DefaultIpmiPassword string `help:"Default IPMI passowrd"`
DefaultStrongIpmiPassword string `help:"Default strong IPMI passowrd"`
WindowsDefaultAdminUser bool `default:"true" help:"Default account for Windows system is Administrator"`
}
var (
+17 -13
View File
@@ -15,12 +15,13 @@ import (
)
type SDeployInfo struct {
publicKey *sshkeys.SSHKeys
deploys []jsonutils.JSONObject
password string
isInit bool
enableTty bool
defaultRootUser bool
publicKey *sshkeys.SSHKeys
deploys []jsonutils.JSONObject
password string
isInit bool
enableTty bool
defaultRootUser bool
windowsDefaultAdminUser bool
}
func NewDeployInfo(
@@ -30,14 +31,16 @@ func NewDeployInfo(
isInit bool,
enableTty bool,
defaultRootUser bool,
windowsDefaultAdminUser bool,
) *SDeployInfo {
return &SDeployInfo{
publicKey: publicKey,
deploys: deploys,
password: password,
isInit: isInit,
enableTty: enableTty,
defaultRootUser: defaultRootUser,
publicKey: publicKey,
deploys: deploys,
password: password,
isInit: isInit,
enableTty: enableTty,
defaultRootUser: defaultRootUser,
windowsDefaultAdminUser: windowsDefaultAdminUser,
}
}
@@ -176,7 +179,8 @@ func DeployGuestFs(
}
}
if len(deployInfo.password) > 0 {
if account := rootfs.GetLoginAccount(partition, deployInfo.defaultRootUser); len(account) > 0 {
if account := rootfs.GetLoginAccount(partition,
deployInfo.defaultRootUser, deployInfo.windowsDefaultAdminUser); len(account) > 0 {
ret.Set("account", jsonutils.NewString(account))
if err = rootfs.DeployPublicKey(partition, account, deployInfo.publicKey); err != nil {
return nil, fmt.Errorf("DeployPublicKey: %v", err)
+1 -1
View File
@@ -17,6 +17,6 @@ func init() {
rootfsDrivers = append(rootfsDrivers, linuxFsDrivers...)
//rootfsDrivers = append(rootfsDrivers, NewMacOSRootFs)
//rootfsDrivers = append(rootfsDrivers, NewEsxiRootFs)
//rootfsDrivers = append(rootfsDrivers, NewWindowsRootFs)
rootfsDrivers = append(rootfsDrivers, NewWindowsRootFs)
//rootfsDrivers = append(rootfsDrivers, NewAndroidRootFs)
}
+2 -1
View File
@@ -9,6 +9,7 @@ import (
)
type IDiskPartition interface {
GetLocalPath(sPath string, caseInsensitive bool) string
FileGetContents(sPath string, caseInsensitive bool) ([]byte, error)
FilePutContents(sPath, content string, modAppend, caseInsensitive bool) error
Exists(sPath string, caseInsensitive bool) bool
@@ -44,7 +45,7 @@ type IRootFsDriver interface {
DeployStandbyNetworkingScripts(part IDiskPartition, nics, nicsStandby []jsonutils.JSONObject) error
DeployUdevSubsystemScripts(IDiskPartition) error
DeployFstabScripts(IDiskPartition, []jsonutils.JSONObject) error
GetLoginAccount(IDiskPartition, bool) string
GetLoginAccount(IDiskPartition, bool, bool) string
DeployPublicKey(IDiskPartition, string, *sshkeys.SSHKeys) error
ChangeUserPasswd(part IDiskPartition, account, gid, publicKey, password string) (string, error)
DeployYunionroot(IDiskPartition, *sshkeys.SSHKeys) error
+1 -1
View File
@@ -60,7 +60,7 @@ func (l *sLinuxRootFs) DeployHosts(rootFs IDiskPartition, hostname, domain strin
return rootFs.FilePutContents(etcHosts, hf.String(), false, false)
}
func (l *sLinuxRootFs) GetLoginAccount(rootFs IDiskPartition, defaultRootUser bool) string {
func (l *sLinuxRootFs) GetLoginAccount(rootFs IDiskPartition, defaultRootUser bool, windowsDefaultAdminUser bool) string {
var selUsr string
if defaultRootUser && rootFs.Exists("/root", false) {
selUsr = ROOT_USER
+419 -3
View File
@@ -1,9 +1,425 @@
package fsdriver
import (
"crypto/md5"
"fmt"
"math/rand"
"path"
"regexp"
"strings"
"syscall"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/onecloud/pkg/cloudcommon/sshkeys"
"yunion.io/x/onecloud/pkg/cloudcommon/types"
"yunion.io/x/onecloud/pkg/hostman/options"
"yunion.io/x/onecloud/pkg/util/fileutils2"
"yunion.io/x/onecloud/pkg/util/netutils2"
"yunion.io/x/onecloud/pkg/util/seclib2"
"yunion.io/x/onecloud/pkg/util/version"
"yunion.io/x/onecloud/pkg/util/winutils"
"yunion.io/x/pkg/utils"
)
const (
TCPIP_PARAM_KEY = `HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters`
BOOT_SCRIPT_PATH = "/Windows/System32/GroupPolicy/Machine/Scripts/Startup/cloudboot.bat"
WIN_BOOT_SCRIPT_PATH = "cloudboot.bat"
)
type SWindowsRootFs struct {
*sGuestRootFsDriver
guestDebugLogPath string
bootScripts string
}
//func NewWindowsRootFs(part IDiskPartition) IRootFsDriver {
//return &SWindowsRootFs{sGuestRootFsDriver: newGuestRootFsDriver(part)}
//}
func NewWindowsRootFs(part IDiskPartition) IRootFsDriver {
seq := []byte{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'}
suffix := make([]byte, 16)
lenSeq := len(seq)
for i := 0; i < 16; i++ {
suffix[i] = seq[rand.Intn(lenSeq)]
}
return &SWindowsRootFs{
sGuestRootFsDriver: newGuestRootFsDriver(part),
guestDebugLogPath: `%SystemRoot%\mdbg_` + string(suffix),
}
}
func (w *SWindowsRootFs) IsFsCaseInsensitive() bool {
return true
}
func (w *SWindowsRootFs) GetName() string {
return "Windows"
}
func (w *SWindowsRootFs) DeployPublicKey(IDiskPartition, string, *sshkeys.SSHKeys) error {
return nil
}
func (w *SWindowsRootFs) RootSignatures() []string {
return []string{
"/program files", "/windows",
"/windows/system32/drivers/etc", "/windows/system32/config",
"/windows/system32/config/sam",
"/windows/system32/config/software",
"/windows/system32/config/system",
}
}
func (w *SWindowsRootFs) GetReleaseInfo(IDiskPartition) *SReleaseInfo {
confPath := w.rootFs.GetLocalPath("/windows/system32/config", true)
tool := winutils.NewWinRegTool(confPath)
if tool.CheckPath() {
distro := tool.GetProductName()
version := tool.GetVersion()
arch := tool.GetArch()
lan := tool.GetInstallLanguage()
return &SReleaseInfo{distro, version, arch, lan}
} else {
return nil
}
}
func (w *SWindowsRootFs) GetLoginAccount(rootFs IDiskPartition, defaultRootUser bool, windowsDefaultAdminUser bool) string {
confPath := w.rootFs.GetLocalPath("/windows/system32/config", true)
tool := winutils.NewWinRegTool(confPath)
users := tool.GetUsers()
admin := "Administrator"
selUsr := ""
if w.IsWindows10() {
delete(users, admin)
}
if _, ok := users[admin]; ok && windowsDefaultAdminUser {
selUsr = admin
} else {
for user, _ := range users {
if user != admin && (len(selUsr) == 0 || len(selUsr) > len(user)) {
selUsr = user
}
}
if _, ok := users[admin]; ok && len(selUsr) == 0 {
selUsr = admin
}
}
if len(selUsr) > 0 {
if _, ok := users[selUsr]; !ok {
tool.UnlockUser(selUsr)
}
}
return selUsr
}
func (w *SWindowsRootFs) IsWindows10() bool {
info := w.GetReleaseInfo(nil)
if info != nil && strings.HasPrefix(info.Distro, "Windows 10 ") {
return true
}
return false
}
func (w *SWindowsRootFs) GetOs() string {
return "Windows"
}
func (w *SWindowsRootFs) appendGuestBootScript(content string) string {
w.bootScripts += "\r\n" + content
return w.bootScripts
}
func (w *SWindowsRootFs) regAdd(path, key, val, regType string) string {
return fmt.Sprintf(`REG ADD %s /V "%s" /D "%s" /T %s /F`, path, key, val, regType)
}
func (w *SWindowsRootFs) putGuestScriptContents(spath, content string) error {
contentArr := []string{}
contentLen := len(content)
var j = 0
for i := 1; i < contentLen; i++ {
if content[i] == '\n' && content[i-1] != '\r' {
contentArr = append(contentArr, content[j:i])
j = i + 1
}
}
if j < contentLen {
contentArr = append(contentArr, content[j:])
}
content = strings.Join(contentArr, "\r\n")
return w.rootFs.FilePutContents(spath, content, false, true)
}
func (w *SWindowsRootFs) DeployHostname(part IDiskPartition, hostname, domain string) error {
bootScript := strings.Join([]string{
`set HOSTNAME_SCRIPT=%SystemRoot%\hostnamecfg.bat`,
`if exist %HOSTNAME_SCRIPT% (`,
` call %HOSTNAME_SCRIPT%`,
` del %HOSTNAME_SCRIPT%`,
`)`,
}, "\r\n")
w.appendGuestBootScript(bootScript)
lines := []string{}
for k, v := range map[string]string{
"Hostname": hostname,
"Domain": domain,
"NV Hostname": hostname,
"NV Domain": domain,
} {
lines = append(lines, w.regAdd(TCPIP_PARAM_KEY, k, v, "REG_SZ"))
}
hostScripts := strings.Join(lines, "\r\n")
return w.putGuestScriptContents("/windows/hostnamecfg.bat", hostScripts)
}
func (w *SWindowsRootFs) DeployHosts(part IDiskPartition, hn, domain string, ips []string) error {
var (
ETC_HOSTS = "/windows/system32/drivers/etc/hosts"
oldHf = ""
)
if w.rootFs.Exists(ETC_HOSTS, true) {
oldHfBytes, err := w.rootFs.FileGetContents(ETC_HOSTS, true)
if err != nil {
log.Errorln(err)
return err
}
oldHf = string(oldHfBytes)
}
hf := fileutils2.HostsFile{}
hf.Parse(oldHf)
hf.Add("127.0.0.1", "localhost")
for _, ip := range ips {
hf.Add(ip, fmt.Sprintf("%s.%s", hn, domain), hn)
}
return w.rootFs.FilePutContents(ETC_HOSTS, hf.String(), false, true)
}
func (w *SWindowsRootFs) DeployNetworkingScripts(rootfs IDiskPartition, nics []jsonutils.JSONObject) error {
mainNic, err := netutils2.GetMainNic(nics)
if err != nil {
return err
}
mainIp := ""
if mainNic != nil {
mainIp, _ = mainNic.GetString("ip")
}
bootScript := strings.Join([]string{
`set NETCFG_SCRIPT=%SystemRoot%\netcfg.bat`,
`if exist %NETCFG_SCRIPT% (`,
` call %NETCFG_SCRIPT%`,
` del %NETCFG_SCRIPT%`,
`)`,
}, "\r\n")
w.appendGuestBootScript(bootScript)
lines := []string{
"@echo off",
w.MakeGuestDebugCmd("netcfg step 1"),
"setlocal enableDelayedExpansion",
`for /f "delims=" %%a in (\'getmac /fo csv /nh /v\') do (`,
` set line=%%a&set line=!line:"=,!`,
` for /f "delims=,,, tokens=1,3" %%b in ("!line!") do (`,
}
for _, nic := range nics {
snic := &types.SServerNic{}
if err := nic.Unmarshal(snic); err != nil {
log.Errorln(err)
return err
}
mac := snic.Mac
mac = strings.Replace(strings.ToUpper(mac), ":", "-", -1)
lines = append(lines, fmt.Sprintf(` if "%%%%c" == "%s" (`, mac))
if jsonutils.QueryBoolean(nic, "manual", false) {
netmask := netutils2.Netlen2Mask(snic.Masklen)
cfg := fmt.Sprintf(` netsh interface ip set address "%%%%b" static %s %s`, snic.Ip, netmask)
if len(snic.Gateway) > 0 && snic.Ip == mainIp {
cfg += fmt.Sprintf(" %s", snic.Gateway)
}
lines = append(lines, cfg)
routes := [][]string{}
netutils2.AddNicRoutes(&routes, snic, mainIp, len(nics), options.HostOptions.PrivatePrefixes)
for _, r := range routes {
lines = append(lines, fmt.Sprintf(` netsh interface ip add route %s "%%%%b" %s`, r[0], r[1]))
}
dnslist := netutils2.GetNicDns(snic)
if len(dnslist) > 0 {
lines = append(lines, fmt.Sprintf(
` netsh interface ip set dns name="%%%%b" source=static addr=%s ddns=disabled suffix=interface`, dnslist[0]))
if len(dnslist) > 1 {
for i := 1; i < len(dnslist); i++ {
lines = append(lines, fmt.Sprintf(` netsh interface ip add dns "%%%%b" %s index=%d`, dnslist[i], i+1))
}
}
}
if len(snic.Domain) > 0 && snic.Ip == mainIp {
lines = append(lines, w.regAdd(TCPIP_PARAM_KEY, "SearchList", snic.Domain, "REG_SZ"))
}
} else {
lines = append(lines, ` netsh interface ip set address "%%b" dhcp`)
lines = append(lines, ` netsh interface ip set dns "%%b" dhcp`)
}
lines = append(lines, ` )`)
}
lines = append(lines, ` )`)
lines = append(lines, `)`)
lines = append(lines, w.MakeGuestDebugCmd("netcfg step 2"))
lines = append(lines, `netsh advfirewall firewall set rule group=\"remote desktop\" new enable=yes`)
netScript := strings.Join(lines, "\r\n")
return w.putGuestScriptContents("/windows/netcfg.bat", netScript)
}
func (w *SWindowsRootFs) MakeGuestDebugCmd(content string) string {
mark := "============="
content = regexp.MustCompile(`(["^&<>|])`).ReplaceAllString(content, "^$1")
return fmt.Sprintf("echo %s %s %s >> %s", mark, content, mark, w.guestDebugLogPath)
}
func (w *SWindowsRootFs) prependGuestBootScript(content string) {
w.bootScripts = content + "\r\n" + w.bootScripts
}
func (w *SWindowsRootFs) PrepareFsForTemplate(IDiskPartition) error {
for _, f := range []string{"/Pagefile.sys", "/Hiberfil.sys", "/Swapfile.sys"} {
if w.rootFs.Exists(f, true) {
w.rootFs.Remove(f, true)
}
}
return nil
}
func (w *SWindowsRootFs) CommitChanges(part IDiskPartition) error {
confPath := part.GetLocalPath("/windows/system32/config", true)
tool := winutils.NewWinRegTool(confPath)
tool.CheckPath()
tool.EnableRdp()
tool.InstallGpeditStartScript(WIN_BOOT_SCRIPT_PATH)
if err := w.rootFs.Mkdir(path.Dir(BOOT_SCRIPT_PATH), syscall.S_IRUSR|syscall.S_IWUSR|syscall.S_IXUSR, true); err != nil {
return err
}
return w.rootFs.FilePutContents(BOOT_SCRIPT_PATH, w.bootScripts, false, false)
}
func (w *SWindowsRootFs) ChangeUserPasswd(part IDiskPartition, account, gid, publicKey, password string) (string, error) {
rinfo := w.GetReleaseInfo(part)
confPath := part.GetLocalPath("/windows/system32/config", true)
tool := winutils.NewWinRegTool(confPath)
tool.CheckPath()
success := false
if rinfo != nil && version.GE(rinfo.Version, "6.1") {
success = w.deployPublicKeyByGuest(account, password)
} else {
success = tool.ChangePassword(account, password) == nil
}
var (
secret string
err error
)
if success {
if len(publicKey) > 0 {
secret, err = seclib2.EncryptBase64(publicKey, password)
if err != nil {
return "", err
}
} else {
secret, err = utils.EncryptAESBase64(gid, password)
if err != nil {
return "", err
}
}
if rinfo != nil && strings.Contains(rinfo.Distro, "Windows XP") {
if len(tool.GetLogontype()) > 0 {
tool.SetLogontype("0x0")
}
}
} else {
log.Errorf("Filaed Password %s", account)
}
defUanme := tool.GetDefaultAccount()
if len(defUanme) > 0 && defUanme != account {
tool.SetDefaultAccount(account)
}
return secret, nil
}
func (w *SWindowsRootFs) deployPublicKeyByGuest(uname, passwd string) bool {
if !w.deploySetupCompleteScripts(uname, passwd) {
return false
}
bootScript := strings.Join([]string{
`set CHANGE_PASSWD_SCRIPT=%SystemRoot%\chgpwd.bat`,
`if exist %CHANGE_PASSWD_SCRIPT% (`,
` call %CHANGE_PASSWD_SCRIPT%`,
` del %CHANGE_PASSWD_SCRIPT%`,
`)`,
}, "\r\n")
w.prependGuestBootScript(bootScript)
logPath := w.guestDebugLogPath
chksum := md5.Sum([]byte(passwd + logPath[(len(logPath)-10):]))
chgpwdScript := strings.Join([]string{
w.MakeGuestDebugCmd("change password step 1"),
strings.Join([]string{
`%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe`,
` -executionpolicy bypass %SystemRoot%\chgpwd.ps1`,
fmt.Sprintf(" %s %s %s %s", uname, passwd, chksum, logPath),
}, ""),
`del %SystemRoot%\chgpwd.ps1`,
w.MakeGuestDebugCmd("change password step 2"),
}, "\r\n")
if w.putGuestScriptContents("/windows/chgpwd.bat", chgpwdScript) != nil {
return false
}
if w.putGuestScriptContents("/windows/chgpwd.ps1", WinScriptChangePassword) != nil {
return false
}
return true
}
func (w *SWindowsRootFs) deploySetupCompleteScripts(uname, passwd string) bool {
SETUP_SCRIPT_PATH := "/Windows/Setup/Scripts/SetupComplete.cmd"
if !w.rootFs.Exists(path.Dir(SETUP_SCRIPT_PATH), true) {
w.rootFs.Mkdir(path.Dir(SETUP_SCRIPT_PATH),
syscall.S_IRUSR|syscall.S_IWUSR|syscall.S_IXUSR, true)
}
if w.putGuestScriptContents("/windows/chgpwd_setup.ps1", WinScriptChangePassword) != nil {
return false
}
cmds := []string{
`%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe -executionpolicy bypass %SystemRoot%\chgpwd_setup.ps1 '` +
fmt.Sprintf("%s %s", uname, passwd),
"Net stop wuauserv",
}
for _, v := range [][3]string{
[3]string{"AUOptions", "REG_DWORD", "3"},
[3]string{"NoAutoUpdate", "REG_DWORD", "0"},
[3]string{"ScheduledInstallDay", "REG_DWORD", "0"},
[3]string{"ScheduledInstallTime", "REG_DWORD", "4"},
[3]string{"AutoInstallMinorUpdates", "REG_DWORD", "1"},
[3]string{"NoAutoRebootWithLoggedOnUsers", "REG_DWORD", "1"},
[3]string{"IncludeRecommendedUpdates", "REG_DWORD", "0"},
[3]string{"EnableFeaturedSoftware", "REG_DWORD", "1"},
} {
cmds = append(cmds, `REG ADD "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update" /v %s /t %s /d %s /f`,
v[0], v[1], v[2])
}
cmds = append(cmds, "Net start wuauserv")
cmds = append(cmds, "wuauclt /detectnow")
cmds = append(cmds, `del %SystemRoot%\chgpwd_setup.ps1`)
cmds = append(cmds, `del %SystemRoot%\Setup\Scripts\SetupComplete.cmd`)
if w.putGuestScriptContents(SETUP_SCRIPT_PATH, strings.Join(cmds, "\r\n")) != nil {
return false
}
return true
}
+2 -2
View File
@@ -116,7 +116,7 @@ func (p *SKVMGuestDiskPartition) fsck() error {
if err == nil {
break
} else {
return err
continue
}
}
}
@@ -125,7 +125,7 @@ func (p *SKVMGuestDiskPartition) fsck() error {
}
func (p *SKVMGuestDiskPartition) Exists(sPath string, caseInsensitive bool) bool {
sPath = p.getLocalPath(sPath, caseInsensitive)
sPath = p.GetLocalPath(sPath, caseInsensitive)
if len(sPath) > 0 {
return fileutils2.Exists(sPath)
}
+15 -15
View File
@@ -23,7 +23,7 @@ func (f *SLocalGuestFS) SupportSerialPorts() bool {
return false
}
func (f *SLocalGuestFS) getLocalPath(sPath string, caseInsensitive bool) string {
func (f *SLocalGuestFS) GetLocalPath(sPath string, caseInsensitive bool) string {
var fullPath = f.mountPath
pathSegs := strings.Split(sPath, "/")
for _, seg := range pathSegs {
@@ -51,7 +51,7 @@ func (f *SLocalGuestFS) getLocalPath(sPath string, caseInsensitive bool) string
}
func (f *SLocalGuestFS) Remove(path string, caseInsensitive bool) {
path = f.getLocalPath(path, caseInsensitive)
path = f.GetLocalPath(path, caseInsensitive)
if len(path) > 0 {
os.Remove(path)
}
@@ -60,16 +60,16 @@ func (f *SLocalGuestFS) Remove(path string, caseInsensitive bool) {
func (f *SLocalGuestFS) Mkdir(sPath string, mode int, caseInsensitive bool) error {
segs := strings.Split(sPath, "/")
sPath = ""
pPath := f.getLocalPath("/", caseInsensitive)
pPath := f.GetLocalPath("/", caseInsensitive)
for _, s := range segs {
if len(s) > 0 {
sPath = path.Join(sPath, s)
vPath := f.getLocalPath(sPath, caseInsensitive)
vPath := f.GetLocalPath(sPath, caseInsensitive)
if len(vPath) == 0 {
if err := os.Mkdir(path.Join(pPath, s), os.FileMode(mode)); err != nil {
return err
}
pPath = f.getLocalPath(sPath, caseInsensitive)
pPath = f.GetLocalPath(sPath, caseInsensitive)
} else {
pPath = vPath
}
@@ -79,7 +79,7 @@ func (f *SLocalGuestFS) Mkdir(sPath string, mode int, caseInsensitive bool) erro
}
func (f *SLocalGuestFS) ListDir(sPath string, caseInsensitive bool) []string {
sPath = f.getLocalPath(sPath, caseInsensitive)
sPath = f.GetLocalPath(sPath, caseInsensitive)
if len(sPath) > 0 {
files, err := ioutil.ReadDir(sPath)
if err != nil {
@@ -96,7 +96,7 @@ func (f *SLocalGuestFS) ListDir(sPath string, caseInsensitive bool) []string {
}
func (f *SLocalGuestFS) Cleandir(dir string, keepdir, caseInsensitive bool) error {
sPath := f.getLocalPath(dir, caseInsensitive)
sPath := f.GetLocalPath(dir, caseInsensitive)
if len(sPath) > 0 {
return fileutils2.Cleandir(sPath, keepdir)
}
@@ -104,7 +104,7 @@ func (f *SLocalGuestFS) Cleandir(dir string, keepdir, caseInsensitive bool) erro
}
func (f *SLocalGuestFS) Zerofiles(dir string, caseInsensitive bool) error {
sPath := f.getLocalPath(dir, caseInsensitive)
sPath := f.GetLocalPath(dir, caseInsensitive)
if len(sPath) > 0 {
return fileutils2.Zerofiles(sPath)
}
@@ -149,7 +149,7 @@ func (f *SLocalGuestFS) Passwd(account, password string, caseInsensitive bool) e
}
func (f *SLocalGuestFS) Stat(usrDir string, caseInsensitive bool) os.FileInfo {
sPath := f.getLocalPath(usrDir, caseInsensitive)
sPath := f.GetLocalPath(usrDir, caseInsensitive)
if len(sPath) > 0 {
fileInfo, err := os.Stat(sPath)
if err != nil {
@@ -161,7 +161,7 @@ func (f *SLocalGuestFS) Stat(usrDir string, caseInsensitive bool) os.FileInfo {
}
func (f *SLocalGuestFS) Exists(sPath string, caseInsensitive bool) bool {
sPath = f.getLocalPath(sPath, caseInsensitive)
sPath = f.GetLocalPath(sPath, caseInsensitive)
if len(sPath) > 0 {
return fileutils2.Exists(sPath)
}
@@ -169,7 +169,7 @@ func (f *SLocalGuestFS) Exists(sPath string, caseInsensitive bool) bool {
}
func (f *SLocalGuestFS) Chown(sPath string, uid, gid int, caseInsensitive bool) error {
sPath = f.getLocalPath(sPath, caseInsensitive)
sPath = f.GetLocalPath(sPath, caseInsensitive)
if len(sPath) > 0 {
return os.Chown(sPath, uid, gid)
}
@@ -177,7 +177,7 @@ func (f *SLocalGuestFS) Chown(sPath string, uid, gid int, caseInsensitive bool)
}
func (f *SLocalGuestFS) Chmod(sPath string, mode uint32, caseInsensitive bool) error {
sPath = f.getLocalPath(sPath, caseInsensitive)
sPath = f.GetLocalPath(sPath, caseInsensitive)
if len(sPath) > 0 {
return os.Chmod(sPath, os.FileMode(mode))
}
@@ -196,7 +196,7 @@ func (f *SLocalGuestFS) UserAdd(user string, caseInsensitive bool) error {
}
func (f *SLocalGuestFS) FileGetContents(sPath string, caseInsensitive bool) ([]byte, error) {
sPath = f.getLocalPath(sPath, caseInsensitive)
sPath = f.GetLocalPath(sPath, caseInsensitive)
if len(sPath) > 0 {
return ioutil.ReadFile(sPath)
}
@@ -204,11 +204,11 @@ func (f *SLocalGuestFS) FileGetContents(sPath string, caseInsensitive bool) ([]b
}
func (f *SLocalGuestFS) FilePutContents(sPath, content string, modAppend, caseInsensitive bool) error {
sFilePath := f.getLocalPath(sPath, caseInsensitive)
sFilePath := f.GetLocalPath(sPath, caseInsensitive)
if len(sFilePath) > 0 {
sPath = sFilePath
} else {
dirPath := f.getLocalPath(path.Dir(sPath), caseInsensitive)
dirPath := f.GetLocalPath(path.Dir(sPath), caseInsensitive)
if len(dirPath) > 0 {
sPath = path.Join(dirPath, path.Base(sPath))
}
+13 -13
View File
@@ -69,15 +69,15 @@ func (p *SSHPartition) osMkdirP(dir string, mode uint32) error {
func (p *SSHPartition) Mkdir(sPath string, mode int, caseInsensitive bool) error {
segs := strings.Split(sPath, "/")
sp := ""
pPath := p.getLocalPath("/", caseInsensitive)
pPath := p.GetLocalPath("/", caseInsensitive)
var err error
for _, s := range segs {
if len(s) > 0 {
sp = path.Join(sp, s)
vPath := p.getLocalPath(sp, caseInsensitive)
vPath := p.GetLocalPath(sp, caseInsensitive)
if len(vPath) == 0 {
err = p.osMkdirP(path.Join(pPath, s), uint32(mode))
pPath = p.getLocalPath(sp, caseInsensitive)
pPath = p.GetLocalPath(sp, caseInsensitive)
} else {
pPath = vPath
}
@@ -160,7 +160,7 @@ func (p *SSHPartition) IsMounted() bool {
}
func (p *SSHPartition) Chmod(sPath string, mode uint32, caseI bool) error {
sPath = p.getLocalPath(sPath, caseI)
sPath = p.GetLocalPath(sPath, caseI)
if sPath != "" {
return p.osChmod(sPath, mode)
}
@@ -193,7 +193,7 @@ func (p *SSHPartition) osListDir(path string) ([]string, error) {
return files, nil
}
func (p *SSHPartition) getLocalPath(sPath string, caseI bool) string {
func (p *SSHPartition) GetLocalPath(sPath string, caseI bool) string {
var fullPath = p.mountPath
pathSegs := strings.Split(sPath, "/")
for _, seg := range pathSegs {
@@ -221,7 +221,7 @@ func (p *SSHPartition) getLocalPath(sPath string, caseI bool) string {
}
func (p *SSHPartition) Exists(sPath string, caseInsensitive bool) bool {
sPath = p.getLocalPath(sPath, caseInsensitive)
sPath = p.GetLocalPath(sPath, caseInsensitive)
if len(sPath) > 0 {
return p.osPathExists(sPath)
}
@@ -242,7 +242,7 @@ func (p *SSHPartition) sshFileGetContents(path string) ([]byte, error) {
}
func (p *SSHPartition) FileGetContents(sPath string, caseInsensitive bool) ([]byte, error) {
sPath = p.getLocalPath(sPath, caseInsensitive)
sPath = p.GetLocalPath(sPath, caseInsensitive)
if len(sPath) > 0 {
return p.sshFileGetContents(sPath)
}
@@ -282,11 +282,11 @@ func (p *SSHPartition) sshFilePutContents(sPath, content string, modAppend bool)
}
func (p *SSHPartition) FilePutContents(sPath, content string, modAppend, caseInsensitive bool) error {
sFilePath := p.getLocalPath(sPath, caseInsensitive)
sFilePath := p.GetLocalPath(sPath, caseInsensitive)
if len(sFilePath) > 0 {
sPath = sFilePath
} else {
dirPath := p.getLocalPath(path.Dir(sPath), caseInsensitive)
dirPath := p.GetLocalPath(path.Dir(sPath), caseInsensitive)
if len(dirPath) > 0 {
sPath = path.Join(dirPath, path.Base(sPath))
}
@@ -298,7 +298,7 @@ func (p *SSHPartition) FilePutContents(sPath, content string, modAppend, caseIns
}
func (p *SSHPartition) ListDir(sPath string, caseInsensitive bool) []string {
sPath = p.getLocalPath(sPath, caseInsensitive)
sPath = p.GetLocalPath(sPath, caseInsensitive)
if len(sPath) > 0 {
ret, err := p.osListDir(sPath)
if err != nil {
@@ -317,7 +317,7 @@ func (p *SSHPartition) osChown(sPath string, uid, gid int) error {
}
func (p *SSHPartition) Chown(sPath string, uid, gid int, caseInsensitive bool) error {
sPath = p.getLocalPath(sPath, caseInsensitive)
sPath = p.GetLocalPath(sPath, caseInsensitive)
if len(sPath) == 0 {
return fmt.Errorf("Can't get local path: %s", sPath)
}
@@ -331,7 +331,7 @@ func (p *SSHPartition) osRemove(sPath string) error {
}
func (p *SSHPartition) Remove(sPath string, caseInsensitive bool) {
sPath = p.getLocalPath(sPath, caseInsensitive)
sPath = p.GetLocalPath(sPath, caseInsensitive)
if len(sPath) > 0 {
p.osRemove(sPath)
}
@@ -445,7 +445,7 @@ func (info sFileInfo) Sys() interface{} {
}
func (p *SSHPartition) Stat(sPath string, caseInsensitive bool) os.FileInfo {
sPath = p.getLocalPath(sPath, caseInsensitive)
sPath = p.GetLocalPath(sPath, caseInsensitive)
if len(sPath) == 0 {
return nil
}
+3 -1
View File
@@ -291,7 +291,9 @@ func (m *SGuestManager) GuestDeploy(ctx context.Context, params interface{}) (js
password = seclib.RandomPassword(12)
}
guestInfo, err := guest.DeployFs(guestfs.NewDeployInfo(publicKey, deploys, password, deployParams.IsInit, false, options.HostOptions.LinuxDefaultRootUser))
guestInfo, err := guest.DeployFs(guestfs.NewDeployInfo(
publicKey, deploys, password, deployParams.IsInit, false,
options.HostOptions.LinuxDefaultRootUser, options.HostOptions.WindowsDefaultAdminUser))
if err != nil {
log.Errorf("Deploy guest fs error: %s", err)
return nil, err
+4 -2
View File
@@ -34,6 +34,7 @@ import (
"yunion.io/x/onecloud/pkg/util/qemutils"
"yunion.io/x/onecloud/pkg/util/sysutils"
"yunion.io/x/onecloud/pkg/util/timeutils2"
"yunion.io/x/onecloud/pkg/util/winutils"
)
var (
@@ -216,8 +217,9 @@ func (h *SHostInfo) prepareEnv() error {
log.Errorf("Failed to activate nbd device: %s", output)
}
// TODO: winRegTool还未实现
// if not WinRegTool.check_tool(options.chntpw_path)...
if !winutils.CheckTool(options.HostOptions.ChntpwPath) {
return fmt.Errorf("Failed to find chntpw tool")
}
if err := hostbridge.Prepare(options.HostOptions.BridgeDriver); err != nil {
log.Errorln(err)
+1 -1
View File
@@ -44,7 +44,7 @@ func Init() {
func Start() {
if hostMetricsCollector != nil {
hostMetricsCollector.Start()
go hostMetricsCollector.Start()
}
}
+2 -1
View File
@@ -86,7 +86,8 @@ type SHostOptions struct {
SnapshotDirSuffix string `help:"Snapshot dir name equal diskId concat snapshot dir suffix" default:"_snap"`
SnapshotRecycleDay int `default:"1" help:"Snapshot Recycle delete Duration day"`
EnableTelegraf bool `default:"true" help:"enable send monitoring data to telegraf"`
EnableTelegraf bool `default:"true" help:"enable send monitoring data to telegraf"`
WindowsDefaultAdminUser bool `default:"true" help:"Default account for Windows system is Administrator"`
}
var HostOptions SHostOptions
+683
View File
@@ -0,0 +1,683 @@
package winutils
import (
"crypto/md5"
"fmt"
"io"
"io/ioutil"
"os/exec"
"path"
"regexp"
"strconv"
"strings"
"syscall"
"yunion.io/x/log"
"yunion.io/x/onecloud/pkg/util/fileutils2"
"yunion.io/x/onecloud/pkg/util/procutils"
"yunion.io/x/onecloud/pkg/util/regutils2"
"yunion.io/x/pkg/utils"
)
var _CHNTPW_PATH string
func SetChntpwPath(spath string) {
_CHNTPW_PATH = spath
}
func GetChntpwPath() string {
if len(_CHNTPW_PATH) == 0 {
_CHNTPW_PATH = "/usr/local/bin/chntpw.static"
}
return _CHNTPW_PATH
}
const (
SYSTEM = "system"
SOFTWARE = "software"
SECURITY = "security"
SAM = "sam"
CONFIRM = "y"
)
func NewWinRegTool(spath string) *SWinRegTool {
return &SWinRegTool{ConfigPath: spath}
}
func CheckTool(spath string) bool {
if fileutils2.Exists(spath) && exec.Command(spath, "-h").Run() == nil {
return true
} else {
return false
}
}
type SWinRegTool struct {
ConfigPath string
SystemPath string
SoftwarePath string
SamPath string
SecurityPath string
}
func (w *SWinRegTool) CheckPath() bool {
files, err := ioutil.ReadDir(w.ConfigPath)
if err != nil {
log.Errorln(err)
return false
}
for _, file := range files {
switch strings.ToLower(file.Name()) {
case SYSTEM:
w.SystemPath = path.Join(w.ConfigPath, file.Name())
case SOFTWARE:
w.SoftwarePath = path.Join(w.ConfigPath, file.Name())
case SAM:
w.SamPath = path.Join(w.ConfigPath, file.Name())
case SECURITY:
w.SecurityPath = path.Join(w.ConfigPath, file.Name())
}
}
if len(w.SystemPath) > 0 && len(w.SoftwarePath) > 0 &&
len(w.SamPath) > 0 && len(w.SecurityPath) > 0 {
return true
}
return false
}
func (w *SWinRegTool) GetUsers() map[string]bool {
output, err := procutils.NewCommand(GetChntpwPath(), "-l", w.SamPath).Run()
if err != nil {
log.Errorln(err)
return nil
}
users := map[string]bool{}
re := regexp.MustCompile(
`\|\s*\w+\s*\|\s*(?P<user>\w+)\s*\|\s*(ADMIN)?\s*\|\s*(?P<lock>(dis/lock|\*BLANK\*)?)`)
for _, line := range strings.Split(string(output), "\n") {
m := regutils2.GetParams(re, line)
if len(m) > 0 {
user, _ := m["user"]
if strings.ToLower(user) != "guest" {
lock, _ := m["lock"]
users[user] = lock != "dis/lock"
}
}
}
return users
}
func (w *SWinRegTool) samChange(user string, seq ...string) error {
proc := exec.Command(GetChntpwPath(), "-u", user, w.SamPath, w.SystemPath, w.SecurityPath)
stdin, err := proc.StdinPipe()
if err != nil {
return err
}
defer stdin.Close()
outb, err := proc.StdoutPipe()
if err != nil {
return err
}
defer outb.Close()
errb, err := proc.StderrPipe()
if err != nil {
return err
}
defer errb.Close()
if err := proc.Start(); err != nil {
return err
}
io.WriteString(stdin, "n\n")
for _, s := range seq {
io.WriteString(stdin, s+"\n")
}
io.WriteString(stdin, CONFIRM+"\n")
stdoutPut, err := ioutil.ReadAll(outb)
if err != nil {
return err
}
stderrOutPut, err := ioutil.ReadAll(errb)
if err != nil {
return err
}
log.Debugf("Sam change %s %s", stdoutPut, stderrOutPut)
if proc.ProcessState.Exited() {
if err := proc.Wait(); err != nil {
if exiterr, ok := err.(*exec.ExitError); ok {
ws := exiterr.Sys().(syscall.WaitStatus)
if ws.ExitStatus() == 2 {
return nil
}
}
log.Errorf("Failed to change SAM password")
return err
} else {
return nil
}
} else {
proc.Process.Kill()
return fmt.Errorf("Failed to change SAM password, not exit cleanly")
}
}
func (w *SWinRegTool) ChangePassword(user, password string) error {
return w.samChange(user, "2", password)
}
func (w *SWinRegTool) RemovePassword(user string) error {
return w.samChange(user, "2")
}
func (w *SWinRegTool) UnlockUser(user string) error {
return w.samChange(user, "4")
}
func (w *SWinRegTool) GetRegFile(regPath string) (string, []string) {
re := regexp.MustCompile("\\")
vals := re.Split(regPath, -1)
regSeg := []string{}
for _, val := range vals {
if len(val) > 0 {
regSeg = append(regSeg, val)
}
}
if regSeg[0] == "HKLM" {
regSeg = regSeg[1:]
}
if strings.ToLower(regSeg[0]) == SOFTWARE {
regSeg = regSeg[1:]
return w.SoftwarePath, regSeg
} else if strings.ToLower(regSeg[0]) == SYSTEM {
regSeg = regSeg[1:]
return w.SystemPath, regSeg
} else {
return "", nil
}
}
func (w *SWinRegTool) showRegistry(spath string, keySeg []string, verb string) ([]string, error) {
proc := exec.Command(GetChntpwPath(), spath)
stdin, err := proc.StdinPipe()
if err != nil {
return nil, err
}
defer stdin.Close()
outb, err := proc.StdoutPipe()
if err != nil {
return nil, err
}
defer outb.Close()
// errb, err := proc.StderrPipe()
// if err != nil {
// return nil, err
// }
// defer errb.Close()
if err := proc.Start(); err != nil {
return nil, err
}
keypath := strings.Join(keySeg, "\\")
io.WriteString(stdin, fmt.Sprintf("%s %s\n", verb, keypath))
io.WriteString(stdin, "q\n")
stdoutPut, err := ioutil.ReadAll(outb)
if err != nil {
return nil, err
}
if !proc.ProcessState.Exited() {
proc.Process.Kill()
}
return strings.Split(string(stdoutPut), "\n"), nil
}
func (w *SWinRegTool) getRegistry(spath string, keySeg []string) string {
keyPath := strings.Join(keySeg, "\\")
lines, err := w.showRegistry(spath, keySeg, "cat")
if err != nil {
log.Errorln(err)
return ""
}
for i, line := range lines {
if len(keyPath) > 85 {
keyPath = keyPath[:85]
}
if strings.Contains(line, fmt.Sprintf("> Value <%s> of type REG_", keyPath)) {
return lines[i+1]
}
}
return ""
}
type sRegistry struct {
Key string
Type string
Size string
}
func (w *SWinRegTool) listRegistry(spath string, keySeg []string) ([]string, []sRegistry, error) {
lines, err := w.showRegistry(spath, keySeg, "ls")
if err != nil {
return nil, nil, err
}
keys := []string{}
values := []sRegistry{}
keyPattern := regexp.MustCompile("^<(?P<key>[^>]+)>$")
valPattern := regexp.MustCompile(`^(?P<size>\d+)\s+(?P<type>REG\_\w+)\s+<(?P<key>[^>]+)>\s*`)
for _, line := range lines {
m := regutils2.GetParams(keyPattern, line)
if len(m) > 0 {
keys = append(keys, m["key"])
}
m = regutils2.GetParams(valPattern, line)
if len(m) > 0 {
values = append(values, sRegistry{m["key"], m["type"], m["size"]})
}
}
return keys, values, nil
}
func (w *SWinRegTool) cmdRegistry(spath string, ops []string, retcode int) bool {
proc := exec.Command(GetChntpwPath(), "-e", spath)
stdin, err := proc.StdinPipe()
if err != nil {
log.Errorln(err)
return false
}
defer stdin.Close()
outb, err := proc.StdoutPipe()
if err != nil {
log.Errorln(err)
return false
}
defer outb.Close()
errb, err := proc.StderrPipe()
if err != nil {
log.Errorln(err)
return false
}
defer errb.Close()
if err := proc.Start(); err != nil {
log.Errorln(err)
return false
}
for _, op := range ops {
io.WriteString(stdin, op+"\n")
}
io.WriteString(stdin, "q\n")
io.WriteString(stdin, CONFIRM+"\n")
stdoutPut, err := ioutil.ReadAll(outb)
if err != nil {
log.Errorln(err)
return false
}
stderrOutPut, err := ioutil.ReadAll(errb)
if err != nil {
log.Errorln(err)
return false
}
log.Debugf("Cmd registry %s %s", stdoutPut, stderrOutPut)
if proc.ProcessState.Exited() {
if err := proc.Wait(); err != nil {
if exiterr, ok := err.(*exec.ExitError); ok {
ws := exiterr.Sys().(syscall.WaitStatus)
if ws.ExitStatus() == retcode {
return true
}
}
} else {
return retcode == 0
}
} else {
proc.Process.Kill()
}
return false
}
func (w *SWinRegTool) setRegistry(spath string, keySeg []string, value string) bool {
keyPath := strings.Join(keySeg, "\\")
return w.cmdRegistry(spath, []string{fmt.Sprintf("ed %s", keyPath), value}, 0)
}
func (w *SWinRegTool) mkdir(spath string, keySeg []string) bool {
return w.cmdRegistry(spath,
[]string{
fmt.Sprintf("cd %s", strings.Join(keySeg[:len(keySeg)-1], "\\")),
fmt.Sprintf("nk %s", keySeg[len(keySeg)-1]),
}, 2)
}
func (w *SWinRegTool) keyExists(spath string, keySeg []string) bool {
keys, _, err := w.listRegistry(spath, keySeg[:len(keySeg)-1])
if err != nil {
log.Errorln(err)
return false
}
if utils.IsInStringArray(keySeg[len(keySeg)-1], keys) {
return true
}
return false
}
func (w *SWinRegTool) valExists(spath string, keySeg []string) bool {
_, vals, err := w.listRegistry(spath, keySeg[:len(keySeg)-1])
if err != nil {
log.Errorln(err)
return false
}
for _, val := range vals {
if val.Key == keySeg[len(keySeg)-1] {
return true
}
}
return false
}
func (w *SWinRegTool) mkdir_P(spath string, keySeg []string) bool {
seg := []string{}
for _, k := range keySeg {
seg = append(seg, k)
if !w.keyExists(spath, seg) {
if !w.mkdir(spath, seg) {
return false
}
}
}
return true
}
func (w *SWinRegTool) newValue(spath string, keySeg []string, regtype, val string) bool {
REG_TYPE_TBL := []string{
"REG_NONE",
"REG_SZ",
"REG_EXPAND_SZ",
"REG_BINARY",
"REG_DWORD",
"REG_DWORD_BIG_ENDIAN",
"REG_LINK",
"REG_MULTI_SZ",
"REG_RESOUCE_LIST",
"REG_FULL_RES_DESC",
"REG_RES_REQ",
"REG_QWORD",
}
ok, idx := utils.InStringArray(regtype, REG_TYPE_TBL)
if !ok {
return false
}
cmds := []string{
fmt.Sprintf("cd %s", strings.Join(keySeg[:len(keySeg)-1], "\\")),
fmt.Sprintf("nv %x %s", idx, keySeg[len(keySeg)-1]),
fmt.Sprintf("ed %s", keySeg[len(keySeg)-1]),
}
if regtype == "REG_QWORD" {
cmds = append(cmds, "16", ": 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0", "s")
} else {
cmds = append(cmds, val)
}
return w.cmdRegistry(spath, cmds, 0)
}
func (w *SWinRegTool) GetRegistry(keyPath string) string {
p1, p2s := w.GetRegFile(keyPath)
if len(p1) == 0 && len(p2s) == 0 {
return ""
} else {
return w.getRegistry(p1, p2s)
}
}
func (w *SWinRegTool) ListRegistry(keyPath string) ([]string, []sRegistry) {
p1, p2s := w.GetRegFile(keyPath)
if len(p1) == 0 && len(p2s) == 0 {
return nil, nil
} else {
v1, v2, err := w.listRegistry(p1, p2s)
if err != nil {
log.Errorln(err)
return nil, nil
}
return v1, v2
}
}
func (w *SWinRegTool) SetRegistry(keyPath, value, regtype string) bool {
p1, p2s := w.GetRegFile(keyPath)
if len(p1) == 0 && len(p2s) == 0 {
return false
} else {
if w.valExists(p1, p2s) {
return w.setRegistry(p1, p2s, value)
} else {
if !w.keyExists(p1, p2s[:len(p2s)-1]) {
if !w.mkdir_P(p1, p2s[:len(p2s)-1]) {
return false
}
}
return w.newValue(p1, p2s, regtype, value)
}
}
}
func (w *SWinRegTool) KeyExists(keyPath string) bool {
p1, p2s := w.GetRegFile(keyPath)
if len(p1) == 0 && len(p2s) == 0 {
return false
} else {
return w.keyExists(p1, p2s)
}
}
func (w *SWinRegTool) MkdirP(keyPath string) bool {
p1, p2s := w.GetRegFile(keyPath)
if len(p1) == 0 && len(p2s) == 0 {
return false
} else {
return w.mkdir_P(p1, p2s)
}
}
func (w *SWinRegTool) GetCcsKey() string {
ver := w.GetRegistry(`HKLM\SYSTEM\Select\Current`)
iv, _ := strconv.ParseInt(ver, 16, 0)
return fmt.Sprintf("ControlSet%03d", iv)
}
func (w *SWinRegTool) GetCcsKeyPath() string {
return fmt.Sprintf(`HKLM\SYSTEM\%s`, w.GetCcsKey())
}
func (w *SWinRegTool) getComputerNameKeyPath() string {
key := w.GetCcsKey()
return key + `\Control\ComputerName\ComputerName\ComputerName`
}
func (w *SWinRegTool) GetComputerName() string {
key := w.getComputerNameKeyPath()
return w.GetRegistry(key)
}
func (w *SWinRegTool) setComputerName(cn string) {
MAX_COMPUTER_NAME_LEN := 15
COMMON_PREFIX_LEN := 10
if len(cn) > MAX_COMPUTER_NAME_LEN {
suffix := cn[COMMON_PREFIX_LEN:]
suffixlen := MAX_COMPUTER_NAME_LEN - COMMON_PREFIX_LEN
md5sum := md5.Sum([]byte(suffix))
cn = cn[:COMMON_PREFIX_LEN] + string(md5sum[:])[:suffixlen]
}
key := w.getComputerNameKeyPath()
w.SetRegistry(key, cn, "")
}
func (w *SWinRegTool) SetHostname(hostname, domain string) {
tcpipKey := w.GetCcsKeyPath() + `\Services\Tcpip\Parameters`
hnKey := tcpipKey + `\Hostname`
dmKey := tcpipKey + `\Domain`
nvHnKey := tcpipKey + `\NV Hostname`
nvDmKey := tcpipKey + `\NV Domain`
w.SetRegistry(hnKey, hostname, "REG_SZ")
w.SetRegistry(dmKey, domain, "REG_SZ")
w.SetRegistry(nvHnKey, hostname, "REG_SZ")
w.SetRegistry(nvDmKey, domain, "REG_SZ")
}
func (w *SWinRegTool) SetDnsServer(nameserver, searchlist string) {
tcpipKey := w.GetCcsKeyPath() + `\Services\Tcpip\Parameters`
ns_key := tcpipKey + `\NameServer`
search_key := tcpipKey + `\SearchList`
w.SetRegistry(ns_key, nameserver, "REG_SZ")
w.SetRegistry(search_key, searchlist, "REG_SZ")
}
func (w *SWinRegTool) GetProductName() string {
prodKey := `HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProductName`
return w.GetRegistry(prodKey)
}
func (w *SWinRegTool) GetVersion() string {
prodKey := `HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\CurrentVersion`
return w.GetRegistry(prodKey)
}
func (w *SWinRegTool) GetInstallLanguage() string {
nlsTbl := map[string]string{"0804": "zh_CN", "0404": "zh_TW", "0c04": "zh_HK",
"1004": "zh_SG", "0409": "en_US", "0809": "en_UK"}
key := w.GetCcsKeyPath()
key += `\Control\Nls\Language\InstallLanguage`
val := w.GetRegistry(key)
if xval, ok := nlsTbl[key]; ok {
return xval
} else {
return val
}
}
func (w *SWinRegTool) GetArch() string {
prodKey := `HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows NT\CurrentVersion\CurrentVersion`
ver := w.GetRegistry(prodKey)
if len(ver) > 0 {
return "x86_64"
} else {
return "x86"
}
}
func (w *SWinRegTool) LogontypePath() string {
return `HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\LogonType`
}
func (w *SWinRegTool) GetLogontype() string {
return w.GetRegistry(w.LogontypePath())
}
func (w *SWinRegTool) SetLogontype(val string) {
w.SetRegistry(w.LogontypePath(), val, "")
}
func (w *SWinRegTool) DefaultAccountPath() string {
return `HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\DefaultUserName`
}
func (w *SWinRegTool) GetDefaultAccount() string {
return w.GetRegistry(w.DefaultAccountPath())
}
func (w *SWinRegTool) SetDefaultAccount(user string) {
w.SetRegistry(w.DefaultAccountPath(), user, "")
}
func (w *SWinRegTool) GpeditScriptPath() string {
return `HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Group Policy\Scripts`
}
func (w *SWinRegTool) GpeditScriptStatePath() string {
return `HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Group Policy\State\Machine\Scripts`
}
func (w *SWinRegTool) GetGpeditStartScripts() []string {
scriptKey := w.GpeditScriptPath() + `\Startup\0`
keys, _ := w.ListRegistry(scriptKey)
ret := []string{}
for _, k := range keys {
spath := scriptKey + (fmt.Sprintf(`\%s\Script`, k))
val := w.GetRegistry(spath)
ret = append(ret, val)
}
return ret
}
func (w *SWinRegTool) IsGpeditStartScriptInstalled(script string) bool {
scripts := w.GetGpeditStartScripts()
return utils.IsInStringArray(script, scripts)
}
func (w *SWinRegTool) InstallGpeditStartScript(script string) {
if w.IsGpeditStartScriptInstalled(script) {
return
}
w.installGpeditStartScript(script, w.GpeditScriptPath())
w.installGpeditStartScript(script, w.GpeditScriptStatePath())
}
func (w *SWinRegTool) GetGpoDisplayname() string {
spath := `HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Group Policy\State\Machine\GPO-List\0\DisplayName`
return w.GetRegistry(spath)
}
func (w *SWinRegTool) installGpeditStartScript(script, scriptPath string) {
idx := 0
if !w.KeyExists(scriptPath + `\Startup`) {
w.MkdirP(scriptPath + `\Startup`)
w.MkdirP(scriptPath + `\Shutdown`)
dsname := "Local Group Policy"
kvts := [][3]string{
[3]string{"GPO-ID", "LocalGPO", "REG_SZ"},
[3]string{"SOM-ID", "Local", "REG_SZ"},
[3]string{"FileSysPath", `C:\Windows\System32\GroupPolicy\Machine`, "REG_SZ"},
[3]string{"DisplayName", dsname, "REG_SZ"},
[3]string{"GPOName", dsname, "REG_SZ"},
[3]string{"PSScriptOrder", "1", "REG_DWORD"},
}
for _, kvt := range kvts {
w.SetRegistry(fmt.Sprintf(`%s\Startup\0\%s`, scriptPath, kvt[0]), kvt[1], kvt[2])
}
} else {
for w.KeyExists(scriptPath + (fmt.Sprintf(`\Startup\0\%d`, idx))) {
idx += 1
}
}
kvts := [][3]string{
[3]string{"Script", script, "REG_SZ"},
[3]string{"Parameters", "", "REG_SZ"},
[3]string{"ExecTime", "", "REG_QWORD"},
[3]string{"IsPowershell", "0", "REG_DWORD"},
}
for _, kvt := range kvts {
w.SetRegistry(fmt.Sprintf(`%s\Startup\0\%d\%s`, scriptPath, idx, kvt[0]), kvt[1], kvt[2])
}
}
func (w *SWinRegTool) EnableRdp() {
key := w.GetCcsKeyPath() + `\Control\Terminal Server\fDenyTSConnections`
w.SetRegistry(key, "0", `REG_DWORD`)
key = w.GetCcsKeyPath() + `\Services\MpsSvc\Start`
w.SetRegistry(key, "3", `REG_DWORD`)
}