|
@@ -17,41 +17,35 @@ 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.
|
|
|
'''
|
|
|
-import os
|
|
|
import getpass
|
|
|
+import os
|
|
|
+import random
|
|
|
import shlex
|
|
|
import subprocess
|
|
|
import sys
|
|
|
+import tempfile
|
|
|
import time
|
|
|
-import win32api
|
|
|
-import win32event
|
|
|
-import win32service
|
|
|
-import win32con
|
|
|
-import win32serviceutil
|
|
|
-import wmi
|
|
|
-import random
|
|
|
import string
|
|
|
|
|
|
import ctypes
|
|
|
|
|
|
-from win32security import *
|
|
|
-from win32api import *
|
|
|
-from winerror import ERROR_INVALID_HANDLE
|
|
|
-from win32process import GetExitCodeProcess, STARTF_USESTDHANDLES, STARTUPINFO, CreateProcessAsUser
|
|
|
-from win32event import WaitForSingleObject, INFINITE
|
|
|
import msvcrt
|
|
|
-import tempfile
|
|
|
-from win32event import *
|
|
|
-from win32api import CloseHandle
|
|
|
-
|
|
|
-from ambari_commons.exceptions import *
|
|
|
-from logging_utils import *
|
|
|
|
|
|
-from win32security import LsaOpenPolicy, POLICY_CREATE_ACCOUNT, POLICY_LOOKUP_NAMES, LookupAccountName, \
|
|
|
- LsaAddAccountRights, LsaRemoveAccountRights, SE_SERVICE_LOGON_NAME
|
|
|
-from win32net import NetUserAdd
|
|
|
-from win32netcon import USER_PRIV_USER, UF_NORMAL_ACCOUNT, UF_SCRIPT
|
|
|
import pywintypes
|
|
|
+import winerror
|
|
|
+import win32api
|
|
|
+import win32con
|
|
|
+import win32event
|
|
|
+import win32net
|
|
|
+import win32netcon
|
|
|
+import win32process
|
|
|
+import win32security
|
|
|
+import win32service
|
|
|
+import win32serviceutil
|
|
|
+import wmi
|
|
|
+
|
|
|
+from ambari_commons.exceptions import FatalException
|
|
|
+from ambari_commons.logging_utils import print_info_msg, print_warning_msg
|
|
|
|
|
|
SERVICE_STATUS_UNKNOWN = "unknown"
|
|
|
SERVICE_STATUS_STARTING = "starting"
|
|
@@ -63,6 +57,27 @@ SERVICE_STATUS_NOT_INSTALLED = "not installed"
|
|
|
WHOAMI_GROUPS = "whoami /groups"
|
|
|
ADMIN_ACCOUNT = "BUILTIN\\Administrators"
|
|
|
|
|
|
+#
|
|
|
+# os.symlink is not implemented in Windows. Patch it.
|
|
|
+#
|
|
|
+__CSL = None
|
|
|
+def symlink(source, link_name):
|
|
|
+ '''symlink(source, link_name)
|
|
|
+ Creates a symbolic link pointing to source named link_name'''
|
|
|
+ global __CSL
|
|
|
+ if __CSL is None:
|
|
|
+ csl = ctypes.windll.kernel32.CreateSymbolicLinkW
|
|
|
+ csl.argtypes = (ctypes.c_wchar_p, ctypes.c_wchar_p, ctypes.c_uint32)
|
|
|
+ csl.restype = ctypes.c_ubyte
|
|
|
+ __CSL = csl
|
|
|
+ flags = 0
|
|
|
+ if source is not None and os.path.isdir(source):
|
|
|
+ flags = 1
|
|
|
+ if __CSL(link_name, source, flags) == 0:
|
|
|
+ raise ctypes.WinError()
|
|
|
+
|
|
|
+os.symlink = symlink
|
|
|
+
|
|
|
class OSVERSIONINFOEXW(ctypes.Structure):
|
|
|
_fields_ = [('dwOSVersionInfoSize', ctypes.c_ulong),
|
|
|
('dwMajorVersion', ctypes.c_ulong),
|
|
@@ -77,17 +92,17 @@ class OSVERSIONINFOEXW(ctypes.Structure):
|
|
|
('wReserved', ctypes.c_byte)]
|
|
|
|
|
|
def get_windows_version():
|
|
|
- """
|
|
|
- Get's the OS major and minor versions. Returns a tuple of
|
|
|
- (OS_MAJOR, OS_MINOR).
|
|
|
- """
|
|
|
- os_version = OSVERSIONINFOEXW()
|
|
|
- os_version.dwOSVersionInfoSize = ctypes.sizeof(os_version)
|
|
|
- retcode = ctypes.windll.Ntdll.RtlGetVersion(ctypes.byref(os_version))
|
|
|
- if retcode != 0:
|
|
|
- raise Exception("Failed to get OS version")
|
|
|
-
|
|
|
- return os_version.dwMajorVersion, os_version.dwMinorVersion, os_version.dwBuildNumber
|
|
|
+ """
|
|
|
+ Gets the OS major and minor versions. Returns a tuple of
|
|
|
+ (OS_MAJOR, OS_MINOR).
|
|
|
+ """
|
|
|
+ os_version = OSVERSIONINFOEXW()
|
|
|
+ os_version.dwOSVersionInfoSize = ctypes.sizeof(os_version)
|
|
|
+ retcode = ctypes.windll.Ntdll.RtlGetVersion(ctypes.byref(os_version))
|
|
|
+ if retcode != 0:
|
|
|
+ raise Exception("Failed to get OS version")
|
|
|
+
|
|
|
+ return os_version.dwMajorVersion, os_version.dwMinorVersion, os_version.dwBuildNumber
|
|
|
|
|
|
CHECK_FIREWALL_SCRIPT = """[string]$CName = $env:computername
|
|
|
$reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey("LocalMachine",$computer)
|
|
@@ -116,25 +131,25 @@ def _get_files_output(out, err):
|
|
|
|
|
|
def _safe_duplicate_handle(h):
|
|
|
try:
|
|
|
- h = DuplicateHandle(GetCurrentProcess(),
|
|
|
- h,
|
|
|
- GetCurrentProcess(),
|
|
|
- 0,
|
|
|
- True,
|
|
|
- win32con.DUPLICATE_SAME_ACCESS)
|
|
|
+ h = win32api.DuplicateHandle(win32process.GetCurrentProcess(),
|
|
|
+ h,
|
|
|
+ win32process.GetCurrentProcess(),
|
|
|
+ 0,
|
|
|
+ True,
|
|
|
+ win32con.DUPLICATE_SAME_ACCESS)
|
|
|
return True, h
|
|
|
except Exception as exc:
|
|
|
- if exc.winerror == ERROR_INVALID_HANDLE:
|
|
|
+ if exc.winerror == winerror.ERROR_INVALID_HANDLE:
|
|
|
return True, None
|
|
|
return False, None
|
|
|
|
|
|
|
|
|
def run_os_command_impersonated(cmd, user, password, domain='.'):
|
|
|
- si = STARTUPINFO()
|
|
|
+ si = win32process.STARTUPINFO()
|
|
|
|
|
|
out_handle, err_handle, out_file, err_file = _create_tmp_files()
|
|
|
|
|
|
- ok, si.hStdInput = _safe_duplicate_handle(GetStdHandle(STD_INPUT_HANDLE))
|
|
|
+ ok, si.hStdInput = _safe_duplicate_handle(win32api.GetStdHandle(win32api.STD_INPUT_HANDLE))
|
|
|
|
|
|
if not ok:
|
|
|
raise Exception("Unable to create StdInput for child process")
|
|
@@ -145,27 +160,29 @@ def run_os_command_impersonated(cmd, user, password, domain='.'):
|
|
|
if not ok:
|
|
|
raise Exception("Unable to create StdErr for child process")
|
|
|
|
|
|
- si.dwFlags = STARTF_USESTDHANDLES
|
|
|
+ si.dwFlags = win32process.STARTF_USESTDHANDLES
|
|
|
si.lpDesktop = ""
|
|
|
|
|
|
- user_token = LogonUser(user, domain, password, win32con.LOGON32_LOGON_SERVICE, win32con.LOGON32_PROVIDER_DEFAULT)
|
|
|
- primary_token = DuplicateTokenEx(user_token, SecurityImpersonation, 0, TokenPrimary)
|
|
|
- info = CreateProcessAsUser(primary_token, None, cmd, None, None, 1, 0, None, None, si)
|
|
|
+ user_token = win32security.LogonUser(user, domain, password,
|
|
|
+ win32con.LOGON32_LOGON_SERVICE, win32con.LOGON32_PROVIDER_DEFAULT)
|
|
|
+ primary_token = win32security.DuplicateTokenEx(user_token,
|
|
|
+ win32security.SecurityImpersonation, 0, win32security.TokenPrimary)
|
|
|
+ info = win32process.CreateProcessAsUser(primary_token, None, cmd, None, None, 1, 0, None, None, si)
|
|
|
|
|
|
hProcess, hThread, dwProcessId, dwThreadId = info
|
|
|
hThread.Close()
|
|
|
|
|
|
try:
|
|
|
- WaitForSingleObject(hProcess, INFINITE)
|
|
|
+ win32event.WaitForSingleObject(hProcess, win32event.INFINITE)
|
|
|
except KeyboardInterrupt:
|
|
|
pass
|
|
|
|
|
|
out, err = _get_files_output(out_file, err_file)
|
|
|
- exitcode = GetExitCodeProcess(hProcess)
|
|
|
+ exitcode = win32process.GetExitCodeProcess(hProcess)
|
|
|
|
|
|
return exitcode, out, err
|
|
|
|
|
|
-def run_os_command(cmd, env=None):
|
|
|
+def os_run_os_command(cmd, env=None, shell=False):
|
|
|
if isinstance(cmd,basestring):
|
|
|
cmd = cmd.replace("\\", "\\\\")
|
|
|
cmd = shlex.split(cmd)
|
|
@@ -173,7 +190,8 @@ def run_os_command(cmd, env=None):
|
|
|
stdout=subprocess.PIPE,
|
|
|
stdin=subprocess.PIPE,
|
|
|
stderr=subprocess.PIPE,
|
|
|
- env=env
|
|
|
+ env=env,
|
|
|
+ shell=shell
|
|
|
)
|
|
|
(stdoutdata, stderrdata) = process.communicate()
|
|
|
return process.returncode, stdoutdata, stderrdata
|
|
@@ -186,13 +204,13 @@ def run_powershell_script(script_content):
|
|
|
script_file = open(os.path.join(tmp_dir,random_filename+".ps1"),"w")
|
|
|
script_file.write(script_content)
|
|
|
script_file.close()
|
|
|
- result = run_os_command("powershell -ExecutionPolicy unrestricted -File {0}".format(script_file.name))
|
|
|
+ result = os_run_os_command("powershell -ExecutionPolicy unrestricted -File {0}".format(script_file.name))
|
|
|
os.remove(script_file.name)
|
|
|
return result
|
|
|
|
|
|
def os_change_owner(filePath, user):
|
|
|
cmd = ['icacls', filePath, '/setowner', user]
|
|
|
- retcode, outdata, errdata = run_os_command(cmd)
|
|
|
+ retcode, outdata, errdata = os_run_os_command(cmd)
|
|
|
return retcode
|
|
|
|
|
|
def os_is_root():
|
|
@@ -200,9 +218,10 @@ def os_is_root():
|
|
|
Checks whether the current user is a member of the Administrators group
|
|
|
Returns True if yes, otherwise False
|
|
|
'''
|
|
|
- retcode, out, err = run_os_command(WHOAMI_GROUPS)
|
|
|
+ retcode, out, err = os_run_os_command(WHOAMI_GROUPS)
|
|
|
if retcode != 0:
|
|
|
- err_msg = "Unable to check the current user's group memberships. Command {0} returned exit code {1} with message: {2}".format(WHOAMI_GROUPS, retcode, err)
|
|
|
+ err_msg = "Unable to check the current user's group memberships. " \
|
|
|
+ "Command {0} returned exit code {1} with message: {2}".format(WHOAMI_GROUPS, retcode, err)
|
|
|
print_warning_msg(err_msg)
|
|
|
raise FatalException(retcode, err_msg)
|
|
|
|
|
@@ -221,20 +240,20 @@ def os_set_file_permissions(file, mod, recursive, user):
|
|
|
#else:
|
|
|
# params = ""
|
|
|
#command = NR_CHMOD_CMD.format(params, mod, file)
|
|
|
- #retcode, out, err = run_os_command(command)
|
|
|
+ #retcode, out, err = os_run_os_command(command)
|
|
|
#if retcode != 0:
|
|
|
# print_warning_msg(WARN_MSG.format(command, file, err))
|
|
|
#command = NR_CHOWN_CMD.format(params, user, file)
|
|
|
- #retcode, out, err = run_os_command(command)
|
|
|
+ #retcode, out, err = os_run_os_command(command)
|
|
|
#if retcode != 0:
|
|
|
# print_warning_msg(WARN_MSG.format(command, file, err))
|
|
|
|
|
|
# rights = mod
|
|
|
# acls_remove_cmd = "icacls {0} /remove {1}".format(file, user)
|
|
|
- # retcode, out, err = run_os_command(acls_remove_cmd)
|
|
|
+ # retcode, out, err = os_run_os_command(acls_remove_cmd)
|
|
|
# if retcode == 0:
|
|
|
# acls_modify_cmd = "icacls {0} /grant {1}:{2}".format(file, user, rights)
|
|
|
- # retcode, out, err = run_os_command(acls_modify_cmd)
|
|
|
+ # retcode, out, err = os_run_os_command(acls_modify_cmd)
|
|
|
return retcode
|
|
|
|
|
|
|
|
@@ -248,8 +267,6 @@ def os_getpass(prompt, stream=None):
|
|
|
if sys.stdin is not sys.__stdin__:
|
|
|
return getpass.fallback_getpass(prompt, stream)
|
|
|
|
|
|
- import msvcrt
|
|
|
-
|
|
|
for c in prompt:
|
|
|
msvcrt.putch(c)
|
|
|
|
|
@@ -506,24 +523,24 @@ class WinService(win32serviceutil.ServiceFramework):
|
|
|
class SystemWideLock(object):
|
|
|
|
|
|
def __init__(self, name):
|
|
|
- self._mutex = CreateMutex(None, 0, name)
|
|
|
+ self._mutex = win32event.CreateMutex(None, 0, name)
|
|
|
|
|
|
def lock(self, timeout=0):
|
|
|
- result = WaitForSingleObject(self._mutex, timeout)
|
|
|
- if result in [WAIT_TIMEOUT, WAIT_ABANDONED, WAIT_FAILED]:
|
|
|
+ result = win32event.WaitForSingleObject(self._mutex, timeout)
|
|
|
+ if result in [win32event.WAIT_TIMEOUT, win32event.WAIT_ABANDONED, win32event.WAIT_FAILED]:
|
|
|
return False
|
|
|
- elif result == WAIT_OBJECT_0:
|
|
|
+ elif result == win32event.WAIT_OBJECT_0:
|
|
|
return True
|
|
|
|
|
|
def unlock(self):
|
|
|
try:
|
|
|
- ReleaseMutex(self._mutex)
|
|
|
+ win32event.ReleaseMutex(self._mutex)
|
|
|
return True
|
|
|
except:
|
|
|
return False
|
|
|
|
|
|
def __del__(self):
|
|
|
- CloseHandle(self._mutex)
|
|
|
+ win32api.CloseHandle(self._mutex)
|
|
|
|
|
|
class UserHelper(object):
|
|
|
ACTION_OK = 0
|
|
@@ -531,17 +548,18 @@ class UserHelper(object):
|
|
|
ACTION_FAILED = -1
|
|
|
|
|
|
def __init__(self):
|
|
|
- self._policy = LsaOpenPolicy(None, POLICY_CREATE_ACCOUNT | POLICY_LOOKUP_NAMES)
|
|
|
+ self._policy = win32security.LsaOpenPolicy(None,
|
|
|
+ win32security.POLICY_CREATE_ACCOUNT | win32security.POLICY_LOOKUP_NAMES)
|
|
|
|
|
|
def create_user(self, name, password, comment="Ambari user"):
|
|
|
user_info = {}
|
|
|
user_info['name'] = name
|
|
|
user_info['password'] = password
|
|
|
- user_info['priv'] = USER_PRIV_USER
|
|
|
+ user_info['priv'] = win32netcon.USER_PRIV_USER
|
|
|
user_info['comment'] = comment
|
|
|
- user_info['flags'] = UF_NORMAL_ACCOUNT | UF_SCRIPT
|
|
|
+ user_info['flags'] = win32netcon.UF_NORMAL_ACCOUNT | win32netcon.UF_SCRIPT
|
|
|
try:
|
|
|
- NetUserAdd(None, 1, user_info)
|
|
|
+ win32net.NetUserAdd(None, 1, user_info)
|
|
|
except pywintypes.error as e:
|
|
|
if e.winerror == 2224:
|
|
|
return UserHelper.USER_EXISTS, e.strerror
|
|
@@ -551,16 +569,16 @@ class UserHelper(object):
|
|
|
|
|
|
def add_user_privilege(self, name, privilege):
|
|
|
try:
|
|
|
- acc_sid = LookupAccountName(None, name)[0]
|
|
|
- LsaAddAccountRights(self._policy, acc_sid, (privilege,))
|
|
|
+ acc_sid = win32security.LookupAccountName(None, name)[0]
|
|
|
+ win32security.LsaAddAccountRights(self._policy, acc_sid, (privilege,))
|
|
|
except pywintypes.error as e:
|
|
|
return UserHelper.ACTION_FAILED, e.strerror
|
|
|
return UserHelper.ACTION_OK, "Privilege added."
|
|
|
|
|
|
def remove_user_privilege(self, name, privilege):
|
|
|
try:
|
|
|
- acc_sid = LookupAccountName(None, name)[0]
|
|
|
- LsaRemoveAccountRights(self._policy, acc_sid, 0, (privilege,))
|
|
|
+ acc_sid = win32security.LookupAccountName(None, name)[0]
|
|
|
+ win32security.LsaRemoveAccountRights(self._policy, acc_sid, 0, (privilege,))
|
|
|
except pywintypes.error as e:
|
|
|
return UserHelper.ACTION_FAILED, e.strerror
|
|
|
return UserHelper.ACTION_OK, "Privilege removed."
|