Forum: Cfengine Help
Subject: Re: is it possible to combine arrays and lists?
Author: Seva Gluschenko
Link to topic: https://cfengine.com/forum/read.php?3,16807,16815#msg-16815

Neil, here is the almost real keepalived.conf (just IPs, names, and passwords 
were changed):


! Configuration File for keepalived

global_defs {
   router_id ID1
}

vrrp_instance ID1 {
    state MASTER
    interface eth1
    virtual_router_id 111
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass some_pass
    }
    virtual_ipaddress {
        172.16.0.11 label eth1:11
        172.16.0.111 label eth1:111
    }
    notify_backup "/usr/local/bin/vrrp.sh BACKUP ID1"
    notify_master "/usr/local/bin/vrrp.sh MASTER ID1"
    notify_fault  "/usr/local/bin/vrrp.sh FAULT ID1"
}

vrrp_instance ID2 {
    state BACKUP
    interface eth1
    virtual_router_id 112
    priority 99
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass some_pass
    }
    virtual_ipaddress {
        172.16.0.12 label eth1:12
        172.16.0.112 label eth1:112
    }
    notify_backup "/usr/local/bin/vrrp.sh BACKUP ID2"
    notify_master "/usr/local/bin/vrrp.sh MASTER ID2"
    notify_fault  "/usr/local/bin/vrrp.sh FAULT ID2"
}



The relevant dummy interfaces are configured as follows:


# cat /etc/sysconfig/network-scripts/ifcfg-dummy0\:112
DEVICE=dummy0:112
BOOTPROTO=none
ONBOOT=yes
IPADDR=172.16.0.112
NETMASK=255.255.255.255
TYPE=Ethernet



The servers are working in pairs, so I have ID1 and ID2 pair with swapped 
master and slave instances, ID3 and ID4 pair etc. Each pair has its set of IPs, 
router ids and virtual router ids, all remaining pieces of the configuration 
are identical, so I believe it would be correct to build the configuration from 
templates.

Well, I'm really not just sitting here and whining for somebody's help. I'm 
wasting the whole today trying to troubleshoot this situation, and sometimes it 
seems like things are only getting worse. After careful research I've got the 
following setup which allows me to maintain only one instance of variables 
without redefining them:


bundle common c
{
 vars:
        "external_eth" string => "eth1";
}

bundle agent vrrp
{
 vars:
        "id"    string => "keepalived";
        "cfg"   string => "/etc/keepalived.conf";
        "src"   string => "vrrp.sh";
        "scrpt" string => "/usr/local/bin/$(src)";

        "dummy_iface"   string  => 
"/etc/sysconfig/network-scripts/ifcfg-dummy0";

    vr1|vr2::
        "net"   string  => "172.16.0";
        "ip1"   int     => "40";
        "ip2"   int     => "41";

    vr3|vr4::
        "net"   string  => "172.16.90";
        "ip1"   int     => { "38", "138", "178" };
        "ip2"   int     => { "39", "139", "179" };

    vr1|vr3::
        "my"    ilist   => { @(ip1) };
        "his"   ilist   => { @(ip2) };

    vr2|vr4::
        "my"    ilist   => { @(ip2) };
        "his"   ilist   => { @(ip1) };

 files:
  "$(cfg)"
        comment         => "Set up $(id) configuration file",
        edit_line       => vrrp_cf("$(net)", "$(scrpt)"),
        edit_defaults   => reconstruct,
        perms           => mo("400", "root");

  "$(dummy_iface):$(my)"
        comment         => "Set up dummy interfaces",
        edit_line       => dummy_list("$(my)", "$(net)"),
        edit_defaults   => reconstruct,
        perms           => mog("555", "root", "root");
}

########################################################

bundle edit_line vrrp_cf(net, scrpt)
{
 vars:
        "ip1"   ilist   => { @(do_vrrp.my) };
        "ip2"   ilist   => { @(do_vrrp.his) };

        "pass"  string  => "some_pass";

        "id"  int       => "20";
        "id"  int       => "21";
        "id"  int       => "22";
        "id"  int       => "20";

     vr1::
        "my"    string  => "ID1";
        "his"   string  => "ID2";

    vr2::
        "my"    string  => "ID2";
        "his"   string  => "ID1";

    vr3::
        "my"    string  => "ID3";
        "his"   string  => "ID4";

    vr4::
        "my"    string  => "ID4";
        "his"   string  => "ID3";

    any::
        "nfy"   string  => "BACKUP";
        "nfy"   string  => "MASTER";
        "nfy"   string  => "FAULT";
        "nlist"         slist           => getindices("nfy");

 insert_lines:

"! Configuration File for keepalived, generated by Cfengine
global_defs {
   router_id $(my)
}

vrrp_instance $(my) {
    state MASTER
    interface $(c.external_eth)
    virtual_router_id $(id[$(my)])
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass $(pass)
    }
    virtual_ipaddress {
        $(net).$(ip1) label $(c.external_eth):$(ip1)
    }
    notify_$(nlist) \"$(scrpt) $(nfy[$(nlist)]) $(item)\""
}

vrrp_instance $(his) {
    state BACKUP
    interface $(c.external_eth)
    virtual_router_id $(id[$(his)])
    priority 97
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass $(pass)
    }
    virtual_ipaddress {
        $(net).$(ip2) label $(c.external_eth):$(ip2)
    }
    notify_$(nlist) \"$(scrpt) $(nfy[$(nlist)]) $(item)\""
}
"
         comment => "VRRP configuration";
}


Note that I don't even try to virtualize vrrp instances, just because I know 
that iteration depth isn't enough. Well, wanna see the result for cf-agent -D 
vr3 -f ./test.cf? Here it is:

! Configuration File for keepalived, generated by Cfengine
global_defs {
   router_id ID3
}

vrrp_instance ID3 {
    state MASTER
    interface eth1
    virtual_router_id 22
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass some_pass
    }
    virtual_ipaddress {
        172.16.90.38 label eth1:38
    }
    notify_fault "/usr/local/bin/vrrp.sh FAULT ID3"
}

vrrp_instance ID4 {
    state BACKUP
    interface eth1
    virtual_router_id 20
    priority 97
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass some_pass
    }
    virtual_ipaddress {
        172.16.90.39 label eth1:39
    }
    notify_fault "/usr/local/bin/vrrp.sh FAULT ID4"
}
        172.16.90.138 label eth1:138
        172.16.90.178 label eth1:178
    notify_master "/usr/local/bin/vrrp.sh MASTER ID3"
    notify_master "/usr/local/bin/vrrp.sh MASTER ID4"
    notify_backup "/usr/local/bin/vrrp.sh BACKUP ID3"
    notify_backup "/usr/local/bin/vrrp.sh BACKUP ID4"
        172.16.90.139 label eth1:139
        172.16.90.179 label eth1:179

Fantastic, eh?

That happens because of list iteration disorder which I've reported already to 
the bug tracker, but for the moment nobody seems to be interested.

So I mark the places where to insert lines with comments:


    virtual_ipaddress { ! backup interfaces
    }
    ! backup notices


and then insert lines there with the separate promise like this:

           "        $(net).$(ip1) label $(c.external_eth):$(ip1)"
                location => after(".*! master interfaces");

It produces a lot of warnings:
 
!! insert_lines promise uses the same select_line_matching anchor as another 
promise. This will lead to non-convergent behaviour.
Promise (version not specified) belongs to bundle 'vrrp_cf' in file 
'./vrrptest.cf' near line 252


But at least it works.

_______________________________________________
Help-cfengine mailing list
[email protected]
https://cfengine.org/mailman/listinfo/help-cfengine

Reply via email to