Scheduled Tasks and FOG 0.32



  • Many of us have been experiencing issues with fog 0.32 where Scheduled Tasks do not show up in the web GUI. I’ve seen various discussions on these forums about the issue but no definitive fix. Hopefully this will provide a solution.

    Before I go any further into this I work for a large university in the UK who rely on group scheduled tasks. We re-image a large number of machines each week based on group schedules including our IT Suites and Seminar rooms. Until a few weeks ago we had been using FOG 0.29 but decided to upgrade to 0.32 to find this bug.

    For reference we are running FOG with CentOS 6.5, PHP 5.3.3, MySQL 5.1.73

    Though you can schedule single host tasks and group tasks the webGUI will not display the scheduled tasks to allow you to delete them.

    !http://fogproject.org/forum/threads/call-to-undefined-method-group-addmember.1008/. The instructions given were to comment out some of the code which got the GUI working however it stopped group scheduled tasks from running. Host scheduled tasks continued to work.

    The instructions from Ritchy_Purple were as follows (I’ve put them here for reference - do not follow them!):

    Modify FOGCore.class.php
    line 137
    [php]else if ( $group != null )
    {
    //add copy from below
    $task = new ScheduledTask( $host, $group, $timer, $ar[“stTaskType”], $ar[“stID”] );
    $task->setShutdownAfterTask( $ar[“stShutDown”] == 1 );
    $task->setOther1( $ar[“stOther1”] );
    $task->setOther2( $ar[“stOther2”] );
    $task->setOther3( $ar[“stOther3”] );
    $task->setOther4( $ar[“stOther4”] );
    $task->setOther5( $ar[“stOther5”] );
    $arTasks[] = $task;
    // start Comment
    /* if ( $group->getCount() > 0 )
    {
    $arRm = array();
    $hosts = $group->getMembers();
    for( $i = 0; $i < count($hosts); $i++ )
    {
    if ( $hosts[$i] != null )
    {
    $h = $hosts[$i];
    if ( ! ($h->isReadyToImage() && $h->getImage()->getStorageGroup()->getID() == $groupid ) )
    {
    $arRm[] = $h;
    }
    }
    }

    //echo ( "Before: " . $group->getCount() );
    for( $i = 0; $i < count($arRm); $i++ )
    {
    $group->removeMember( $arRm[$i] );
    }
    //echo ( "After: " . $group->getCount() );

    $task = new ScheduledTask( $host, $group, $timer, $ar[“stTaskType”], $ar[“stID”] );
    $task->setShutdownAfterTask( $ar[“stShutDown”] == 1 );
    $task->setOther1( $ar[“stOther1”] );
    $task->setOther2( $ar[“stOther2”] );
    $task->setOther3( $ar[“stOther3”] );
    $task->setOther4( $ar[“stOther4”] );
    $task->setOther5( $ar[“stOther5”] );
    $arTasks[] = $task;
    } */
    //end comment


    //and comment also from below (Line 212 for me) BOLD
    $group = null;
    while( $ar = mysql_fetch_array( $res ) )
    {
    if ( $group == null )
    {
    $group = new Group($ar[“groupID”], $ar[“groupName”], $ar[“groupDesc”] );
    }
    /* $hid = $ar[“hostid”];
    if ( $hid !== null && is_numeric( $hid ) )
    {
    $host = $this->getHostById( $hid );
    if ( $host != null )
    $group->addMember( $host );
    } */
    }
    return $group;[/php]

    While working through the instructions from that thread I setup a test group and a scheduled task to run every minute. Once the web GUI was showing the scheduled tasks I checked the Fog Scheduler log to find that group scheduled tasks no longer worked as it could not find the list of hosts associated with the group. (I have edited the output of the fog scheduler to give more details)

    [INDENT=1]tail -f /opt/fog/log/fogscheduler.log[/INDENT]
    [INDENT=1][04-17-14 12:29:45 pm] * Task run time: * * * * *[/INDENT]
    [INDENT=1][04-17-14 12:29:45 pm] * Found a task that should run…[/INDENT]
    [INDENT=1][04-17-14 12:29:45 pm] - Is a group based task.[/INDENT]
    [INDENT=1][04-17-14 12:29:45 pm] - Found 0 hosts.[/INDENT]
    [INDENT=1][04-17-14 12:29:45 pm] - No valid hosts.[/INDENT]

    So dissecting the FOGScheduler service at /opt/fog/service/FOGTaskScheduler/FOGTaskScheduler, I found that the getScheduledTasksByStorageGroupID function I’ve just commented a load of code out from is being re-used.

    [INDENT=1]91 $tasks = $core->getScheduledTasksByStorageGroupID( $groupid );[/INDENT]

    So looking back over the code that was commented out you can see that once the getScheduledTasksByStorageGroupID function has information about the task it looks to see if the task is a group or a single task.

    [INDENT=1]Is task is a single host task?[/INDENT]
    [INDENT=1]115 If ( $ar[“stIsGroup”] == 0 ){[/INDENT]
    [INDENT=1]Get information about host[/INDENT]
    [INDENT=1]116 $host=$this->getHostById($ar[“stGroupHostID”]);[/INDENT]
    [INDENT=1]117[/INDENT]
    [INDENT=1]Is task a group task?[/INDENT]
    [INDENT=1]118 }else if ( $ar[“stIsGroup”] == 1 ){// Task[/INDENT]
    [INDENT=1]Get information about the group[/INDENT]
    [INDENT=1]119 $group = $this->getGroupById($ar[“stGroupHostID”]);[/INDENT]
    [INDENT=1]120[/INDENT]
    [INDENT=1]121 }[/INDENT]

    For group tasks on line 119 the function passes to another function getGroupById to get the members of the group. The getGroupById function looks at the DB and gets a list of hosts that are members of the group and then builds an array / list (calling another function Group::addMember( $host ) which caused the web GUI error) with each host as an entry.

    The instructions from ritchy_purple were to comment out the part of the getGroupById function that built the array / list of hosts. So commenting out that would be the reason why the Fog Scheduler stopped working for groups!


  • Senior Developer

    Thank you Neil, it just makes it easier for people to copy paste and such.



  • @Tom Elliott, post: 25823, member: 7271 said:

    Can you put your code into [ p h p ] [ / p h p ] blocks without the spaces?
    Sorry Tom, I’ve updated my post.


  • Senior Developer

    Can you put your code into [ p h p ] [ / p h p ] blocks without the spaces?



  • Find the following on lines 182 - 184

    FOGCore.class.phptasks.sched.include.php



  • Becomes

    From line 135 to 185
    [php] $arTasks[] = $task;
    }
    }
    else if ( $group != null )
    {
    if ($wgui == true){
    $task = new ScheduledTask( $host, $group, $timer, $ar[“stTaskType”], $ar[“stID”] );
    $task->setShutdownAfterTask( $ar[“stShutDown”] == 1 );
    $task->setOther1( $ar[“stOther1”] );
    $task->setOther2( $ar[“stOther2”] );
    $task->setOther3( $ar[“stOther3”] );
    $task->setOther4( $ar[“stOther4”] );
    $task->setOther5( $ar[“stOther5”] );
    $arTasks[] = $task;
    }else{
    if ( $group->getCount() > 0 )
    {
    $arRm = array();
    $hosts = $group->getMembers();
    for( $i = 0; $i < count($hosts); $i++ )
    {
    if ( $hosts[$i] != null )
    {
    $h = $hosts[$i];
    if ( ! ($h->isReadyToImage() && $h->getImage()->getStorageGroup()->getID() == $groupid ) )
    {
    $arRm[] = $h;
    }
    }
    }
    //echo ( "Before: " . $group->getCount() );
    for( $i = 0; $i < count($arRm); $i++ )
    {
    $group->removeMember( $arRm[$i] );
    }
    //echo ( "After: " . $group->getCount() );
    $task = new ScheduledTask( $host, $group, $timer, $ar[“stTaskType”], $ar[“stID”] );
    $task->setShutdownAfterTask( $ar[“stShutDown”] == 1 );
    $task->setOther1( $ar[“stOther1”] );
    $task->setOther2( $ar[“stOther2”] );
    $task->setOther3( $ar[“stOther3”] );
    $task->setOther4( $ar[“stOther4”] );
    $task->setOther5( $ar[“stOther5”] );
    $arTasks[] = $task;
    }
    }
    }[/php]

    This adds a bypass allowing the original script to execute or if the call is coming from the webGUI the script will be shortened bypassing the calls to get info on the members of the group.



  • Find the following on lines 135 to 172:
    [php] $arTasks[] = $task;
    }
    }
    else if ( $group != null )
    {
    if ( $group->getCount() > 0 )
    {
    $arRm = array();
    $hosts = $group->getMembers();
    for( $i = 0; $i < count($hosts); $i++ )
    {
    if ( $hosts[$i] != null )
    {
    $h = $hosts[$i];
    if ( ! ($h->isReadyToImage() && $h->getImage()->getStorageGroup()->getID() == $groupid ) )
    {
    $arRm[] = $h;
    }
    }
    }

                                                              //echo ( "Before: " . $group->getCount() );
                                                              for( $i = 0; $i < count($arRm); $i++ )
                                                              {
                                                                      $group->removeMember( $arRm[$i] );
                                                              }
                                                              //echo ( "After: " . $group->getCount() );
    
                                                              $task = new ScheduledTask( $host, $group, $timer, $ar["stTaskType"], $ar["stID"] );
                                                              $task->setShutdownAfterTask( $ar["stShutDown"] == 1 );
                                                              $task->setOther1( $ar["stOther1"] );
                                                              $task->setOther2( $ar["stOther2"] );
                                                              $task->setOther3( $ar["stOther3"] );
                                                              $task->setOther4( $ar["stOther4"] );
                                                              $task->setOther5( $ar["stOther5"] );
                                                              $arTasks[] = $task;
                                                      }
                                              }[/php]


  • The question now is how to get both the web GUI and group scheduled tasks working? Assuming you have a fresh install of FOG 0.32 and have not made the changes suggested by above: I’ve introduced a new variable to the getScheduledTasksByStorageGroupID and getGroupById functions and a few if statements that allows the script to bypass parts of the code.

    Your code might not match the line numbers in mine but should be pretty close.

    Before making any changes make sure you make a backup of the file you edit!

    cp /var/www/html/fog/management/lib/FOGCore.class.php /var/www/html/fog/management/lib/FOGCore.class.bak

    First off lets edit the /var/www/html/fog/management/lib/FOGCore.class.php file:

    Looks for:
    [php]function getScheduledTasksByStorageGroupID( $groupid, $blIgnoreNonImageReady=false )
    {
    $arTasks = array();[/php]

    Edit to become:

    [php]function getScheduledTasksByStorageGroupID( $groupid, $blIgnoreNonImageReady=false, $wgui = false )
    {
    $arTasks = array();[/php]

    This introduced the $wgui variable in the function parameters, if it is not supplied as a parameter it will default to the value of false.

    Find this on lines 110 to 122

    [php]if ( $timer != null )
    {
    $group=null;
    $host=null;

    If ( $ar[“stIsGroup”] == 0 ){
    $host=$this->getHostById($ar[“stGroupHostID”]);

    }else if ( $ar[“stIsGroup”] == 1 ){
    $group = $this->getGroupById($ar[“stGroupHostID”]);

    }
    if ( $group != null || $host != null )[/php]

    Edit it to become:

    [php]if ( $timer != null )
    {
    $group=null;
    $host=null;

    If ( $ar[“stIsGroup”] == 0 ){
    $host=$this->getHostById($ar[“stGroupHostID”]);

    }else if ( $ar[“stIsGroup”] == 1 ){
    ($wgui == true ? $group = $this->getGroupById($ar[“stGroupHostID”],true) : $group = $this->getGroupById($ar[“stGroupHostID”]));

    }
    if ( $group != null || $host != null )[/php]

    This edit adds a shorthand if statement. If $wgui is true it will add a new parameter of “true” to the [B]getGroupById [/B]function call.

    — Update —
    On reflection I’ve overcomplicated the last change. You can also replace the shorthand if statement simply with

    [INDENT=1]$group = $this->getGroupById($ar[“stGroupHostID”],$wgui);[/INDENT]


Log in to reply
 

394
Online

38920
Users

10688
Topics

101407
Posts

Looks like your connection to FOG Project was lost, please wait while we try to reconnect.