Statistics
| Branch: | Tag: | Revision:

root / image_creator / os_type / windows.py @ 9ca717c4

History | View | Annotate | Download (7 kB)

1
# -*- coding: utf-8 -*-
2
#
3
# Copyright 2012 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 hosts OS-specific code common for the various Microsoft
37
Windows OSs."""
38

    
39
from image_creator.os_type import OSBase, sysprep
40
from image_creator.util import FatalError, check_guestfs_version, get_command
41

    
42
import hivex
43
import tempfile
44
import os
45
import time
46
import random
47

    
48
kvm = get_command('kvm')
49

    
50

    
51
class Windows(OSBase):
52
    """OS class for Windows"""
53

    
54
    @sysprep(enabled=False)
55
    def test(self, print_header=True):
56
        """test sysprep"""
57
        pass
58

    
59
    def do_sysprep(self):
60
        """Prepare system for image creation."""
61

    
62
        if getattr(self, 'syspreped', False):
63
            raise FatalError("Image is already syspreped!")
64

    
65
        self.mount(readonly=False)
66
        try:
67
            disabled_uac = self._update_uac_remote_setting(1)
68
        finally:
69
            self.umount()
70

    
71
        self.out.output("Shutting down helper VM ...", False)
72
        self.g.sync()
73
        # guestfs_shutdown which is the prefered way to shutdown the backend
74
        # process was introduced in version 1.19.16
75
        if check_guestfs_version(self.g, 1, 19, 16) >= 0:
76
            ret = self.g.shutdown()
77
        else:
78
            ret = self.g.kill_subprocess()
79

    
80
        self.out.success('done')
81
        try:
82
            self.out.output("Starting windows VM ...", False)
83

    
84
            def random_mac():
85
                mac = [0x00, 0x16, 0x3e,
86
                       random.randint(0x00, 0x7f),
87
                       random.randint(0x00, 0xff),
88
                       random.randint(0x00, 0xff)]
89
                return ':'.join(map(lambda x: "%02x" % x, mac))
90

    
91
            vm = kvm('-smp', '1', '-m', '1024', '-drive',
92
                     'file=%s,format=raw,cache=none,if=virtio' %
93
                     self.image.device,
94
                     '-netdev', 'type=user,hostfwd=tcp::445-:445,id=netdev0',
95
                     '-device', 'virtio-net-pci,mac=%s,netdev=netdev0' %
96
                     random_mac(), '-vnc', ':0', _bg=True)
97
            time.sleep(30)
98
            self.out.success('done')
99
            vm.wait()
100
        finally:
101
            self.out.output("Relaunching helper VM (may take a while) ...",
102
                            False)
103
            self.g.launch()
104
            self.out.success('done')
105

    
106
        if disabled_uac:
107
            self._update_uac_remote_setting(0)
108

    
109
        self.syspreped = True
110

    
111
    def _registry_file_path(self, regfile):
112
        """Retrieves the case sensitive path to a registry file"""
113

    
114
        systemroot = self.g.inspect_get_windows_systemroot(self.root)
115
        path = "%s/system32/config/%s" % (systemroot, regfile)
116
        try:
117
            path = self.g.case_sensitive_path(path)
118
        except RuntimeError as e:
119
            raise FatalError("Unable to retrieve registry file: %s. Reason: %s"
120
                             % (regfile, str(e)))
121
        return path
122

    
123
    def _update_uac_remote_setting(self, value):
124
        """Updates the registry key value:
125
        [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies
126
        \System]"LocalAccountTokenFilterPolicy"
127

128
        value = 1 will disable the UAC remote restrictions
129
        value = 0 will enable the UAC remote restrictions
130

131
        For more info see here: http://support.microsoft.com/kb/951016
132

133
        Returns:
134
            True if the key is changed
135
            False if the key is unchanged
136
        """
137

    
138
        if value not in (0, 1):
139
            raise ValueError("Valid values for value parameter are 0 and 1")
140

    
141
        path = self._registry_file_path('SOFTWARE')
142
        softwarefd, software = tempfile.mkstemp()
143
        try:
144
            os.close(softwarefd)
145
            self.g.download(path, software)
146

    
147
            h = hivex.Hivex(software, write=True)
148

    
149
            key = h.root()
150
            for child in ('Microsoft', 'Windows', 'CurrentVersion', 'Policies',
151
                          'System'):
152
                key = h.node_get_child(key, child)
153

    
154
            policy = None
155
            for val in h.node_values(key):
156
                if h.value_key(val) == "LocalAccountTokenFilterPolicy":
157
                    policy = val
158

    
159
            if policy is not None:
160
                dword = h.value_dword(policy)
161
                if dword == value:
162
                    return False
163
            elif value == 0:
164
                return False
165

    
166
            new_value = {
167
                'key': "LocalAccountTokenFilterPolicy", 't': 4L,
168
                'value': '%s\x00\x00\x00' % '\x00' if value == 0 else '\x01'}
169

    
170
            h.node_set_value(key, new_value)
171
            h.commit(None)
172

    
173
            self.g.upload(software, path)
174

    
175
        finally:
176
            os.unlink(software)
177

    
178
        return True
179

    
180
    def _do_collect_metadata(self):
181
        """Collect metadata about the OS"""
182
        super(Windows, self)._do_collect_metadata()
183
        self.meta["USERS"] = " ".join(self._get_users())
184

    
185
    def _get_users(self):
186
        """Returns a list of users found in the images"""
187
        path = self._registry_file_path('SAM')
188
        samfd, sam = tempfile.mkstemp()
189
        try:
190
            os.close(samfd)
191
            self.g.download(path, sam)
192

    
193
            h = hivex.Hivex(sam)
194

    
195
            key = h.root()
196
            # Navigate to /SAM/Domains/Account/Users/Names
197
            for child in ('SAM', 'Domains', 'Account', 'Users', 'Names'):
198
                key = h.node_get_child(key, child)
199

    
200
            users = [h.node_name(x) for x in h.node_children(key)]
201

    
202
        finally:
203
            os.unlink(sam)
204

    
205
        # Filter out the guest account
206
        return filter(lambda x: x != "Guest", users)
207

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