Statistics
| Branch: | Tag: | Revision:

root / image_creator / winexe.py @ 9b2b47ae

History | View | Annotate | Download (4.1 kB)

1
# -*- coding: utf-8 -*-
2
#
3
# Copyright 2013 GRNET S.A. All rights reserved.
4
#
5
# Redistribution and use in source and binary forms, with or
6
# without modification, are permitted provided that the following
7
# conditions are met:
8
#
9
#   1. Redistributions of source code must retain the above
10
#      copyright notice, this list of conditions and the following
11
#      disclaimer.
12
#
13
#   2. Redistributions in binary form must reproduce the above
14
#      copyright notice, this list of conditions and the following
15
#      disclaimer in the documentation and/or other materials
16
#      provided with the distribution.
17
#
18
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
19
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
22
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
25
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
28
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29
# POSSIBILITY OF SUCH DAMAGE.
30
#
31
# The views and conclusions contained in the software and
32
# documentation are those of the authors and should not be
33
# interpreted as representing official policies, either expressed
34
# or implied, of GRNET S.A.
35

    
36
"""This module provides an interface for the WinEXE utility"""
37

    
38
import subprocess
39
import time
40
import signal
41
import distutils
42

    
43
from image_creator.util import FatalError
44

    
45

    
46
class WinexeTimeout(FatalError):
47
    """Raised when a WinExE command times-out"""
48
    pass
49

    
50

    
51
class WinEXE:
52
    """Wrapper class for the winexe command"""
53

    
54
    @staticmethod
55
    def is_installed(program='winexe'):
56
        return distutils.spawn.find_executable(program) is not None
57

    
58
    def __init__(self, username, password, hostname, program='winexe'):
59
        self._host = hostname
60
        self._user = username
61
        self._pass = password
62
        self._prog = program
63

    
64
        # -U USERNAME[%PASSWORD]
65
        user = '%s%s' % (self._user, '%%%s' % self._pass if self._pass else "")
66
        self._opts = ['-U', user]
67

    
68
    def reset(self):
69
        """Reset all winexe options"""
70

    
71
        # -U USERNAME[%PASSWORD]
72
        user = '%s%s' % (self._user, '%%%s' % self._pass if self._pass else "")
73
        self._opts = ['-U', user]
74

    
75
    def runas(self, username, password):
76
        """Run command as this user"""
77
        self._opts.append('--runas=%s%%%s' % (username, password))
78
        return self
79

    
80
    def system(self):
81
        """Use SYSTEM account"""
82
        self._opts.append('--system')
83
        return self
84

    
85
    def uninstall(self):
86
        """Uninstall winexe service after remote execution"""
87
        self._opts.append('--uninstall')
88
        return self
89

    
90
    def reinstall(self):
91
        """Reinstall winexe service before remote execution"""
92
        self._opts.append('--reinstall')
93
        return self
94

    
95
    def debug(self, level):
96
        """Set debug level"""
97
        self._opts.append('--debuglevel=%d' % level)
98
        return self
99

    
100
    def debug_stderr(self):
101
        """Send debug output to STDERR"""
102
        self._opts.append('--debug-stderr')
103

    
104
    def run(self, command, timeout=0):
105
        """Run a command on a remote windows system"""
106

    
107
        args = [self._prog] + self._opts + ["//%s" % self._host] + [command]
108
        run = subprocess.Popen(args, stdout=subprocess.PIPE,
109
                               stderr=subprocess.PIPE)
110

    
111
        def handler(signum, frame):
112
            run.terminate()
113
            time.sleep(1)
114
            run.poll()
115
            if run.returncode is None:
116
                run.kill()
117
            run.wait()
118
            raise WinexeTimeout("Command: `%s' timed-out" % " ".join(args))
119

    
120
        signal.signal(signal.SIGALRM, handler)
121
        signal.alarm(timeout)
122
        stdout, stderr = run.communicate()
123
        rc = run.poll()
124
        signal.alarm(0)
125

    
126
        return (stdout, stderr, rc)
127

    
128
# vim: set sta sts=4 shiftwidth=4 sw=4 et ai :