Having main server automatically task storage node for imaging based off client IP/SUBNET
-
I’ve been researching and inquiring online about this subject and I cannot find any useful info regarding it. So, the location and subnet plugins within fog only works with registered host to direct it to the storage node to use for the imaging task I know this and use this function with all registered host I have. But, I want to know if there is a way to implement this with non-registered host, where if I choose the deploy image option in the PXE menu the main fog server can determine the node to use within the same location/subnet of the client pc booting in to PXE based off info gathered from the pc like Ip address/subnet, I have not been successful yet at cracking this so I’m wondering if anyone else has attempted or been successful at doing this or could give me some ideas of where to tie all this together to make it possible. I want the node assignment during the imaging task to be automated without having to always register the host pc. I have a main fog server and 2 storage nodes on 2 different subnets within our facility right now I am running dnsmasq on the storage nodes to respond to PXE request within the different subnets and serve the files. It works great but it obviously will choose a random node based off the main server’s current logic after the deploy image option is selected; I want to see about implementing this to cut latency down by having the closest node (the node within the corresponding subnet of the client pc) to always be the one to handle imaging.
Not sure if this is relevant but I modified the embedded ipxescript from the original to automate the chain loading of the tftp server I want to use so I don’t have to enter it manually each time here is a copy of my script below, so this process is already automated but I want to automate the logic for the storage node tasked with the imaging and Ive experimented with trying to set parameters within the ipxe script did not work:
#!ipxeObtain DHCP lease
dhcp || goto dhcperror
echo Received DHCP lease, proceeding…Test the hostname resolution by pinging it
ping -c 1 fogserver || goto pingerror
echo Hostname resolved, proceeding…Proceed to netboot using the hostname directly
chain tftp://fogserver/default.ipxe || goto chainloadfailed:chainloadfailed
prompt --key s --timeout 10000 Chainloading failed, hit ‘s’ for the iPXE shell; reboot in 10 seconds && shell || reboot:dhcperror
prompt --key s --timeout 10000 DHCP failed, hit ‘s’ for the iPXE shell; reboot in 10 seconds && shell || reboot:pingerror
prompt --key s --timeout 10000 Hostname resolution failed, hit ‘s’ for the iPXE shell; reboot in 10 seconds && shell || rebootAnd below is the script I tried to use to attempt to set the location of the host booting over pxe to task the storage node with imaging task, which did not work due to the main servers decision is done after choices are made in the pxe menu so I do not think that adding params to this script is the way to go but I may be wrong:
#!ipxe
Obtain DHCP lease
dhcp || goto dhcperror
echo Received DHCP lease, proceeding…Determine the location based on subnet
set clientip ${net0/ip}
set locationid 0 # Default location ID (if needed)
if (${clientip} =~ 10.130.192.) set locationid 1
if (${clientip} =~ 10.130.208.) set locationid 2Perform the API call to set the location for this session
Replace <api-user> and <api-pass> with your FOG API credentials
set api_user <api-user>
set api_pass <api-pass>
set api_token “”
set user_token “”Fetch API token
set api_url
http://<fog-server>/fog/management/index.php?sub=auth&action=login
params set=api_user=${api_user}&api_pass=${api_pass}
route http post ${api_url} params | parse api_token=${api_token},user_token=${user_token}Set location via API call
set location_url
http://<fog-server>/fog/management/index.php?sub=location&action=setLocation&mac=${net0/mac}&locationid=${locationid}
route http post ${location_url} Authorization: “Bearer ${api_token}”Test the hostname resolution by pinging it
ping -c 1 fogserver || goto pingerror
echo Hostname resolved, proceeding…Chain to boot.php and pass location ID
chain tftp://fogserver/default.ipxe?locationid=${locationid} || goto chainloadfailed
:chainloadfailed
prompt --key s --timeout 10000 Chainloading failed, hit ‘s’ for the iPXE shell; reboot in 10 seconds && shell || reboot
:dhcperror
prompt --key s --timeout 10000 DHCP failed, hit ‘s’ for the iPXE shell; reboot in 10 seconds && shell || reboot
:pingerror
prompt --key s --timeout 10000 Hostname resolution failed, hit ‘s’ for the iPXE shell; reboot in 10 seconds && shell || reboot -
This post is deleted! -
@JamiesonCA092 I can’t really give you a solid solution because fog isn’t designed to work the way you want it with unregistered target computers.
But I know how FOG works. There are 2 “hook” scripts. One is before imaging starts and one after the image push is complete. The bash script that is called before imaging starts is the postinit script. When this script runs all of the kernel parameters have been expanded to variables, including storageip value. This value as well as most others could be reset by this postinit script.
I have a tutorial on a postinstall script that uses the IP address of the target computer to decide what OU the target computer will connect to. That mechanics of the bash script could be the basis to update the storage IP variable. I don’t know if it works, but if you are that deep into modifying the ipxe script, creating your own bash script shouldn’t be to complicated.
Edit: Post on point. https://forums.fogproject.org/post/69725
-
First thought, figure out how to make the FOG Server return the storage node you want.
Take a look at this function:
I think if you can figure out how to pass in an IP address (and maybe subnet mask) to this, you can add logic to select the storage node you want.
The hard part will be figuring out how to pass in the IP address / subnet mask all the way from the unregistered host to the FOG Server and into this function. The easy part is adding a bunch of logic in here to return the node you want.
This link below is for USB devices, but it shows how the request is made and parameters are passed back. You could modify this to pass your IP, subnet, and whatever else to the fog server:
Notice that it writes to this file:
/tmp/hinfo.txt
You would add lines somewhere in here to get the IP / subnets from the request that the host makes:
And you would pass that IP / subnet information into that optimal storage node function here somewhere:
Second thought, hack the storage node selection into a custom FOS build
Checkout this spot, it may have potential:
Another thought here is to look at how the Capone plugin sets this stuff. The script is called here:
And this is the file that gets executed, you see it sets a storage node IP, among other things:
https://github.com/FOGProject/fos/blob/c0238723ce381b5cd0340932086b10d47e79e26b/Buildroot/board/FOG/FOS/rootfs_overlay/bin/fog.capone#L108Third thought, postinit scripts
The method @george1421 suggested seems promising, but I am unsure how the postinit script would make changes to environment variables that will persist after the postinit script ends. If you could solve that somehow, this seems like the easy path. -
@george1421 @Wayne-Workman I was thinking towards the postinit script as well before, but I had the same concerns that @Wayne-Workman mentioned about the changes persisting after the script was ran as well. I’m about to continue working on this now, I was messing around in the ipxe menu items and was able to have the server pass the image I want to use automatically on a new menu item I created like so, in my mind if you are able to pass this logic to set the image you should be able to pass the same logic if I find the right parameters to set the storage node as well since that logic can be passed with the registered host using the location or subnet plugin:
login
set imageID 1
params
param mac0 ${net0/mac}
param arch ${arch}
param imageID ${imageID}
param qihost 1
param username ${username}
param password ${password}
param sysuuid ${uuid}
isset ${net1/mac} && param mac1 ${net1/mac} || goto bootme
isset ${net2/mac} && param mac2 ${net2/mac} || goto bootmeso, once I saw I was successfully able to pass this over and it worked I experimented with different parameters to set the storage node as well based on parameters I saw that gets passed in some of the php scripts already within fog server, I set the storage location to 4 which corresponds with one of my storage nodes identifiers in the sql database but got a kernel panic so not sure if that parameter actually worked when I did that or what. I was trying to see if I could successfully pass the parameter manually that way I could understand how to make it automated after then I could add some subnet mappings for the server to review the ip address of the host and map it accordingly to the proper node, or if this fails I was going to see if there is a way to add logic in the decision making process of the main fog server to measure the latency so that it will always choose the closest node either will work if I can make it happen. I was also looking into the location/subnet plugins that I have installed to see if there is a way to modify those to work with unregistered host or at least mimic functions they add in a similar way for unregistered host. The solution I’m looking for is deff possible just have to put the right pieces together and make it whole, once I do figure this out I will post my solution, I think there would be many others that would like to be able to utilize the same function. If anyone else comes up with some more ideas to add I am open to hear all.
-
@george1421 @Wayne-Workman but thank you guys I think with what you provided me so far will put me on the right track to my solution.
-
@JamiesonCA092 ok it shows you have some debugging skills, so I’ll add a few new tools into your toolbox.
- on the fos linux (target computer) when you schedule a task and tick the debug checkbox, when you pxe boot the target computer you will be dropped to the fos linux command prompt.
- You can start the imaging process in single step mode by simply keying in
fog
at the command prompt. - The script will run until it hits a
debugPause;
command in the script. You can add that command in your custom script with echo statements to understand how your script is running. Pressing the enter key will cause the script to run again until the next debugPause command. - At the fos linux command prompt if you get the ip address of the fos linux (target computer) with
ip a s
and then give root a password with thepasswd
command (make it simple like hello, it will be reset at the next reboot). Once you have those 2 bits of into you can use putty or ssh from a second computer to the fos linux computer for debugging. Using this method you don’t have to sit in front of the target computer plus you can copy and paste using the putty/ssh session. - If you need to stop the
fog
script during hit ctrl-c to skip out of the script. At this point you can verify the environment, check the available variables, etc. When you are done looking around, then you can enterfog
again to begin the imaging process once again. No reboot needed. - In the fog script the kernel parameters sent to fos linux are converted to bash script variables in the functs.sh script between lines 9 and 13 https://github.com/FOGProject/fos/blob/0efdd68f1783a06f3214607fc313db50747fbc43/Buildroot/board/FOG/FOS/rootfs_overlay/usr/share/fog/lib/funcs.sh#L9
I’m pretty sure Wayne is right that the varialbles in the postinit script are local and will be erased when the script terminates. But I would test to be sure.
One last hack I can think of is that you can hack the fog.mount script https://github.com/FOGProject/fos/blob/master/Buildroot/board/FOG/FOS/rootfs_overlay/bin/fog.mount Put the logic to decide the target’s IP address into that script. The concept of dynamically patching the fog.mount script can be found in this tutorial (which addressing the fog.man.reg script) https://forums.fogproject.org/topic/14278/creating-custom-hostname-default-for-fog-man-reg but the concept and actions are the same.
-
@george1421 so I did your method by using ssh to get into the fos of the target computer during the imaging process and I found a command that worked I typed storage=fogstorage01.gmh.org/images and got a successful completion command that youll see here in the screenshot
so, seeing this I think I can implement this parameter in a postinit script to run by manually mapping subnets or using a helper function within the script to get the host ip address then match it to the proper storage node by implementing something like if the host ip matches subnet 10.130.208.0/24 storage=fogstorage02.gmh.org/images or if its 10.130.192.0/24 storage=fogstorage02.gmh.org/images and see if it completes successfully. I am going to attempt this then I will report back the results.
-
@george1421 passing the command storage=fogstorage01.gmh.org/images is confirmed successful by the screenshot below
so, knowing this I think passing this in a postinitscript will actually work, I am going to attempt this on the next boot to test it out and I will post the script I created to have this work if it is successful
-
@JamiesonCA092 typo in this column the command was storage=fogstorage01.gmh.org/images
-
Sorry everyone I haven’t updated on this post, my organization wanted our fog server migrated to our data center on to a vm so my time was reverted to doing that and building an additional one at one of our new hospitals we recently finished construction on. But I plan to get back to working on it this week on my test server I have set up. Once I have it set up I am going to implement it on our production servers, I think I’m very close to implementing this concept and once I have it cracked I will make sure to share this with everyone because I think the option of being able to do this will be valuable to many others. @george1421 @Wayne-Workman