Location Plugin - enhancement of behavior
-
Two words:
IP ranges.
Here’s this idea:
Add another field to the locations table:
CIDR
. Values would be in CIDR format. Example:10.0.0.0/8
This would represent 10.0.0.0 - 10.255.255.25510.5.40.0/24
This would represent 10.5.40.0 - 10.5.40.255- And so on
So, if a host does not have a location ID assigned to it, look at it’s IP address and see if it matches the CIDR of any location. If you find a match, choose that location and use one of that location’s storage nodes.
@developers @moderators @testers Thoughts? I will gladly write the necessary bash functions for FOS used to get a host’s CIDR.
-
@Wayne-Workman Yeah, interesting one! Thanks. I’d vote for that. Shouldn’t be too hard to add.
-
@Wayne-Workman I agree, this could be a very useful feature. Though it would be best to have the CIDR conversion and mapping done entirely on the backend, and not in FOS. @Tom-Elliott thoughts?
-
@joe-schmitt said in Location Plugin Enhancement of behavior:
Though it would be best to have the CIDR conversion and mapping done entirely on the backend, and not in FOS.
All web frameworks I know of can easily get the requester’s IP address, so yeah I think it would be best done in the backend. I was just excited and not thinking when I suggested doing it in FOS.
-
yeah this was an improvement me and tom discussed several times in the past to improve the location plugin and remove the need for “manual” location selection but was going to save the implementation for FOG2.
However, i’d welcome the enhancement - unfortunately i don’t have anytime at the moment due to work/personal commitments to dedicate to it but as Seb said, would be fairly easy to implement.
i’d recommend making sure we implement being able to add multiple CIDR addresses to a location.
this would certainly remove the “User Error” in choosing incorrect locations or forgetting to change location when kits moved killing the WAN links and contradicting the whole reason for location plugin… not that, that ever happens of course rolls eyes lol
-
I do a modification of this (CIDR extraction) for my post install script for proper OU placement.
myip=`ip route get 8.8.8.8 | awk 'NR==1 {print $NF}' | cut -d "." -f1-2`; case "${myip}" in 10.1) sitecode="NYC"; timezone="Eastern Standard Time"; oupath="ou=computers,ou=nyc,dc=domain,dc=com"; ;; 10.2) sitecode="LA"; timezone="Western Standard Time"; oupath="ou=computers,ou=la,dc=domain,dc=com"; ;; *) # Default code for the unknowns sitecode="CORP"; timezone="Eastern Standard Time"; oupath="ou=computers,ou=corp,dc=domain,dc=com"; ;; esac
I think it would be a great idea. Any time we can eliminate system errors its a great plan.
Ref: https://forums.fogproject.org/topic/7740/the-magical-mystical-fog-post-download-script/6
-
@lee-rowlett said in Location Plugin - enhancement of behavior:
i’d recommend making sure we implement being able to add multiple CIDR addresses to a location.
Can you explain in more detail why a location would need multiple CIDRs?
-
@wayne-workman big multi-floor offices where the infrastructure is a scope per floor
Head Office:
ground floor - 192.168.0.0/24
first floor - 192.168.1.0/24
second floor - 192.168.2.0/24
third floor - 192.168.3.0/24
fourth floor - 192.168.4.0/24and so on… and only requires one storage node/Location to cater for the imaging demand.
otherwise you’d have to do Location per CIDR…obviously this would be few and fair between but it’s worth considering…
also another scenario would be
Location A:
Mobile Devices: 192.168.10.0/24
Desktop Devices: 192.168.11.0/24 -
@lee-rowlett I see what your saying, and we should be able to associate multiple CIDRs for a node.
I’ve been looking at the database layout for locations and I’ve figured out how to do this. We add a CIDR field and add it to the composite primary key for the location table. This allows for a single storage node to have multiple locations associated with it - as long as each one has a different CIDR. Here’s my changes:
CREATE TABLE `location` ( `lID` int(11) NOT NULL AUTO_INCREMENT, `lName` varchar(255) NOT NULL, `lDesc` longtext NOT NULL, `lStorageGroupID` int(11) NOT NULL, `lStorageNodeID` int(11) NOT NULL, `lCidr` varchar(50), `lCreatedBy` varchar(40) NOT NULL, `lCreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, `lTftpEnabled` enum('0','1') NOT NULL, PRIMARY KEY (`lID`), UNIQUE KEY `index0` (`lID`), UNIQUE KEY `index1` (`lName`), UNIQUE KEY `index2` (`lStorageGroupID`,`lStorageNodeID`,`lCidr`) ) ENGINE=MyISAM AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;
As you can see, there’s the new field
lCidr
that is optional. I’ve also addedlCidr
to the composite primary key. Next, I inserted some data:insert into location(lName,lDesc,lStorageGroupID,lStorageNodeID,lCidr,lCreatedBy,lCreatedTime,lTftpEnabled) VALUES ('Floor2','None','1','1','10.0.1.0/24','wayne','2017-12-31 15:07:51','1'); insert into location(lName,lDesc,lStorageGroupID,lStorageNodeID,lCidr,lCreatedBy,lCreatedTime,lTftpEnabled) VALUES ('Floor1','None','1','1','10.0.2.0/24','wayne','2017-12-31 15:07:51','1');
And viola, I can create multiple locations for a single storage node as long as I give each location a different CIDR value:
MariaDB [fog]> select * from location; +-----+--------+-------+-----------------+----------------+-------------+------------+---------------------+--------------+ | lID | lName | lDesc | lStorageGroupID | lStorageNodeID | lCidr | lCreatedBy | lCreatedTime | lTftpEnabled | +-----+--------+-------+-----------------+----------------+-------------+------------+---------------------+--------------+ | 3 | Floor2 | None | 1 | 1 | 10.0.1.0/24 | wayne | 2017-12-31 15:07:51 | 1 | | 4 | Floor1 | None | 1 | 1 | 10.0.2.0/24 | wayne | 2017-12-31 15:07:51 | 1 | +-----+--------+-------+-----------------+----------------+-------------+------------+---------------------+--------------+ 2 rows in set (0.00 sec)
The above method I think would involve the least amount of work. It’s not normalized (but the entire fog database is not normalized already). The longer harder way would be to create a table just for CIDRs, and then create a Cidr-location-association table - which would require another screen for adding & associating them and would be more work. Not worth it to go that harder route IMO.
-
@Wayne-Workman Thanks for looking into this! About normalized DB structure: Usually one should move information to an extra table if it is redundant or used in various combinations. That’s not the case here because CIDRs won’t be redundant within one organization. So I think “the harder route” - as you call it - is not advisable anyhow. I am with you there.
-
Nice one! having to setup additional locations per CIDR is no biggy really as this will automate the selection anyhow! So shouldn’t be too much of a change for people to get their heads around and most setups will work without the need of additional locations and is really the only caveat we’d need to make users aware of.
so all that’s left to do is edit
locationmanagementpage.class.php to include CIDR field and then the changeitems.hook.php storagenode functions are going to need rewriting - that’s probably the best place to include the CIDR enhancement.nice start wayne
-
Issues that will need to be addressed is location cidr addresses eclipsing other addresses.
i.e. Location A = 192.168.0.0/23
Location B = 192.168.1.0/24Or location A = 10.0.0.0/24
Location B = 10.0.3.0/21Also a quick google search finds php code to find if IP address is in a specific CIDR range.
/** * Check if a given ip is in a network * @param string $ip IP to check in IPV4 format eg. 127.0.0.1 * @param string $range IP/CIDR netmask eg. 127.0.0.0/24, also 127.0.0.1 is accepted and /32 assumed * @return boolean true if the ip is in this range / false if not. */ function ip_in_range( $ip, $range ) { if ( strpos( $range, '/' ) == false ) { $range .= '/32'; } // $range is in IP/CIDR format eg 127.0.0.1/24 list( $range, $netmask ) = explode( '/', $range, 2 ); $range_decimal = ip2long( $range ); $ip_decimal = ip2long( $ip ); $wildcard_decimal = pow( 2, ( 32 - $netmask ) ) - 1; $netmask_decimal = ~ $wildcard_decimal; return ( ( $ip_decimal & $netmask_decimal ) == ( $range_decimal & $netmask_decimal ) );
ref and thanks to: https://gist.github.com/tott/7684443
If this has to be done in Ash (FOS environment) then maybe a tool from RHEL (ipcalc) could be implemented in buildroot for FOS. ref: https://arstechnica.com/civis/viewtopic.php?p=23215698
-
@george1421 It would be best if we modeled how forwarding tables work; Longest Prefix Match. Its a fairly intuitive way of handling multiple CIDRs that may overlap, and is the standard.
Implementing this optimally is fairly straight forward as well, in fact I’ve done so before in other applications. All the “heavy lifting” should be done by the backend, as it will know the host’s IP from the HTTP request, and can quickly perform a longest prefix match on all registered CIDRs.
-
@george1421 said in Location Plugin - enhancement of behavior:
Issues that will need to be addressed is location cidr addresses eclipsing other addresses.
Exactly, I thought about this too. And when there is overlap, as Joe said, we just pick the best match. If there’s a tie, just pick the first one in the tie.