Conditional evaluation question.
Stewart Walters
stw at bgc.com.au
Mon Apr 19 14:14:06 UTC 2010
Hi List,
Just FYI - looks like my config from the 8th April 2010 had a tiny error
in it which created a massive problem.
If your a Sunray user reading my post from the 20100408, please do not
use that config I submitted previously. The "match if" statement in the
ProductionSunray class is wrong. It should read "match if option".
Using the incorrect config does not cause dhcpd to complain about syntax
error (not even in debug logging mode). While it allocates an IP
address to the Sunray client, it fails to pass on any vendor
encapsulated options at all. The Sunrays at that point display boot
error code 27B with this config.
I didn't pick up on this at first because I had a working config
internally on my proof-of-concept server (using a "match if option").
At some point while I was typing the 8th of April email (or maybe when I
was generic-ising the information), "match if option" became "match if".
Subsequently when I rebuilt the proof-of-concept server last weekend to
a development server, for some reason I did not restore my backup of
dhcpd.conf. Instead copied my own work from April 8th and hit the problem.
The corrected config, taking in to account Glenn's suggestion that the
difference in arbitrary names for Production and Test settings is not
required, is as follows:
--- 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.
option space SunRay-VendEncOpts; # 'SunRay-VendEncOpts' is an arbitary
value, but needs to be used consistently for all the 'options' that
apply to this space.
option SunRay-VendEncOpts.altauth code 35 = array of
ip-address; # Optional List of Sun Ray server IP addresses
option SunRay-VendEncOpts.authsrvr code 21 =
ip-address; # Mandatory Single Sun Ray server IP address
option SunRay-VendEncOpts.authport code 22 = unsigned integer
16; # Optional Sun Ray server port
option SunRay-VendEncOpts.barrierlevel code 36 = unsigned integer
32; # Mandatory Firmware Download: barrier level
option SunRay-VendEncOpts.fwsrvr code 31 =
ip-address; # Optional Firmware tftp server IP address
option SunRay-VendEncOpts.intf code 29 =
text; # Optional Sun Ray server interface name
option SunRay-VendEncOpts.loghost code 24 =
ip-address; # Optional Syslog server IP address
option SunRay-VendEncOpts.logkern code 25 = unsigned integer
8; # Optional Log level for kernel
option SunRay-VendEncOpts.lognet code 26 = unsigned integer
8; # Optional Log level for network
option SunRay-VendEncOpts.logusb code 27 = unsigned integer
8; # Optional Log level for USB
option SunRay-VendEncOpts.logvid code 28 = unsigned integer
8; # Optional Log level for video
option SunRay-VendEncOpts.logappl code 28 = unsigned integer
8; # Optional Sun Ray server interface namea (== logvid??)
option SunRay-VendEncOpts.newtbw code 30 = unsigned integer
32; # Optional Bandwidth cap
option SunRay-VendEncOpts.newtpispindx code 32 = unsigned integer
32; # Optional Obsolete. Do not use.
option SunRay-VendEncOpts.newtflags code 34 = unsigned integer
32; # Optional Obsolete. Do not use.
option SunRay-VendEncOpts.newtver code 23 =
text; # Optional Desired firmware version
#----------
# Define Production & Testing Sunray Environments Section
#----------
# dhcpd checks host statements before checking class statements.
#
# As such, if dhcpd can match the booting Sunray's MAC address as a host
statement within the group "TestingSunray",
# then the Sunray receives vendor encapsulated options for the Testing
environment.
#
# If dhcpd does not find a MAC address match, then it matches the vendor
class identifier that all Sunray's
# possess ("SUNW.NewT.SUNW") and the Sunray will receive vendor
encapsulated options for the Production
# environment instead.
#
# An excerpt from the man page:
#
# 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 option vendor-class-identifier = "SUNW.NewT.SUNW";
option dhcp-parameter-request-list 1,2,3,23,43,51,54,49,62;
vendor-option-space SunRay-VendEncOpts;
option SunRay-VendEncOpts.altauth prodsunray2.example.com,
prodsunray3.example.com, prodsunray4.example.com;
option SunRay-VendEncOpts.authsrvr prodsunray1.example.com;
option SunRay-VendEncOpts.fwsrvr prodsunray1.example.com;
option SunRay-VendEncOpts.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-VendEncOpts;
option SunRay-VendEncOpts.altauth testsunray1.example.com;
option SunRay-VendEncOpts.authsrvr testsunray1.example.com;
option SunRay-VendEncOpts.fwsrvr testsunray1.example.com;
option SunRay-VendEncOpts.loghost testsunray1.example.com;
# Enter your Testing Sunray MAC addresses below.
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,
>
> 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.
>>>
>> _______________________________________________
>> dhcp-users mailing list
>> dhcp-users at lists.isc.org
>> https://lists.isc.org/mailman/listinfo/dhcp-users
> _______________________________________________
> dhcp-users mailing list
> dhcp-users at lists.isc.org
> https://lists.isc.org/mailman/listinfo/dhcp-users
More information about the dhcp-users
mailing list