Conditional evaluation question.

Glenn Satchell glenn.satchell at uniq.com.au
Thu Apr 8 14:51:28 UTC 2010


Hi Stewart,

Nicely documented solution - very handy for the archives and google!

One point I would make is that you only need to define one option space. 
You can fill in different values in the class and the group and the 
appropriate values will be used by the client...

regards,
-glenn

On 04/08/10 16:46, Stewart Walters wrote:
> Hi Glenn,
>
> Sorry, I re-read your reply and ultimately found the answer. You said,
> as does the man page, host definitions get processed before classes.
>
> If anyone else in future wants to know how to get this to work
> (particularly Sunray users attempting the same thing) - this is
> essentially how to structure dhcpd.conf to manage multiple Sunray
> environments:
>
> --- snip ---
> authoritative;
>
> options.... # fill out all global options here
>
> #----------
> # Sunray DHCP Vendor Encapsulated Options Definitions
> #----------
> # Setup the vendor encapulated options specific to Sun Ray DTUs. Run
> 'man 5 dhcp-options' and search for 'VENDOR ENCAPSULATED OPTIONS' for
> more information.
>
> # Production Environment
> option space SunRay-ProdEnv; # 'SunRay-ProdEnv' is an arbitary value,
> but needs to be used consistently for all the 'options' that apply to
> this space.
> option SunRay-ProdEnv.altauth code 35 = array of ip-address; # Optional
> List of Sun Ray server IP addresses
> option SunRay-ProdEnv.authsrvr code 21 = ip-address; # Mandatory Single
> Sun Ray server IP address
> option SunRay-ProdEnv.authport code 22 = unsigned integer 16; # Optional
> Sun Ray server port
> option SunRay-ProdEnv.barrierlevel code 36 = unsigned integer 32; #
> Mandatory Firmware Download: barrier level
> option SunRay-ProdEnv.fwsrvr code 31 = ip-address; # Optional Firmware
> tftp server IP address
> option SunRay-ProdEnv.intf code 29 = text; # Optional Sun Ray server
> interface name
> option SunRay-ProdEnv.loghost code 24 = ip-address; # Optional Syslog
> server IP address
> option SunRay-ProdEnv.logkern code 25 = unsigned integer 8; # Optional
> Log level for kernel
> option SunRay-ProdEnv.lognet code 26 = unsigned integer 8; # Optional
> Log level for network
> option SunRay-ProdEnv.logusb code 27 = unsigned integer 8; # Optional
> Log level for USB
> option SunRay-ProdEnv.logvid code 28 = unsigned integer 8; # Optional
> Log level for video
> option SunRay-ProdEnv.logappl code 28 = unsigned integer 8; # Optional
> Sun Ray server interface namea (== logvid??)
> option SunRay-ProdEnv.newtbw code 30 = unsigned integer 32; # Optional
> Bandwidth cap
> option SunRay-ProdEnv.newtpispindx code 32 = unsigned integer 32; #
> Optional Obsolete. Do not use.
> option SunRay-ProdEnv.newtflags code 34 = unsigned integer 32; #
> Optional Obsolete. Do not use.
> option SunRay-ProdEnv.newtver code 23 = text; # Optional Desired
> firmware version
>
> # Test Environment
> option space SunRay-TestEnv; # 'SunRay-TestEnv' is an arbitary value,
> but needs to be used consistently for all the 'options' that apply to
> this space.
> option SunRay-TestEnv.altauth code 35 = array of ip-address; # Optional
> List of Sun Ray server IP addresses
> option SunRay-TestEnv.authsrvr code 21 = ip-address; # Mandatory Single
> Sun Ray server IP address
> option SunRay-TestEnv.authport code 22 = unsigned integer 16; # Optional
> Sun Ray server port
> option SunRay-TestEnv.barrierlevel code 36 = unsigned integer 32; #
> Mandatory Firmware Download: barrier level
> option SunRay-TestEnv.fwsrvr code 31 = ip-address; # Optional Firmware
> tftp server IP address
> option SunRay-TestEnv.intf code 29 = text; # Optional Sun Ray server
> interface name
> option SunRay-TestEnv.loghost code 24 = ip-address; # Optional Syslog
> server IP address
> option SunRay-TestEnv.logkern code 25 = unsigned integer 8; # Optional
> Log level for kernel
> option SunRay-TestEnv.lognet code 26 = unsigned integer 8; # Optional
> Log level for network
> option SunRay-TestEnv.logusb code 27 = unsigned integer 8; # Optional
> Log level for USB
> option SunRay-TestEnv.logvid code 28 = unsigned integer 8; # Optional
> Log level for video
> option SunRay-TestEnv.logappl code 28 = unsigned integer 8; # Optional
> Sun Ray server interface namea (== logvid??)
> option SunRay-TestEnv.newtbw code 30 = unsigned integer 32; # Optional
> Bandwidth cap
> option SunRay-TestEnv.newtpispindx code 32 = unsigned integer 32; #
> Optional Obsolete. Do not use.
> option SunRay-TestEnv.newtflags code 34 = unsigned integer 32; #
> Optional Obsolete. Do not use.
> option SunRay-TestEnv.newtver code 23 = text; # Optional Desired
> firmware version
>
> #----------
> # Define Production & Testing Sunray Environments Section
> #----------
> # dhcpd checks host statements before checking class statements.
> #
> # An excert from that section:
> #
> # When a client is to be booted, its boot parameters are determined by
> consulting that client's host declaration (if any), and then consulting any
> # class declarations matching the client, followed by the pool, subnet
> and shared-network declarations for the IP address assigned to the client.
> # Each of these declarations itself appears within a lexical scope, and
> all declarations at less specific lexical scopes are also consulted for
> # client option declarations. Scopes are never considered twice, and if
> parameters are declared in more than one scope, the parameter declared in
> # the most specific scope is the one that is used.
> #
> # Run 'man 5 dhcpd.conf' and read the 'DESCRIPTION' section for more
> infomation.
>
> # Production Sunray Class
> class "ProductionSunray" {
> match if vendor-class-identifier = "SUNW.NewT.SUNW";
> option dhcp-parameter-request-list 1,2,3,23,43,51,54,49,62;
> vendor-option-space SunRay-ProdEnv;
> option SunRay-ProdEnv.altauth prodsunray2.example.com,
> prodsunray3.example.com, prodsunray4.example.com;
> option SunRay-ProdEnv.authsrvr prodsunray1.example.com;
> option SunRay-ProdEnv.fwsrvr prodsunray1.example.com;
> option SunRay-ProdEnv.loghost prodsunray1.example.com;
> }
>
> # Testing Suray Group
> group "TestingSunray" {
> option dhcp-parameter-request-list 1,2,3,23,43,51,54,49,62;
> vendor-option-space SunRay-TestEnv;
> option SunRay-TestEnv.altauth testsunray1.example.com;
> option SunRay-TestEnv.authsrvr testsunray1.example.com;
> option SunRay-TestEnv.fwsrvr testsunray1.example.com;
> option SunRay-TestEnv.loghost testsunray1.example.com;
>
> # Training Room Sunrays
> host sunray01 { hardware ethernet xx:xx:xx:xx:xx:xx; } # Asset Number
> XXXXX; Owned by Joe Bloggs
> host sunray02 { hardware ethernet yy:yy:yy:yy:yy:yy; } # Asset Number
> XXXXX; Owned by Jane Bloggs
> host sunray03 { hardware ethernet zz:zz:zz:zz:zz:zz; } # Asset Number
> XXXXX; Owned by Fred Bloggs
> host sunray04 { hardware ethernet aa:aa:aa:aa:aa:aa; } # Asset Number
> XXXXX; Owned by Peter Bloggs
> host sunray05 { hardware ethernet bb:bb:bb:bb:bb:bb; } # Asset Number
> XXXXX; Owned by Madonna Bloggs
> host sunray06 { hardware ethernet cc:cc:cc:cc:cc:cc; } # Asset Number
> XXXXX; Owned by Bloggy Bloggs
> }
>
> subnet 192.168.1.0 netmask 255.255.255.0 {
> option routers 192.168.1.1;
> option subnet-mask 255.255.255.0;
> option broadcast-address 192.168.1.255;
> pool {
> range 192.168.1.30 192.168.1.254;
> }
> }
> --- snip ---
>
> Regards,
>
> Stewart
>
>
>
>
> Stewart Walters wrote:
>> Hi Glenn, Mailinglist,
>>
>> Thanks for the reply.
>>
>> Do you know at all if it's possible to do multiple match statements?
>>
>> e.g.
>>
>> class "TestingSunray" {
>> match vendor-class-identifier = "SUNW.NewT.SUNW" and hardware;
>> option space...
>> option...
>> }
>>
>> Or even like this?
>>
>> class "ProductionSunray {
>> if not match class "TestingSunray" and match vendor-class-identifier =
>> "SUNW.NewT.SUNW";
>> option space...
>> option...
>> }
>>
>> I'm just spitballing ideas here, not really sure if dhcpd is capable
>> in this regard.
>>
>> Regards,
>>
>> Stewart
>>
>>
>>
>> Glenn Satchell wrote:
>>> On 04/07/10 19:00, Stewart Walters wrote:
>>>> Hi,
>>>>
>>>> I'm trying to work out what's the best way to configure dhcpd using
>>>> some
>>>> form of evaluation to send different vendor encapsulated options to our
>>>> Sunray thin clients.
>>>>
>>>> We currently have a server which provides a Production Sunray desktop
>>>> environment to our userbase.
>>>>
>>>> If it helps - here is an example of how to set up dhcpd for passing a
>>>> single Sunray environment to 100% of Sunray clients
>>>> (http://blogs.sun.com/lewiz/entry/configuring_sun_ray_dhcp)
>>>>
>>>> As shown in that example, 100% of Sunray clients can be evaluated via
>>>> the vendor-class-identifier = "SUNW.NewT.SUNW"; statement.
>>>
>>> I did something similar many years ago with ISC dhcpd on Solaris.
>>>
>>>> But I want to create a Test Sunray desktop evironment and move 10% of
>>>> our users (determined by MAC address) to a different Testing
>>>> environment. If the conditional evaluation doesn't qualify in the
>>>> 10%, I
>>>> want the remaining 90% of our Sunray clients to receive the Production
>>>> environment options.
>>>>
>>>> I've been reading through dhcp-options(5), dhcpd.conf(5) and
>>>> dhcp-eval(5), as well as several online posts relating to this.
>>>>
>>>> But I'm a little perplexed about what the best approach for this
>>>> kind of
>>>> setup would be.
>>>>
>>>> Would it be better to go, for example:
>>>>
>>>> --- snip ---
>>>> class "TestingSunray" {
>>>> match <some match criteria here>
>>>> <insert Testing vendor encapsulated options here>
>>>> }
>>>>
>>>> subclass "TestingSunray" 1:xx:xx:xx:xx:xx:xx;
>>>> subclass "TestingSunray" 1:yy:yy:yy:yy:yy:yy;
>>>> subclass "TestingSunray" 1:zz:zz:zz:zz:zz:zz;
>>>
>>> The syntax for whatever is in the match line of the class is what
>>> goes in the match portion of the subclass. So in the class if you said:
>>>
>>> class "TestingSunray" {
>>> match hardware;
>>> option space ...
>>> option ...
>>> }
>>>
>>> Then in the subclass you use the hardware address. This needs a
>>> leading 1 which represents ethernet.
>>>
>>> subclass "TestingSunray" 1:xx:xx:xx:xx:xx:xx;
>>>
>>> The sub-class uses a fast hashing algorithm to determine membership,
>>> so it's efficient even where there are lots of clients. See
>>> dhcpd.conf SUBCLASSES section.
>>>
>>>> class "ProductionSunray" {
>>>> match if vendor-class-identifier = "SUNW.NewT.SUNW";
>>>> <insert Production vendor encapsulated options here>
>>>> }
>>>
>>> If you are going to be filling in the option space in different
>>> places, then you should put the option space definitions in the
>>> global scope, and assign the values in the classes or groups.
>>>
>>>> --- snip ---
>>>>
>>>> Does dhcpd even process class matching in the order in which it's
>>>> listed
>>>> in dhcpd.conf? Am I guaranteed in that configuration that a Test Sunray
>>>> wont be classified as Production just because the Testing class is
>>>> defined first?
>>>
>>> What happens here is that some clients will be in *both* classes.
>>> It's not about only matching the first class you come across.
>>> Unfortunately things are not clear about which class definition is
>>> the most specific, ie which one "wins" when both define the same
>>> options. If this point can be clearly defined then the subclass
>>> solution is the definite winner.
>>>
>>> Now for some other ways to clearly use the most specific group.
>>> Consider this paragraph from the dhcpd.conf man page, which specifies
>>> the scoping order:
>>>
>>> When a client is to be booted, its boot parameters are
>>> determined by consulting that client's host declaration (if
>>> any), and then consulting any class declarations matching
>>> the client, followed by the pool, subnet and shared-network
>>> declarations for the IP address assigned to the client.
>>> Each of these declarations itself appears within a lexical
>>> scope, and all declarations at less specific lexical scopes
>>> are also consulted for client option declarations. Scopes
>>> are never considered twice, and if parameters are declared
>>> in more than one scope, the parameter declared in the most
>>> specific scope is the one that is used.
>>>
>>> We could use a group and host statements to make sure we are more
>>> specific than a class. For example this group, and the
>>> ProductionSunrays class above. You only need to put in the options
>>> that are different for testing, as these clients are still members of
>>> ProductionSunrays and will pick up other options from there.
>>>
>>> # testing sunrays
>>> group {
>>> option ...
>>> host "host1" { hardware ethernet xx:xx:xx:xx:xx:xx; }
>>> host "host2" { hardware ethernet xx:xx:xx:xx:xx:xx; }
>>> }
>>>
>>>> Or is it better to do this?
>>>>
>>>> --- snip ---
>>>> class "Sunray" {
>>>> match if substring(hardware,1,3)=xx:xx:xx:xx:xx:xx or
>>>> elsif substring(hardware,1,3)=yy:yy:yy:yy:yy:yy or
>>>> elsif substring(hardware,1,3)=zz:zz:zz:zz:zz:zz;
>>>> <insert Testing vendor encapsulated options here>
>>>> else
>>>> match if option vendor-class-identifier = "SUNW.NewT.SUNW";
>>>> <insert Production vendor encapsulated options here>
>>>> }
>>>> --- snip ---
>>>> (I probably made a bunch of minor syntax errors above, but I can work
>>>> those out later)
>>>
>>> That doesn't scale very well and the logic is not quite right.
>>>
>>> class "Sunray" {
>>> match if option vendor-class-identifier = "SUNW.NewT.SUNW";
>>> # default options for all
>>> option ...
>>>
>>> # option for testing sunrays
>>> if hardware = xx:xx:xx:xx:xx:xx
>>> or substring(hardware,1,3) = yy:yy:yy
>>> or ... {
>>> option ...
>>> }
>>> }
>>>
>>>> Or should I be doing some complicated if and else statements as
>>>> shown in
>>>> the example at
>>>> http://www.linuxforums.org/forum/servers/69851-dhcpd-conf-multiple-subnet-single-physical-network-configuration.html
>>>>
>>>
>>> Having just looked at that page I would *not* recommend using those
>>> methods at all. That guy is deliberately trying to make things as
>>> difficult and complicated as possible. Difficult and complicated
>>> means hard to understand, hard to get working and hard to fix if
>>> things aren't quite right.
>>>
>>>> As you can see, I'm not exactly sure to which way might be best for me.
>>>> Let me say thanks in advance for any assistance you can provide on the
>>>> matter.
>>>
>>> Ah, it is a very interesting question, but the solution comes down to
>>> being able to define the subset of clients that are going to get
>>> different options. That's all.
>>>



More information about the dhcp-users mailing list