Source for file wsus_sync.php

Documentation is available at wsus_sync.php

  1. #!/usr/bin/php
  2. <?php
  3. /**
  4.  * PHP version 5
  5.  *
  6.  * LICENSE: This program is free software; you can redistribute it and/or
  7.  * modify it under the terms of the GNU General Public License as published
  8.  * by the Free Software Foundation.
  9.  *
  10.  * @package        FreeNAC
  11.  * @author      Wolfram Strauss, Hector Ortiz (FreeNAC Core Team)
  12.  * @copyright   2006 FreeNAC
  13.  * @license     http://www.gnu.org/copyleft/gpl.html   GNU Public License Version 2
  14.  * @version     CVS: $Id:$
  15.  * @link        http://www.freenac.net
  16.  *
  17.  */
  18.  
  19.  
  20. /**
  21. * Obtain update status from the wsus database and store locally.
  22. */
  23.  
  24.  
  25. /*************************************
  26.         MAIN
  27. **************************************/
  28.  
  29.  
  30. // Php weirdness: change to script dir, then look for includes
  31. chdir(dirname(__FILE__));
  32. set_include_path("../:./");
  33.  
  34.  
  35. /**
  36. * Load settings and common functions
  37. */
  38. require_once "./funcs.inc.php";     
  39.  
  40. global $logger;
  41. $logger->setLogToStdOut(false);
  42. $output=true;
  43. $logger->setDebugLevel(0);
  44.  
  45.  
  46. // this timestamp is used as the sync date for data synced from the wsus db to the freenac db
  47. $timestamp=date('Y-m-d H:i:s');
  48. $logger->logit("Starting WSUS Database sync job");
  49.  
  50. db_connect();    // vmps db connection (mysql)
  51. $enabled=v_sql_1_select("select value from config where name='wsus_enabled'");
  52.  
  53. if$enabled )
  54. {
  55.     dbwsus_connect();    // wsus db connection (mssql)
  56.  
  57.     // warning!! this should be done within a transaction
  58.     
  59.     if!empty_tables() ) {
  60.         $logger->logit("Failed to empty all wsus tables, logical status may be inconsistend!"LOG_ERR);
  61.         cleanup();
  62.     }
  63.     
  64.     if!get_global_update_list() ) {
  65.         $logger->logit("Failed to sync global update list"LOG_ERR);
  66.         cleanup();
  67.     }
  68.     
  69.     if!get_systems() ) {
  70.         $logger->logit("Failed to sync systems list"LOG_ERR);
  71.         cleanup;
  72.     }
  73.     
  74.     cleanup();
  75.     
  76. }
  77. else
  78. {
  79.     $logger->logit("WSUS support not enabled"LOG_WARNING);
  80. }
  81.     
  82.  
  83.     
  84. /*******************************
  85.     FUNCTIONS
  86. *******************************/
  87.     
  88.  
  89. /**
  90. *  This function converts the datetime retrieved from MSSQL into MySQL datetime format
  91. */
  92. function convert_date($date)
  93. {
  94.    $date_array=getdate(strtotime($date));
  95.    $date=$date_array['year'].'-';
  96.    $date_array['mon'10 $date.='0'.$date_array['mon'].'-' $date.=$date_array['mon'].'-';
  97.    $date_array['mday'10 $date.='0'.$date_array['mday'].' ' $date.=$date_array['mday'].' ';
  98.    $date_array['hours'10 $date.='0'.$date_array['hours'].':' $date.=$date_array['hours'].':';
  99.    $date_array['minutes'10 $date.='0'.$date_array['minutes'].':' $date.=$date_array['minutes'].':';
  100.    $date_array['seconds'10 $date.='0'.$date_array['seconds'$date.=$date_array['seconds'];
  101.    return $date;
  102. }
  103.  
  104.  
  105. /**
  106. * Ensures that $string is mysql safe
  107. */
  108. function validate($string)
  109. {
  110.    rtrim($string,' ');
  111.    if (get_magic_quotes_gpc()) {
  112.       $value=stripslashes($string);
  113.    }
  114.    if (!is_numeric($string)) {
  115.       $stringmysql_real_escape_string($string);
  116.    }
  117.    return $string;
  118. }
  119.  
  120.  
  121. /**
  122. * Connect to the WSUS server
  123. */
  124. function dbwsus_connect()
  125. {
  126.    global $conf,$wsus_dbuser,$wsus_dbpass$logger;
  127.    $logger->debug("Connecting to ".$conf->wsus_dbalias." ".$conf->wsus_db1);
  128.    $msconnect mssql_connect($conf->wsus_dbalias$wsus_dbuser$wsus_dbpass);
  129.    if !$msconnect )
  130.    {
  131.      $logger->logit("Cannot connect to WSUS server ".$conf->wsus_dbalias.":" mssql_get_last_message()LOG_ERR);
  132.      return false;
  133.    }
  134.    $db mssql_select_db($conf->wsus_db$msconnect);
  135.    if !$db )
  136.    {
  137.       $logger->logit("Couldn't open database ".$conf->wsus_db." ".mssql_get_last_message()LOG_ERR);
  138.       return false;
  139.    }
  140. }
  141.  
  142.  
  143. /**
  144. * Returns the hostname part of an fqdn thus everything before the first dot
  145. */
  146. function get_hostname($fqdn)
  147. {
  148.     global $logger;
  149.     
  150.     $dot_pos strpos($fqdn'.');    // find position of first dot
  151.     $hostname;
  152.     if$dot_pos )
  153.     {
  154.         $hostname substr($fqdn0$dot_pos);    // take everything before the first dot
  155.     }
  156.     else
  157.     {
  158.         $hostname $fqdn;
  159.     }
  160.     
  161.     $logger->debug("Converting $fqdn to $hostname"2);
  162.     
  163.     return strtolower($hostname);
  164. }
  165.  
  166. /**
  167. * Look up a wsus hostname in the vmps table and return the vmps id if and only if there's exactly one entry
  168. */
  169. function get_vmps_id($hostname)
  170. {
  171.     global $logger;
  172.     
  173.     $logger->debug("Looking for vmps system id for hostname $hostname"1);
  174.     
  175.     $query "select id from systems where substring_index(last_hostname, '.', 1) = '$hostname';";
  176.     $logger->debug("Executing: $query"3);
  177.     $result mysql_query($query);
  178.     if!$result )
  179.     {
  180.         $logger->logit("Could not obtain vmps id for $hostnamemysql_error()LOG_WARNING);
  181.         return false;
  182.     }
  183.     $num_rows mysql_num_rows($result);    //TODO: exception handling
  184.     if$num_rows == )
  185.     {
  186.         //$logger->logit("No vmps id for system $hostname found", LOG_WARNING);
  187.         $logger->logit("No vmps id for system $hostname found");// don't flag as warning until 100% right, its flooding logcheck
  188.         return false;
  189.     }
  190.     elseif$num_rows == )
  191.     {
  192.         $row mysql_fetch_row($result);    //TODO: exception handling
  193.         $logger->debug("hostname $hostname has vmps id $row[0]"1);
  194.         return     $row[0];    
  195.     }
  196.     else
  197.     {
  198.         //$logger->logit("$hostname is not unique in vmps", LOG_WARNING);
  199.         $logger->logit("$hostname is not unique in vmps");// don't flag as warning until 100% right, its flooding logcheck
  200.         return false;
  201.     }
  202. }
  203.  
  204.     
  205. /**
  206. * Empty all wsus tables.
  207. */
  208. function empty_tables()
  209. {
  210.     global $logger;
  211.  
  212.     $logger->debug("Emptying wsus tables"1);
  213.     if!mysql_query('truncate table wsus_systems;') ) {
  214.         $logger->logit("Could not empty wsus_systems, " mysql_error()LOG_ERR);
  215.         return false;
  216.     }
  217.     if!mysql_query('truncate table wsus_neededUpdates;') ) {
  218.         $logger->logit("Could not empty wsus_neededUpdates, " mysql_error()LOG_ERR);
  219.         return false;
  220.     }
  221.     if!mysql_query('truncate table wsus_systemToUpdates;') ) {
  222.         $logger->logit("Could not empty wsus_systemToUpdate, " mysql_error()LOG_ERR);
  223.         return false;
  224.     }
  225.     
  226.     return true;
  227. }
  228.  
  229.  
  230. /**
  231. * Get global list of needed updates from wsus db and store in openac db
  232. */
  233. {
  234.     global $logger$timestamp;
  235.  
  236.     // A summarizationstate of 4 references updates that a properly installed. These are the only ones we are not interested in. Languageid 1033 is english, thus we only fetch the english descriptions for the udpates
  237.     $query "select distinct u.localupdateid, lp.title, lp.description, p.msrcseverity, p.creationdate, p.receivedfromcreatorservice from susdb.dbo.tbupdatestatuspercomputer us    left join susdb.dbo.tbupdate u on us.localupdateid = u.localupdateid left join dbo.tbrevision r on u.localupdateid = r.localupdateid    left join dbo.tbproperty p on r.revisionid = p.revisionid    left join dbo.tblocalizedpropertyforrevision lpr on r.revisionid = lpr.revisionid left join dbo.tblocalizedproperty lp on lpr.localizedpropertyid = lp.localizedpropertyid where (us.summarizationstate <> 4) and (us.summarizationstate <> 1) and lpr.languageid = 1033 and r.revisionid = (select max(r.revisionid) from tbrevision r where r.localupdateid = u.localupdateid)";
  238.     
  239.     $logger->debug("Executing: ".$query3);
  240.     $result mssql_query($query)
  241.     if!$result {
  242.         $logger->logit("Could not fetch global update list, " mssql_get_last_message()LOG_ERR);
  243.         return false;
  244.     }
  245.     
  246.     ;
  247.     while$row mssql_fetch_assoc($result) )
  248.     {
  249.         $query sprintf("insert into wsus_neededUpdates(localupdateid, title, description, msrcseverity, creationdate, receiveddate, lastsync) values('%s', '%s', '%s', '%s', '%s', '%s', '%s');"validate($row['localupdateid'])validate($row['title'])validate($row['description'])validate($row['msrcseverity'])convert_date($row['creationdate'])convert_date($row['receivedfromcreatorservice'])$timestamp);
  250.         $logger->debug("Executing: $query"3);
  251.         
  252.         if!mysql_query($query) )
  253.         {
  254.             $logger->logit("Could insert update list into vmps db, " mysql_error()LOG_ERR);
  255.             return false;
  256.         }
  257.     }
  258.  
  259.     return true;
  260. }    
  261.     
  262.     
  263. /**
  264. * Obtain list of system which are registerd in the wsus server, fetch their status for each  necessary update and write everything into the vmps db
  265. */
  266. function get_systems()
  267. {
  268.     global $logger$timestamp;
  269.  
  270.     $query "select t.targetid, t.fulldomainname, t.ipaddress, t.lastreportedstatustime, s.notinstalled, s.downloaded, s.installedpendingreboot, s.failed, d.computermake, d.computermodel, o.oslongname from dbo.tbcomputertarget t left join dbo.tbcomputersummaryformicrosoftupdates s on t.targetid = s.targetid left join dbo.tbcomputertargetdetail d on t.targetid = d.targetid left join dbo.tbosmap o on (d.osminorversion = o.osminorversion and d.osmajorversion = o.osmajorversion and d.osservicepackmajornumber = o.osservicepackmajornumber) where (o.processorarchitecture is null or o.processorarchitecture = 1)";
  271.     
  272.     $logger->debug("Executing: $query"3);
  273.     $result mssql_query($query);
  274.     if!$result )
  275.     {
  276.         $logger->logit("Failed to obtain systems from wsus, " mssql_get_last_message()LOG_ERR);
  277.         return false;
  278.     }
  279.     
  280.     while$sys_row mssql_fetch_assoc($result) )
  281.     {
  282.         $hostname get_hostname($sys_row['fulldomainname']);
  283.         $id get_vmps_id($hostname);
  284.         if!$id )
  285.         {
  286.             continue;
  287.         }
  288.         
  289.         
  290.         $query sprintf("select us.localupdateid from dbo.tbupdatestatuspercomputer us where (us.summarizationstate <> 4) and (us.summarizationstate <> 1) and us.targetid = '%s'"$sys_row['targetid']);
  291.         $logger->debug("Executing: $query"3);
  292.         $result_update mssql_query($query);
  293.         if!$result )    // whenever there occurs an error we skip the current system and continue with the next one
  294.         {
  295.             $logger->logit("Could not fetch update details for " $sys_row['fulldomainname'", skipping this system"LOG_WARNING);
  296.             continue;
  297.         }
  298.         // insert system into wsus_systems
  299.         $query sprintf("insert into wsus_systems values('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s');"$id$hostnamevalidate($sys_row['ipaddress'])convert_date($sys_row['lastreportedstatustime'])validate($sys_row['oslongname'])validate($sys_row['computermake'])validate($sys_row['computermodel'])validate($sys_row['notinstalled'])validate($sys_row['downloaded'])validate($sys_row['installedpendingreboot'])validate($sys_row['failed'])$timestamp);
  300.         
  301.         $logger->debug("Executing: $query"3);
  302.         if!mysql_query($query) )
  303.         {
  304.             $logger->logit("Could not insert system $hostnamemysql_error()LOG_WARNING);
  305.             continue;
  306.         }
  307.         
  308.         // insert mapping to needed updates
  309.         while$update_row mssql_fetch_assoc($result_update) )
  310.         {
  311.             $query sprintf("insert into wsus_systemToUpdates(sid, localupdateid, lastsync) values('%s', '%s', '%s');"$idvalidate($update_row['localupdateid'])$timestamp);
  312.             $logger->debug("Executing $query"3);
  313.             if!mysql_query($query) )
  314.             {
  315.                 $logger->logit("Could not insert update relation $id$update_row['localupdateid']LOG_WARNING);
  316.             }
  317.         }
  318.     }
  319.     
  320.     return true;
  321. }
  322.  
  323.  
  324. /**
  325. *
  326. */
  327. function cleanup()
  328. {
  329.     global $logger;
  330.     
  331.     // TODO: exception handling    
  332.     
  333.     mssql_close();
  334.     mysql_close();
  335.     
  336.     $logger->logit("Done syncing WSUS");
  337.     
  338.     exit;
  339. }
  340.     
  341.     
  342. ?>

Documentation generated on Mon, 01 Dec 2008 01:10:54 +0100 by phpDocumentor 1.4.0