Hello everyone,
First many thanks for your great work on Fog.
I am using fog Version 1.4.4 SVN Revision: 6077.
My server is dual homed (eth0 and eth1) and there is no route between the subnets associated with the two interfaces.
As i have client PC on both interfaces i wanted to be able to use multicast deployment on both interfaces.
To achieved that i created two storage groups and for each storage group i created a primary node. Each of the primary node is configured with the interface IP of one of the interfaces. I also upload two images and associated each one of them to a different storage group.
Image1-- StorageGroup1 – PrimaryStorageNode1 => associated with Interface eth0
Image2 -- StorageGroup2 – PrimaryStorageNode2 => associated with Interface eth1
When I tested this configuration the interface used by udpcast is always eth0 even if i choose to deploy the image associated with StorageGroup2. Hence multicast deployment is only working for client PC on the subnet associated with eth0.
I dig a little bit in to the PHP files that drive the multicast service and, may be, i find where the problem lies.
As i understand the multicast service code, in a nutshell, it is supposed to:
A) Evaluate in turn each storage group.
b) For each evaluated storage group find all the active,not anot already processed , multicast task.
C) For each, not already processed, multicast task found do the following:
1) if the image linked to this task is associated with the primary storage node of the storage group that is being evaluated then use the interface associated with this primary node to create the udpcast command.
2) if the image linked to this task is NOT associated with the primary storage node of the storage group that is being evaluated then do not create any udpcast command and continue to process on to the next active multicast task if any or to the next storage group if any.
Actually the code as it is right now does not do the preceding instead:
A) It Evaluate in turn each storage group.
b) For each evaluated storage group it finds all the active, not already processed, multicast task.
c) For each, not already processed, multicast task found it use the interface associated with the primary node of the storage group that is being evaluated to create the udpcast command.
The result of this is that after the first storage group has been evaluated all the active multicast tasks are already configured with the interface of the primary node associated with this first storage group. The later evaluation of the other storage groups has no effect as all the active multicast task are already processed.
To resolve the issue i had to modify the code off the “getAllMulticastTasks” function that is located on the file “/var/www/html/fog/fog/lib/service/multicasttask.class.php”.
a) I commented line 50 on the original file
// unset($StorageNode);
b) I added this chunk of code just under line 61 on the original file (before any modification made). It test if the multicast task that is being process is link to the storage group that is being process and if not it skip the multicast task that is being process.
if($MultiSess->get('storagegroupID') != $StorageNode->get('storagegroupID')) {
continue;
}
c) I added this just bellow line 106 on the original file (before any modification made)
unset($StorageNode);
finally the function will look like this :
public function getAllMulticastTasks($root, $myStorageNodeID)
{
$StorageNode = self::getClass('StorageNode', $myStorageNodeID);
self::$HookManager->processEvent(
'CHECK_NODE_MASTER',
array(
'StorageNode' => &$StorageNode,
'FOGServiceClass' => &$this
)
);
if (!$StorageNode->get('isMaster')) {
return;
}
$Interface = self::getMasterInterface(
self::resolveHostname(
$StorageNode->get('ip')
)
);
// unset($StorageNode);
$Tasks = array();
$find = array(
'stateID' =>
self::fastmerge(
self::getQueuedStates(),
(array)self::getProgressState()
)
);
foreach ((array)self::getClass('MulticastSessionManager')
->find($find) as $index => &$MultiSess
) {
if($MultiSess->get('storagegroupID') != $StorageNode->get('storagegroupID')) {
continue;
}
$taskIDs = self::getSubObjectIDs(
'MulticastSessionAssociation',
array(
'msID' => $MultiSess->get('id')
),
'taskID'
);
$count = self::getClass('MulticastSessionAssociationManager')
->count(
array(
'msID' => $MultiSess->get('id')
)
);
if ($count < 1) {
$count = $MultiSess->get('sessclients');
}
if ($count < 1) {
$MultiSess->set('stateID', self::getCancelledState())->save();
self::outall(
_('Task not created as there are no associated Tasks')
);
self::outall(
_('Or there was no number defined for joining session')
);
continue;
}
$Image = $MultiSess->getImage();
$fullPath = sprintf('%s/%s', $root, $MultiSess->get('logpath'));
if (!file_exists($fullPath)) {
continue;
}
$Tasks[] = new self(
$MultiSess->get('id'),
$MultiSess->get('name'),
$MultiSess->get('port'),
$fullPath,
$Interface,
$count,
$MultiSess->get('isDD'),
$Image->get('osID'),
$MultiSess->get('clients') == -2 ? 1 : 0,
$taskIDs
);
unset($MultiSess, $index);
}
unset($StorageNode);
return array_filter($Tasks);
}
I am not a programmer and i do not know if those modifications can have any side effects on the overall functionality of fog. I posted this because it works for me an because may be it can help someone else.
Sorry for the verbose style.