FOG 1.3 persistent groups
-
I still have a need to get persistent groups working in fog 1.3.x. While I understand that it may be possible in FOG 2.0, that software is not here today.
First the problem I’m trying to solve. In my AD structure I have different base OUs for different locations. Within those location OUs I have different sub OUs for different types of devices (workstations, instruments, kiosks, etc). These different OUs could have different images, or the same image used for multiple OUs. I can do exactly what I need with post install scripts detecting the subnet where the target device is and what image is pushed to it. I can take this calculated info and populate the unattend.xml script during images. This all works fine. But its a bit cryptic, requires a programmer to make adjustments and I loose out of some of the functionality of FOG because the database fields are out of sync with the target device. If I can’t get the persistent groups to work as I need, I do have this route as a fall back method.
I think I figured a way to hack a solution together that won’t break 1.3.0 (when its released). Right now I’m just posting this here for a sanity check before I go about messing with FOG’s innards.
The idea I had is to create a manually registered host. Lets call this a host template (with an invalid mac address like 00:00:00:00:00:00). The name of that host template will match exactly the text name of the group I’ve created previously. (it would be much easier if I could just create a new integer field in the hosts table and call it TemplateID. And that TemplateID would point to a GroupID. But again I don’t want to break fog 1.3.0 or mess with the db schema). As I register new new hosts, I’ll assign them to a primary group when doing a full registration. This will create a new entry in the groupMembers table (so far this is all normal processes on how we register machines today).
Now I have a linking between a host template record (in pseudo code: [template.name == group.name] and [group.id==host.id] ) I can create a mysql database trigger
after insert
to fire off a sql script to copy the host template fields to the inserted host where the inserted host fields are null (or empty).So far the path sounds logical and somewhat easy(ish).
-
This logic makes sense.
But doesn’t some of it sort of exist and we just need to add the template part?
I.e. as groups are now you can update an entire group with ad settings, snapins, default image, etc.
But it’s all static and you can’t save what snapins and printers the group always needs. (Currently we just made a doc for each group listing the settings outside of fog)My point is, maybe you can reuse the existing update group functions with this template idea.
I figure this is relating to this request, just sooner though.
https://forums.fogproject.org/topic/6637/fog-2-0-persistent-group-settings/16If you need any help with coding or testing this I am happy to be of service.
-
I looked in the database and could not find where the groups actually saved the settings (like ou path). If the existing group function actually saved the values that were set it would be a much easier task to patch. From what I can tell, when you go into the group function and change a parameter, it goes through each device and sets that value. But in the end it does not save that value anywhere. Again, if it saved it at the end of the update, I’d be golden.
(ps I was aware of your thread, but I didn’t want to pollute it with my jibber-jabber).
-
@george1421 I am sorry but I still don’t actually get what you want to achieve with “persistent groups”… Do you mean kind of “persistent settings throughout a group”?
-
@Sebastian-Roth
Ok let me try to explain at least my idea in a simpler way. I tend to use too many words.So lets say you have a department like accounting. This department all needs access to the same printers, software, and needs to be in the same OU.
I want to be able to add a host to the accounting group that already has all those settings saved.
So when I add a host to the accounting group I can then apply all the saved printers, OU settings, snapins, and image with a single action.Does that make sense?
I think @george1421’s desires are a little more complex then mind, but a similar idea.
-
@george1421 said:
We can script it - I’m confident we can.
-
WARNING: I’ll always use to many words
In my case, lets say I have 3 classes of computers. Each class has their own image and OU location.
- Workstations. They are members of the <Site OU> SOE Workstation group. They have image Win7X64, and shall be placed in the “ou=Workstation,ou=<site code>,dc=domain,dc=com” OU
- Design Stations. They are members of the <Site OU> SOE Designstation group. They have image Win7X64DS, and shall be placed in the “ou=Designstation,ou=<site code>,dc=domain,dc=com” OU
- Lab equipment. They are members of the <Site OU> Lab Equipment group. They have image Win7X86Lab, and shall be placed in the “ou=Lab,ou=<site code>,dc=domain,dc=com” OU
This all works good with the groups. But I must first register the name of the system, pick its group association. Then go into the group function and add those proper settings to all hosts in that group.
What I need is a host template somewhere, so when I add that new computer and select its group all of the attributes associated with that group will be applied to that new device. i.e. By having the group values persistently saved some place.
-
@george1421 I’m a new-comer to PHP and web development. I’ve done some cool stuff with it so far - it’s really powerful. but FOG’s plugin system remains a mystery to me.
That said, I can 100% positively create a template in the DB, and create a back-end process that enforces this template. I just don’t know how to integrate it into the fog web-gui.
-
@Wayne-Workman While I haven’t started doing anything yet (waiting for some sanity), I think I’m pretty close with the existing infrastructure. That sql trigger will do all of the dirty work. I’ve coded in sql for about 20 years. Unless mysql is really “out there” that part shouldn’t be that difficult (mssql and oracle can do this, no problem).
-
@george1421 Well then… Sounds like your approach is far superior. If you can handle this in the DB alone somehow, go for it man. I will always opt for a smaller technology stack than a larger one to get something done.
Just fill in the rest of us wondering how it works
-
I didn’t forget about this project (hack), I’ve been tied up with a few commitments for the last few days so I haven’t been able to push to far. I’m going to post what I have so far (just the concept) so I don’t forget what has been done so far.
I’ve looked into how I can best augment what is in place to allow some kind of persistence so newly added hosts will be updated with the values I’ve defined in the host template.
I’ve looked through the db structure for FOG and identified several tables that could help me in my quest. These tables are (hosts, groupMembers, printerAssoc, snapinAssoc, moduleStatusByHost). My approach will a specific database event that is triggered when a record is added to the groupMembers table. This trigger will fire after a new record is added to this table. The trigger will check to see if the group which is associated to the host, has a matching template (also stored in the hosts table). The trigger will attempt to find a hostname that matches the group name (exactly). If it finds this template, it will copy the contents of certain fields from the template record to the host record. After that update is done it will copy the snapins, printers, and modules from the matching host template to the host. In theory this “should work”. If a new group association is added and there is no matching host template then nothing is updated. The only down side I can see with this approach is if you have an established host with custom settings and you assign that host to a group where there is an associated host template, existing values will be overwritten with template values.
-
Here is the sql script as I have it so far. It does work as advertised. Right now I’m doing additional testing on my dev FOG server before its put on the production server. This trigger will fire when a new host is associated with a group and there is a host with the same exact name as the group name.
DELIMITER $$ CREATE TRIGGER new_groupmember_added AFTER INSERT ON `groupMembers` FOR EACH ROW BEGIN SET @myHostID = NEW.gmHostID; SET @myGroupID = NEW.gmGroupID; SET @myTemplateID = (SELECT hostID FROM groups INNER JOIN hosts ON (groupName = hostName) WHERE groupID=@myGroupID); IF (@myTemplateID IS NOT NULL) AND (@myHostID <> @myTemplateID) THEN UPDATE hosts d, (SELECT hostImage, hostBuilding, hostUseAD, hostADDomain, hostADOU, hostADUser, hostADPass, hostADPassLegacy, hostProductKey, hostPrinterLevel, hostKernelArgs, hostExitBios, hostExitEfi FROM hosts WHERE hostID=@myTemplateID) s SET d.hostImage=s.hostImage, d.hostBuilding=s.hostBuilding, d.hostUseAD=s.hostUseAD, d.hostADDomain=s.hostADDomain, d.hostADOU=s.hostADOU, d.hostADUser=s.hostADUser, d.hostADPass=s.hostADPass, d.hostADPassLegacy=s.hostADPassLegacy, d.hostProductKey=s.hostProductKey, d.hostPrinterLevel=s.hostPrinterLevel, d.hostKernelArgs=s.hostKernelArgs, d.hostExitBios=s.hostExitBios, d.hostExitEfi=s.hostExitEfi WHERE d.hostID=@myHostID; INSERT INTO locationAssoc(laHostID,laLocationID) SELECT @myHostID as laHostID,laLocationID FROM locationAssoc WHERE laHostID=@myTemplateID; INSERT INTO printerAssoc(paHostID,paPrinterID,paIsDefault,paAnon1,paAnon2,paAnon3,paAnon4) SELECT @myHostID as paHostID,paPrinterID,paIsDefault,paAnon1,paAnon2,paAnon3,paAnon4 FROM printerAssoc WHERE paHostID=@myTemplateID; INSERT INTO snapinAssoc(saHostID,saSnapinID) SELECT @myHostID as saHostID,saSnapinID FROM snapinAssoc WHERE saHostID=@myTemplateID; INSERT INTO moduleStatusByHost(msHostID,msModuleID,msState) SELECT @myHostID as msHostID,msModuleID,msState FROM moduleStatusByHost WHERE msHostID=@myTemplateID; END IF; END; $$ DELIMITER ;
-
@george1421 That’s pretty sweet looking. I didn’t know about triggers till this thread, actually.
-
@george1421 Well after fine tuning the sql query for the trigger I tested it on my dev box this morning. It worked exactly as advertised. When you associate a device with a group name, where there is a host (template) with the same exact name, the contents of the host (template) will be copied to the device that was just associated with that group. If you associate a host with a group that has no matching host (template) nothing is changed for that associated host.
There were a few caveats that I found, more like rules than caveats.
- Your group name must conform to the rules set out for hosts. In that your Group name may not contain spaces or more than 15 characters. The edit box for the host restricts these the group name does not.
- For every host template you must define a unique mac address, duplicates are not allowed. So for my first host template I entered 00:00:00:00:00:01 and for the second 00:00:00:00:00:02 and so on.
- When you make a host group association all of the fields (even empty ones) will be cloned to the associated host. All existing setting will be overwritten on the association.
- After you have made the host group association, if you make a change to the host template those new settings are not updated on all hosts associated what that group (but you can still do this via the normal group update function)
- Do NOT make the host template a member of the group you are trying to make persistent. I could see a loop being created by the trigger trying to reference a template that it is currently trying to update.
While I say this works, I have not attempted this (hack) on our production server just yet. I feel confident that it will work without issue. Since we are not making group associations every day (as you would if you added new hosts every day) I don’t see any performance issues.
-
Final thoughts.
While this is a hack(ish) solution. The proper solution is for the FOG management GUI to support this directly. If the developers wanted to use the same concept of just using a host as a template. I would probably do it this way.
- Add a check box to the host configuration page and call it ?? “Make this a host a template”
- Once the host is a template it should no longer be displayed in the list of hosts but in a new list of templates.
- For the groups, make a new drop down list called “host template” and only show hosts where the template flag is set.
- Then in the php code do the actions of the trigger after a host association.
- Then you could key off if the host template was updated, ask the user if the fog application should update all hosts associated with this template.
-
Great work George!
-
@george1421 said:
Do NOT make the host template a member of the group you are trying to make persistent. I could see a loop being created by the trigger trying to reference a template that it is currently trying to update.
Any way to add rules so it doesn’t apply if the template is a member of the group?
Or…
Should we force the template to be a member of the group and just disallow settings applying to the template… ???
-
@Wayne-Workman said:
Any way to add rules so it doesn’t apply if the template is a member of the group?
Or…
Should we force the template to be a member of the group and just disallow settings applying to the template… ???
Thinking about it, we probably could update the check for a null template id to also ensure the @myTemplateID variable does not match the @myHostID. If it does then not execute the update. [edit] wow there was to many double negatives in that statement. I should say its possible if we update the conditional if check[/edit] That should do it.
-
While this trigger is not supported by the developers, Tom did look at it and updated it so the fields were escaped properly.
DELIMITER $$ CREATE TRIGGER `new_groupmember_added` AFTER INSERT ON `groupMembers` FOR EACH ROW BEGIN SET @myHostID = `NEW`.`gmHostID`; SET @myGroupID = `NEW`.`gmGroupID`; SET @myTemplateID = (SELECT `hostID` FROM `groups` INNER JOIN `hosts` ON (`groupName` = `hostName`) WHERE `groupID`=@myGroupID); IF (@myTemplateID IS NOT NULL) AND (@myHostID <> @myTemplateID) THEN UPDATE `hosts` `d`, (SELECT `hostImage`, `hostBuilding`, `hostUseAD`, `hostADDomain`, `hostADOU`, `hostADUser`, `hostADPass`, `hostADPassLegacy`, `hostProductKey`, `hostPrinterLevel`, `hostKernelArgs`, `hostExitBios`, `hostExitEfi`, `hostEnforce` FROM `hosts` WHERE `hostID`=@myTemplateID) `s` SET `d`.`hostImage`=`s`.`hostImage`, `d`.`hostBuilding`=`s`.`hostBuilding`, `d`.`hostUseAD`=`s`.`hostUseAD`, `d`.`hostADDomain`=`s`.`hostADDomain`, `d`.`hostADOU`=`s`.`hostADOU`, `d`.`hostADUser`=`s`.`hostADUser`, `d`.`hostADPass`=`s`.`hostADPass`, `d`.`hostADPassLegacy`=`s`.`hostADPassLegacy`, `d`.`hostProductKey`=`s`.`hostProductKey`, `d`.`hostPrinterLevel`=`s`.`hostPrinterLevel`, `d`.`hostKernelArgs`=`s`.`hostKernelArgs`, `d`.`hostExitBios`=`s`.`hostExitBios`, `d`.`hostExitEfi`=`s`.`hostExitEfi`, `d`.`hostEnforce`=`s`.`hostEnforce` WHERE `d`.`hostID`=@myHostID; INSERT INTO `locationAssoc` (`laHostID`,`laLocationID`) SELECT @myHostID as `laHostID`,`laLocationID` FROM `locationAssoc` WHERE `laHostID`=@myTemplateID; INSERT INTO `printerAssoc` (`paHostID`,`paPrinterID`,`paIsDefault`,`paAnon1`,`paAnon2`,`paAnon3`,`paAnon4`) SELECT @myHostID as `paHostID`,`paPrinterID`,`paIsDefault`,`paAnon1`,`paAnon2`,`paAnon3`,`paAnon4` FROM `printerAssoc` WHERE `paHostID`=@myTemplateID; INSERT INTO `snapinAssoc` (`saHostID`,`saSnapinID`) SELECT @myHostID as `saHostID`,`saSnapinID` FROM `snapinAssoc` WHERE `saHostID`=@myTemplateID; INSERT INTO `moduleStatusByHost` (`msHostID`,`msModuleID`,`msState`) SELECT @myHostID as `msHostID`,`msModuleID`,`msState` FROM `moduleStatusByHost` WHERE `msHostID`=@myTemplateID; END IF; END; $$ DELIMITER ;
-
@george1421 So if I understand this correctly, If I go login to mysql and select/use the fog database, then copy paste that nifty script. I will have hackish persistent groups and be able to make templates?