Ejemplo n.º 1
0
    def _execute_command(self, device, command):
        """
        Create WinRS client and run the command remotely.
        """
        winrs = SingleCommandClient(self._conn_info(device))
        result = winrs.run_command(str(command))

        result.addCallback(lambda res: self._on_success(device, res, command))
        result.addErrback(lambda err: self._on_error(device, err))
    def _execute_command(self, device, command):
        """
        Create WinRS client and run the command remotely.
        """
        winrs = SingleCommandClient(self._conn_info(device))
        result = winrs.run_command(str(command))

        result.addCallback(lambda res: self._on_success(device, res, command))
        result.addErrback(lambda err: self._on_error(device, err))
Ejemplo n.º 3
0
class IISCommander(object):
    def __init__(self, conn_info):
        self.winrs = SingleCommandClient(conn_info)

    PS_COMMAND = "powershell -NoLogo -NonInteractive -NoProfile " \
        "-OutputFormat TEXT -Command "

    IIS_COMMAND = '''
        $iisversion = get-itemproperty HKLM:\SOFTWARE\Microsoft\InetStp\ | select versionstring;
        Write-Host $iisversion.versionstring;
    '''

    def get_app_pool_status(self):
        script = '"& {$Host.UI.RawUI.BufferSize = New-Object Management.Automation.Host.Size(4096, 1024);'\
                 ' get-counter \'\APP_POOL_WAS(*)\Current Application Pool State\'}'
        return self.winrs.run_command(self.PS_COMMAND, ps_script=script)

    def get_iis_version(self):
        script = '"& {{{}}}"'.format(self.IIS_COMMAND.replace('\n', ' '))
        return self.winrs.run_command(self.PS_COMMAND, ps_script=script)
Ejemplo n.º 4
0
    def collect(self, config):
        dsconf0 = config.datasources[0]
        conn_info = createConnectionInfo(dsconf0)

        strategy = queryUtility(IStrategy, dsconf0.params['strategy'])

        if not strategy:
            raise WindowsShellException("No strategy chosen for {0}".format(
                dsconf0.datasource))

        counters = [dsconf.params['resource'] for dsconf in config.datasources]

        if dsconf0.params['strategy'].startswith('powershell MSSQL'):
            cmd_line_input, conn_info = self.getSQLConnection(
                dsconf0, conn_info)
            if dsconf0.params['strategy'] == 'powershell MSSQL Instance':
                owner_node, server = dsconf.cluster_node_server.split('//')
                if len(server.split('\\')) < 2:
                    cmd_line_input = 'MSSQLSERVER'
                else:
                    cmd_line_input = dsconf0.params['instanceid']
            if dsconf.params['strategy'] == 'powershell MSSQL' or\
                    dsconf.params['strategy'] == 'powershell MSSQL Job':
                conn_info = conn_info._replace(timeout=dsconf0.cycletime - 5)
            command_line, script = strategy.build_command_line(cmd_line_input)
        elif dsconf0.params['strategy'] == 'Custom Command':
            check_datasource(dsconf0)
            script = dsconf0.params['script']
            usePowershell = dsconf0.params['usePowershell']
            command_line, script = strategy.build_command_line(
                script, usePowershell)
        elif dsconf0.params['strategy'] == 'DCDiag':
            testparms = [
                dsconf.params['script'] for dsconf in config.datasources
                if dsconf.params['script']
            ]
            command_line = strategy.build_command_line(
                counters, testparms, dsconf0.windows_user,
                dsconf0.windows_password)
            conn_info = conn_info._replace(timeout=180)
            script = None
        else:
            command_line, script = strategy.build_command_line(counters)

        command = SingleCommandClient(conn_info)
        self.start = time.mktime(time.localtime())
        results = yield command.run_command(command_line, script)

        defer.returnValue((strategy, config.datasources, results))
    def collect(self, config):
        dsconf0 = config.datasources[0]
        conn_info = createConnectionInfo(dsconf0)

        strategy = queryUtility(IStrategy, dsconf0.params['strategy'])

        if not strategy:
            raise WindowsShellException(
                "No strategy chosen for {0}".format(dsconf0.datasource)
            )

        counters = [dsconf.params['resource'] for dsconf in config.datasources]

        if dsconf0.params['strategy'].startswith('powershell MSSQL'):
            cmd_line_input, conn_info = self.getSQLConnection(dsconf0,
                                                              conn_info)
            if dsconf0.params['strategy'] == 'powershell MSSQL Instance':
                owner_node, server = dsconf.cluster_node_server.split('//')
                if len(server.split('\\')) < 2:
                    cmd_line_input = 'MSSQLSERVER'
                else:
                    cmd_line_input = dsconf0.params['instanceid']
            if dsconf.params['strategy'] == 'powershell MSSQL' or\
                    dsconf.params['strategy'] == 'powershell MSSQL Job':
                conn_info = conn_info._replace(timeout=dsconf0.cycletime - 5)
            command_line, script = strategy.build_command_line(cmd_line_input)
        elif dsconf0.params['strategy'] == 'Custom Command':
            check_datasource(dsconf0)
            script = dsconf0.params['script']
            usePowershell = dsconf0.params['usePowershell']
            command_line, script = strategy.build_command_line(script, usePowershell)
        elif dsconf0.params['strategy'] == 'DCDiag':
            testparms = [dsconf.params['script'] for dsconf in config.datasources if dsconf.params['script']]
            command_line = strategy.build_command_line(counters, testparms, dsconf0.windows_user, dsconf0.windows_password)
            conn_info = conn_info._replace(timeout=180)
            script = None
        else:
            command_line, script = strategy.build_command_line(counters)

        command = SingleCommandClient(conn_info)
        self.start = time.mktime(time.localtime())
        results = yield command.run_command(command_line, script)

        defer.returnValue((strategy, config.datasources, results))
class ClusterCommander(object):
    def __init__(self, conn_info):
        self.winrs = SingleCommandClient(conn_info)

    pscommand = "powershell -NoLogo -NonInteractive -NoProfile " \
        "-OutputFormat TEXT -Command "

    psClusterCommands = []
    psClusterCommands.append("$Host.UI.RawUI.BufferSize = New-Object Management.Automation.Host.Size (512, 512);")
    psClusterCommands.append("import-module failoverclusters;")

    def run_command(self, command):
        """Run command for powershell failover clusters"""
        if isinstance(command, str):
            command = command.splitlines()
        command = "\"& {{{}}}\"".format(
            ''.join(self.psClusterCommands + command)
        )
        return self.winrs.run_command(self.pscommand, ps_script=command)
Ejemplo n.º 7
0
class ClusterCommander(object):
    def __init__(self, conn_info):
        self.winrs = SingleCommandClient(conn_info)

    pscommand = "powershell -NoLogo -NonInteractive -NoProfile " \
        "-OutputFormat TEXT -Command "

    psClusterCommands = []
    psClusterCommands.append(
        "$Host.UI.RawUI.BufferSize = New-Object Management.Automation.Host.Size (512, 512);"
    )
    psClusterCommands.append("import-module failoverclusters;")

    def run_command(self, command):
        """Run command for powershell failover clusters"""
        if isinstance(command, str):
            command = command.splitlines()
        command = "\"& {{{}}}\"".format(''.join(self.psClusterCommands +
                                                command))
        return self.winrs.run_command(self.pscommand, ps_script=command)
Ejemplo n.º 8
0
class EventLogQuery(object):
    def __init__(self, conn_info):
        self.winrs = SingleCommandClient(conn_info)

    PS_COMMAND = "powershell -NoLogo -NonInteractive -NoProfile " \
        "-OutputFormat TEXT -Command "

    PS_SCRIPT = '''
        $FormatEnumerationLimit = -1;
        $Host.UI.RawUI.BufferSize = New-Object Management.Automation.Host.Size(4096, 1024);
        function sstring($s) {{
            if ($s -eq $null) {{
                return "";
            }};
            if ($s.GetType() -eq [System.Security.Principal.SecurityIdentifier]) {{
                [String]$s = $s.Translate( [System.Security.Principal.NTAccount]);
            }} elseif ($s.GetType() -ne [String]) {{
                [String]$s = $s;
            }};
            $s = $s.replace("`r","").replace("`n"," ");
            $s = $s.replace('"', '\\"').replace("\\'","'");
            $s = $s.replace("`t", " ");
            return "$($s)".replace('\\','\\\\').trim();
        }};
        function EventLogToJSON {{
            begin {{
                $first = $True;
                '['
            }}
            process {{
                if ($first) {{
                    $separator = "";
                    $first = $False;
                }} else {{
                    $separator = ",";
                }}
                $separator + "{{
                    `"EntryType`": `"$(sstring($_.EntryType))`",
                    `"TimeGenerated`": `"$(sstring($_.TimeGenerated))`",
                    `"Source`": `"$(sstring($_.Source))`",
                    `"InstanceId`": `"$(sstring($_.InstanceId))`",
                    `"Message`": `"$(sstring($_.Message))`",
                    `"UserName`": `"$(sstring($_.UserName))`",
                    `"MachineName`": `"$(sstring($_.MachineName))`",
                    `"EventID`": `"$(sstring($_.EventID))`"
                }}"
            }}
            end {{
                ']'
            }}
        }};
        function EventLogRecordToJSON {{
            begin {{
                $first = $True;
                '['
            }}
            process {{
                if ($first) {{
                    $separator = "";
                    $first = $False;
                }} else {{
                    $separator = ",";
                }}
                $separator + "{{
                    `"EntryType`": `"$(sstring($_.LevelDisplayName))`",
                    `"TimeGenerated`": `"$(sstring($_.TimeCreated))`",
                    `"Source`": `"$(sstring($_.ProviderName))`",
                    `"InstanceId`": `"$(sstring($_.Id))`",
                    `"Message`": `"$(if ($_.Message){{$(sstring($_.Message))}}else{{$(sstring($_.FormatDescription()))}})`",
                    `"UserName`": `"$(sstring($_.UserId))`",
                    `"MachineName`": `"$(sstring($_.MachineName))`",
                    `"EventID`": `"$(sstring($_.Id))`"
                }}"
            }}
            end {{
                ']'
            }}
        }};
        function get_new_recent_entries($logname, $selector, $max_age, $eventid) {{
            $x=New-Item HKCU:\SOFTWARE\zenoss -ea SilentlyContinue;
            $x=New-Item HKCU:\SOFTWARE\zenoss\logs -ea SilentlyContinue;
            $last_read = Get-ItemProperty -Path HKCU:\SOFTWARE\zenoss\logs -Name  $eventid -ea SilentlyContinue;
            [DateTime]$yesterday = (Get-Date).AddHours(-$max_age);
            [DateTime]$after = $yesterday;
            if ($last_read) {{
                $last_read = [DateTime]$last_read.$eventid;
                if ($last_read -gt $yesterday) {{
                    $after = $last_read;
                }};
            }};
            $win2003 = [environment]::OSVersion.Version.Major -lt 6;
            $dotnets = Get-ChildItem 'HKLM:\\software\\microsoft\\net framework setup\\ndp'| % {{$_.name.split('\\')[5]}} | ? {{ $_ -match 'v3.5|v[45].*'}};
            if ($win2003 -eq $false -and $dotnets -ne $null) {{
                $query = '{filter_xml}';
                [Array]$events = Get-WinEvent -FilterXml $query.replace("{{logname}}",$logname).replace("{{time}}", ((Get-Date) - $after).TotalMilliseconds);
            }} else {{
                [Array]$events = Get-EventLog -After $after -LogName $logname;
            }};
            [DateTime]$last_read = get-date;
            Set-Itemproperty -Path HKCU:\SOFTWARE\zenoss\logs -Name $eventid -Value ([String]$last_read);
            if ($events -eq $null) {{
                return;
            }};
            if($events) {{
                [Array]::Reverse($events);
            }};
            if ($win2003 -and $dotnets -eq $null) {{
                @($events | ? $selector) | EventLogToJSON
            }}
            else {{
                @($events | ? $selector) | EventLogRecordToJSON
            }}
        }};
        get_new_recent_entries -logname "{eventlog}" -selector {selector} -max_age {max_age} -eventid "{eventid}";
    '''

    def run(self, eventlog, selector, max_age, eventid, isxml):
        if selector.strip() == '*':
            selector = '{$True}'
        else:
            selector = selector.replace('\n', ' ').replace('"', r'\"')

        if isxml:
            filter_xml = selector
            selector = '{$True}'
        else:
            filter_xml = FILTER_XML.replace('"', r'\"')
        ps_script = ' '.join([x.strip() for x in self.PS_SCRIPT.split('\n')])
        script = "\"& {{{}}}\"".format(
            ps_script.replace('\n', ' ').replace('"', r'\"').format(
                eventlog=eventlog or 'System',
                selector=selector or '{$True}',
                max_age=max_age or '24',
                eventid=eventid,
                filter_xml=filter_xml))
        log.debug('sending event script: {}'.format(script))
        return self.winrs.run_command(self.PS_COMMAND, ps_script=script)
Ejemplo n.º 9
0
class SQLCommander(object):
    '''
    Custom WinRS client to construct and run PowerShell commands.
    '''
    def __init__(self, conn_info):
        self.winrs = SingleCommandClient(conn_info)

    PS_COMMAND = "powershell -NoLogo -NonInteractive -NoProfile " \
        "-OutputFormat TEXT -Command "

    LOCAL_INSTANCES_PS_SCRIPT = '''
        <# Get registry key for instances (with 2003 or 32/64 Bit 2008 base key) #>
        $reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine', $hostname);
        $baseKeys = 'SOFTWARE\Microsoft\Microsoft SQL Server',
            'SOFTWARE\Wow6432Node\Microsoft\Microsoft SQL Server';
        foreach ($regPath in $baseKeys) {
            $regKey= $reg.OpenSubKey($regPath);
            If ($regKey -eq $null) {Continue};

            <# Get installed instances' names (both cluster and local) #>
            If ($regKey.GetSubKeyNames() -contains 'Instance Names') {
                $regKey = $reg.OpenSubKey($regpath+'\Instance Names\SQL');
                $instances = @($regkey.GetValueNames());
            } ElseIf ($regKey.GetValueNames() -contains 'InstalledInstances') {
                $instances = $regKey.GetValue('InstalledInstances');
            } Else {Continue};

            <# Get only local instances' names #>
            $local_instances = New-Object System.Collections.Arraylist;
            $instances | % {
                $instanceValue = $regKey.GetValue($_);
                $instanceReg = $reg.OpenSubKey($regpath+'\\'+$instanceValue);
                If ($instanceReg.GetSubKeyNames() -notcontains 'Cluster') {
                    $version = $instanceReg.OpenSubKey('MSSQLServer\CurrentVersion').GetValue('CurrentVersion');
                    $instance_ver = $_;$instance_ver+=':';$instance_ver+=$version;
                    $local_instances += $_+':'+$version;
                };
            };
            break;
        };
        $local_instances | % {write-host \"instances:\"$_};
    '''

    CLUSTER_INSTANCES_PS_SCRIPT = '''
        $domain = (gwmi WIN32_ComputerSystem).Domain;
        Import-Module FailoverClusters;
        $cluster_instances = Get-ClusterResource
            | ? {$_.ResourceType -like 'SQL Server'}
            | % {$ownernode = $_.OwnerNode; $_
            | Get-ClusterParameter -Name VirtualServerName,InstanceName
            | Group ClusterObject | Select
            @{Name='SQLInstance';Expression={($_.Group | select -expandproperty Value) -join '\\'}},
            @{Name='OwnerNode';Expression={($ownernode, $domain) -join '.'}}};
        $cluster_instances | % {write-host \"instances:\"($_).OwnerNode\($_).SQLInstance};
    '''

    HOSTNAME_PS_SCRIPT = '''
        $hostname = hostname; write-host \"hostname:\"$hostname;
    '''

    def get_instances_names(self, is_cluster):
        """Run script to retrieve DB instances' names and hostname either
        available in the cluster or installed on the local machine,
        according to the 'is_cluster' parameter supplied.
        """
        psinstance_script = self.CLUSTER_INSTANCES_PS_SCRIPT if is_cluster \
            else self.LOCAL_INSTANCES_PS_SCRIPT
        return self.run_command(psinstance_script + self.HOSTNAME_PS_SCRIPT)

    @defer.inlineCallbacks
    def run_command(self, pscommand):
        """Run PowerShell command."""
        buffer_size = ('$Host.UI.RawUI.BufferSize = New-Object '
                       'Management.Automation.Host.Size (4096, 512);')
        script = "\"{0} & {{{1}}}\"".format(buffer_size,
                                            pscommand.replace('\n', ' '))
        results = yield self.winrs.run_command(self.PS_COMMAND,
                                               ps_script=script)
        defer.returnValue(results)
 def collect(self, config):
     conn_info = createConnectionInfo(config.datasources[0])
     command = SingleCommandClient(conn_info)
     pscommand, script = self.build_command_line()
     results = yield command.run_command(pscommand, script)
     defer.returnValue(results)
class SQLCommander(object):
    '''
    Custom WinRS client to construct and run PowerShell commands.
    '''

    def __init__(self, conn_info, log):
        self.winrs = SingleCommandClient(conn_info)
        self.log = log

    PS_COMMAND = "powershell -NoLogo -NonInteractive -NoProfile " \
        "-OutputFormat TEXT -Command "

    LOCAL_INSTANCES_PS_SCRIPT = '''
        <# Get registry key for instances (with 2003 or 32/64 Bit 2008 base key) #>
        $reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine', $hostname);
        $baseKeys = 'SOFTWARE\Microsoft\Microsoft SQL Server',
            'SOFTWARE\Wow6432Node\Microsoft\Microsoft SQL Server';
        foreach ($regPath in $baseKeys) {
            $regKey= $reg.OpenSubKey($regPath);
            If ($regKey -eq $null) {Continue};

            <# Get installed instances' names (both cluster and local) #>
            If ($regKey.GetSubKeyNames() -contains 'Instance Names') {
                $regKey = $reg.OpenSubKey($regpath+'\Instance Names\SQL');
                $instances = @($regkey.GetValueNames());
            } ElseIf ($regKey.GetValueNames() -contains 'InstalledInstances') {
                $instances = $regKey.GetValue('InstalledInstances');
            } Else {Continue};

            <# Get only local instances' names #>
            $local_instances = New-Object System.Collections.Arraylist;
            $instances | % {
                $instanceValue = $regKey.GetValue($_);
                $instanceReg = $reg.OpenSubKey($regpath+'\\'+$instanceValue);
                If ($instanceReg.GetSubKeyNames() -notcontains 'Cluster') {
                    $version = $instanceReg.OpenSubKey('MSSQLServer\CurrentVersion').GetValue('CurrentVersion');
                    $instance_ver = $_;$instance_ver+=':';$instance_ver+=$version;
                    $local_instances += $_+':'+$version;
                };
            };
            break;
        };
        $local_instances | % {write-host \"instances:\"$_};
    '''

    CLUSTER_INSTANCES_PS_SCRIPT = '''
        $domain = (gwmi WIN32_ComputerSystem).Domain;
        Import-Module FailoverClusters;
        $cluster_instances = Get-ClusterResource
            | ? {$_.ResourceType -like 'SQL Server'}
            | % {$ownernode = $_.OwnerNode; $_
            | Get-ClusterParameter -Name VirtualServerName,InstanceName
            | Group ClusterObject | Select
            @{Name='SQLInstance';Expression={($_.Group | select -expandproperty Value) -join '\\'}},
            @{Name='OwnerNode';Expression={($ownernode, $domain) -join '.'}},
            @{Name='IPv4';Expression={[regex]::match((ping -4 -a -n 1 $ownernode|
            select-string 'Pinging').ToString(), '(\\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\b)').value}}};
        $cluster_instances | % {write-host \"instances:\"($_).OwnerNode\($_).IPv4\($_).SQLInstance};
    '''

    HOSTNAME_PS_SCRIPT = '''
        $hostname = hostname; write-host \"hostname:\"$hostname;
    '''

    def get_instances_names(self, is_cluster):
        """Run script to retrieve DB instances' names and hostname either
        available in the cluster or installed on the local machine,
        according to the 'is_cluster' parameter supplied.
        """
        psinstance_script = self.CLUSTER_INSTANCES_PS_SCRIPT if is_cluster \
            else self.LOCAL_INSTANCES_PS_SCRIPT
        return self.run_command(
            psinstance_script + self.HOSTNAME_PS_SCRIPT
        )

    @defer.inlineCallbacks
    def run_command(self, pscommand):
        """Run PowerShell command."""
        buffer_size = ('$Host.UI.RawUI.BufferSize = New-Object '
                       'Management.Automation.Host.Size (4096, 512);')
        script = "\"& {{{0} {1}}}\"".format(
            buffer_size, pscommand.replace('\n', ' '))
        self.log.debug(script)
        results = yield self.winrs.run_command(self.PS_COMMAND, ps_script=script)
        defer.returnValue(results)
    def collect(self, device, log):
        """
        Collect results of the class' queries and commands.

        This method can be overridden if more complex collection is
        required.
        """
        try:
            conn_info = self.conn_info(device)
        except UnauthorizedError as e:
            msg = "Error on {}: {}".format(device.id, e.message)
            self._send_event(msg, device.id, ZenEventClasses.Error, eventClass='/Status/Winrm', summary=msg)
            raise e
        client = self.client(conn_info)

        results = {}
        queries = self.get_queries()
        if queries:
            query_map = {
                enuminfo: key for key, enuminfo in self.enuminfo_tuples()}

            # Silence winrm logging. We want to control the message.
            winrm_log = logging.getLogger('winrm')
            winrm_log.setLevel(logging.FATAL)

            try:
                query_results = yield client.do_collect(
                    query_map.iterkeys())
            except Exception as e:
                self.log_error(log, device, e)
            else:
                for info, data in query_results.iteritems():
                    results[query_map[info]] = data

        # Get associators.
        associators = self.get_associators()

        if associators:
            assoc_client = AssociatorClient(conn_info)
            for assoc_key, associator in associators.iteritems():
                try:
                    if not associator.get('kwargs'):
                        assoc_result = yield assoc_client.associate(
                            associator['seed_class'],
                            associator['associations'])
                    else:
                        assoc_result = yield assoc_client.associate(
                            associator['seed_class'],
                            associator['associations'],
                            **associator['kwargs'])

                except Exception as e:
                    if 'No results for seed class' in e.message:
                        message = 'No results returned for {}. Check WinRM server'\
                                  ' configuration and z properties.'.format(self.name())
                        e = Exception(message)
                    self.log_error(log, device, e)
                else:
                    results[assoc_key] = assoc_result

        # Get a copy of the class' commands.
        commands = dict(self.get_commands())

        # Add PowerShell commands to commands.
        powershell_commands = self.get_powershell_commands()
        if powershell_commands:
            for psc_key, psc in powershell_commands.iteritems():
                commands[psc_key] = '"& {{{}}}"'.format(psc)

        if commands:
            for command_key, command in commands.iteritems():
                winrs_client = SingleCommandClient(conn_info)
                try:
                    if command.startswith('"&'):
                        results[command_key] = yield winrs_client.run_command(POWERSHELL_PREFIX,
                                                                              ps_script=command)
                    else:
                        results[command_key] = yield winrs_client.run_command(command)
                except Exception as e:
                    self.log_error(log, device, e)

        msg = 'Collection completed for %s'
        for eventClass in ('/Status/Winrm', '/Status/Kerberos'):
            self._send_event(msg % device.id, device.id, ZenEventClasses.Clear, eventClass=eventClass)

        defer.returnValue(results)
class EventLogQuery(object):
    def __init__(self, conn_info):
        self.winrs = SingleCommandClient(conn_info)

    PS_COMMAND = "powershell -NoLogo -NonInteractive -NoProfile " \
        "-OutputFormat TEXT -Command "

    PS_SCRIPT = '''
        $FormatEnumerationLimit = -1;
        $Host.UI.RawUI.BufferSize = New-Object Management.Automation.Host.Size(4096, 1024);
        function sstring($s) {{
            if ($s -eq $null) {{
                return "";
            }};
            if ($s.GetType() -eq [System.Security.Principal.SecurityIdentifier]) {{
                [String]$s = $s.Translate( [System.Security.Principal.NTAccount]);
            }} elseif ($s.GetType() -ne [String]) {{
                [String]$s = $s;
            }};
            $s = $s.replace("`r","").replace("`n"," ");
            $s = $s.replace('"', '\\"').replace("\\'","'");
            $s = $s.replace("`t", " ");
            return "$($s)".replace('\\','\\\\').trim();
        }};
        function EventLogToJSON {{
            begin {{
                $first = $True;
                '['
            }}
            process {{
                if ($first) {{
                    $separator = "";
                    $first = $False;
                }} else {{
                    $separator = ",";
                }}
                $separator + "{{
                    `"EntryType`": `"$(sstring($_.EntryType))`",
                    `"TimeGenerated`": `"$(sstring($_.TimeGenerated))`",
                    `"Source`": `"$(sstring($_.Source))`",
                    `"InstanceId`": `"$(sstring($_.InstanceId))`",
                    `"Message`": `"$(sstring($_.Message))`",
                    `"UserName`": `"$(sstring($_.UserName))`",
                    `"MachineName`": `"$(sstring($_.MachineName))`",
                    `"EventID`": `"$(sstring($_.EventID))`"
                }}"
            }}
            end {{
                ']'
            }}
        }};
        function EventLogRecordToJSON {{
            begin {{
                $first = $True;
                '['
            }}
            process {{
                if ($first) {{
                    $separator = "";
                    $first = $False;
                }} else {{
                    $separator = ",";
                }}
                $separator + "{{
                    `"EntryType`": `"$(sstring($_.LevelDisplayName))`",
                    `"TimeGenerated`": `"$(sstring($_.TimeCreated))`",
                    `"Source`": `"$(sstring($_.ProviderName))`",
                    `"InstanceId`": `"$(sstring($_.Id))`",
                    `"Message`": `"$(if ($_.Message){{$(sstring($_.Message))}}else{{$(sstring($_.FormatDescription()))}})`",
                    `"UserName`": `"$(sstring($_.UserId))`",
                    `"MachineName`": `"$(sstring($_.MachineName))`",
                    `"EventID`": `"$(sstring($_.Id))`"
                }}"
            }}
            end {{
                ']'
            }}
        }};
        function get_new_recent_entries($logname, $selector, $max_age, $eventid) {{
            $x=New-Item HKCU:\SOFTWARE\zenoss -ea SilentlyContinue;
            $x=New-Item HKCU:\SOFTWARE\zenoss\logs -ea SilentlyContinue;
            $last_read = Get-ItemProperty -Path HKCU:\SOFTWARE\zenoss\logs -Name  $eventid -ea SilentlyContinue;
            [DateTime]$yesterday = (Get-Date).AddHours(-$max_age);
            [DateTime]$after = $yesterday;
            if ($last_read) {{
                $last_read = [DateTime]$last_read.$eventid;
                if ($last_read -gt $yesterday) {{
                    $after = $last_read;
                }};
            }};
            $win2003 = [environment]::OSVersion.Version.Major -lt 6;
            $dotnets = ($PSVersionTable.CLRVersion.Major + ($PSVersionTable.CLRVersion.Minor/10)) -ge 3.5;
            if ($win2003 -eq $false -and $dotnets -eq $true) {{
                $query = '{filter_xml}';
                [Array]$events = Get-WinEvent -FilterXml $query.replace("{{logname}}",$logname).replace("{{time}}", ((Get-Date) - $after).TotalMilliseconds);
            }} else {{
                [Array]$events = Get-EventLog -After $after -LogName $logname;
            }};
            [DateTime]$last_read = get-date;
            Set-Itemproperty -Path HKCU:\SOFTWARE\zenoss\logs -Name $eventid -Value ([String]$last_read);
            if ($events -eq $null) {{
                return;
            }};
            if($events) {{
                [Array]::Reverse($events);
            }};
            if ($win2003 -and $dotnets -eq $null) {{
                @($events | ? $selector) | EventLogToJSON
            }}
            else {{
                @($events | ? $selector) | EventLogRecordToJSON
            }}
        }};
        get_new_recent_entries -logname "{eventlog}" -selector {selector} -max_age {max_age} -eventid "{eventid}";
    '''

    def run(self, eventlog, selector, max_age, eventid, isxml):
        if selector.strip() == '*':
            selector = '{$True}'
        else:
            selector = selector.replace('\n', ' ').replace('"', r'\"')

        if isxml:
            filter_xml = selector
            selector = '{$True}'
        else:
            filter_xml = FILTER_XML.replace('"', r'\"')
        ps_script = ' '.join([x.strip() for x in self.PS_SCRIPT.split('\n')])
        script = "\"& {{{}}}\"".format(
            ps_script.replace('\n', ' ').replace('"', r'\"').format(
                eventlog=eventlog or 'System',
                selector=selector or '{$True}',
                max_age=max_age or '24',
                eventid=eventid,
                filter_xml=filter_xml
            )
        )
        log.debug('sending event script: {}'.format(script))
        return self.winrs.run_command(self.PS_COMMAND, ps_script=script)
 def collect(self, config):
     conn_info = createConnectionInfo(config.datasources[0])
     command = SingleCommandClient(conn_info)
     pscommand, script = self.build_command_line()
     results = yield command.run_command(pscommand, script)
     defer.returnValue(results)
    def collect(self, device, log):
        """
        Collect results of the class' queries and commands.

        This method can be overridden if more complex collection is
        required.
        """
        try:
            conn_info = self.conn_info(device)
        except UnauthorizedError as e:
            msg = "Error on {}: {}".format(device.id, e.message)
            self._send_event(msg,
                             device.id,
                             ZenEventClasses.Error,
                             eventClass='/Status/Winrm',
                             summary=msg)
            raise e
        client = self.client(conn_info)

        results = {}
        queries = self.get_queries()
        if queries:
            query_map = {
                enuminfo: key
                for key, enuminfo in self.enuminfo_tuples()
            }

            # Silence winrm logging. We want to control the message.
            winrm_log = logging.getLogger('winrm')
            winrm_log.setLevel(logging.FATAL)

            try:
                query_results = yield client.do_collect(query_map.iterkeys())
            except Exception as e:
                self.log_error(log, device, e)
            else:
                for info, data in query_results.iteritems():
                    results[query_map[info]] = data

        # Get associators.
        associators = self.get_associators()

        if associators:
            assoc_client = AssociatorClient(conn_info)
            for assoc_key, associator in associators.iteritems():
                try:
                    if not associator.get('kwargs'):
                        assoc_result = yield assoc_client.associate(
                            associator['seed_class'],
                            associator['associations'])
                    else:
                        assoc_result = yield assoc_client.associate(
                            associator['seed_class'],
                            associator['associations'], **associator['kwargs'])

                except Exception as e:
                    if 'No results for seed class' in e.message:
                        message = 'No results returned for {}. Check WinRM server'\
                                  ' configuration and z properties.'.format(self.name())
                        e = Exception(message)
                    self.log_error(log, device, e)
                else:
                    results[assoc_key] = assoc_result

        # Get a copy of the class' commands.
        commands = dict(self.get_commands())

        # Add PowerShell commands to commands.
        powershell_commands = self.get_powershell_commands()
        if powershell_commands:
            for psc_key, psc in powershell_commands.iteritems():
                commands[psc_key] = '"& {{{}}}"'.format(psc)

        if commands:
            for command_key, command in commands.iteritems():
                winrs_client = SingleCommandClient(conn_info)
                try:
                    if command.startswith('"&'):
                        results[command_key] = yield winrs_client.run_command(
                            POWERSHELL_PREFIX, ps_script=command)
                    else:
                        results[command_key] = yield winrs_client.run_command(
                            command)
                except Exception as e:
                    self.log_error(log, device, e)

        msg = 'Collection completed for %s'
        for eventClass in ('/Status/Winrm', '/Status/Kerberos'):
            self._send_event(msg % device.id,
                             device.id,
                             ZenEventClasses.Clear,
                             eventClass=eventClass)

        defer.returnValue(results)