Statistics
| Branch: | Tag: | Revision:

root / image_creator / os_type / windows.py @ 640096fb

History | View | Annotate | Download (6.2 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
41

    
42
import hivex
43
import tempfile
44
import os
45

    
46

    
47
class Windows(OSBase):
48
    """OS class for Windows"""
49

    
50
    @sysprep(enabled=False)
51
    def remove_user_accounts(self, print_header=True):
52
        """Remove all user accounts with id greater than 1000"""
53
        pass
54
 
55
    def do_sysprep(self):
56
        """Prepare system for image creation."""
57

    
58
        if getattr(self, 'syspreped', False):
59
            raise FatalError("Image is already syspreped!")
60

    
61
        self.mount(readonly=False)
62
        try:
63
            disabled_uac = self._update_uac_remote_setting(1)
64
        finally:
65
            self.umount()
66

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

    
76
        self.out.success('done')
77

    
78
        self.out.output("Starting windows VM ...", False)
79
        try:
80
            pass
81
        finally:
82
            self.out.output("Relaunching helper VM (may take a while) ...",
83
                            False)
84
            self.g.launch()
85
            self.out.success('done')
86

    
87
        if disabled_uac:
88
            self._update_uac_remote_setting(0)
89

    
90
        self.syspreped = True
91

    
92
    def _registry_file_path(self, regfile):
93
        """Retrieves the case sensitive path to a registry file"""
94

    
95
        systemroot = self.g.inspect_get_windows_systemroot(self.root)
96
        path = "%s/system32/config/%s" % (systemroot, regfile)
97
        try:
98
            path = self.g.case_sensitive_path(path)
99
        except RuntimeError as e:
100
            raise FatalError("Unable to retrieve registry file: %s. Reason: %s"
101
                             % (regfile, str(e)))
102
        return path
103

    
104
    def _update_uac_remote_setting(self, value):
105
        """Updates the registry key value:
106
        [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies
107
        \System]"LocalAccountTokenFilterPolicy"
108

109
        value = 1 will disable the UAC remote restrictions
110
        value = 0 will enable the UAC remote restrictions
111

112
        For more info see here: http://support.microsoft.com/kb/951016
113

114
        Returns:
115
            True if the key is changed
116
            False if the key is unchanged
117
        """
118

    
119
        if value not in (0, 1):
120
            raise ValueError("Valid values for value parameter are 0 and 1")
121

    
122
        path = self._registry_file_path('SOFTWARE')
123
        softwarefd, software = tempfile.mkstemp()
124
        try:
125
            os.close(softwarefd)
126
            self.g.download(path, software)
127

    
128
            h = hivex.Hivex(software, write=True)
129

    
130
            key = h.root()
131
            for child in ('Microsoft', 'Windows', 'CurrentVersion', 'Policies',
132
                          'System'):
133
                key = h.node_get_child(key, child)
134

    
135
            policy = None
136
            for val in h.node_values(key):
137
                if h.value_key(val) == "LocalAccountTokenFilterPolicy":
138
                    policy = val
139

    
140
            if policy is not None:
141
                dword = h.value_dword(policy)
142
                if dword == value:
143
                    return False
144
            elif value == 0:
145
                return False
146

    
147
            new_value = {
148
                'key': "LocalAccountTokenFilterPolicy", 't': 4L,
149
                'value': '%s\x00\x00\x00' % '\x00' if value == 0 else '\x01'}
150

    
151
            h.node_set_value(key, new_value)
152
            h.commit(None)
153

    
154
            self.g.upload(software, path)
155

    
156
        finally:
157
            os.unlink(software)
158

    
159
        return True
160

    
161
    def _do_collect_metadata(self):
162
        """Collect metadata about the OS"""
163
        super(Windows, self)._do_collect_metadata()
164
        self.meta["USERS"] = " ".join(self._get_users())
165

    
166
    def _get_users(self):
167
        """Returns a list of users found in the images"""
168
        path = self._registry_file_path('SAM')
169
        samfd, sam = tempfile.mkstemp()
170
        try:
171
            os.close(samfd)
172
            self.g.download(path, sam)
173

    
174
            h = hivex.Hivex(sam)
175

    
176
            key = h.root()
177
            # Navigate to /SAM/Domains/Account/Users/Names
178
            for child in ('SAM', 'Domains', 'Account', 'Users', 'Names'):
179
                key = h.node_get_child(key, child)
180

    
181
            users = [h.node_name(x) for x in h.node_children(key)]
182

    
183
        finally:
184
            os.unlink(sam)
185

    
186
        # Filter out the guest account
187
        return filter(lambda x: x != "Guest", users)
188

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