Take some of the headaches out of managing sever farms with Cfengine 3. Use this automation introduction to save time, money and spare yourself crippling manual mistakes.
Here we see that the Perl Compatible Regular Expression (PCRE) library is being used. Success.
At this point you could do a make install, as root of course, and the binaries and support files will be installed into the default prefix of /usr/local unless you’ve change it. There is however another option.
Instead of using ‘make install’ you could manually install the files and have Cfengine keep them up to date for you. For example we often manually install the binaries into /var/cfengine/bin and the man pages into standard /usr/share/ man. We also keep copies of these files in our masterfiles repository. Then we configure promises in Cfengine to ensure that the files on client hosts match the files in the masterfiles repository. Using this method we are able to build new binaries once, copy them to masterfiles and Cfengine will automatically distribute them to all of our client hosts.
The basic grammar of Cfengine 3 looks like this:
type:
classes::
"promiser" -> { "promisee1", "promisee2", ... }
attribute_1 => value_1,
attribute_2 => value_2,
...
attribute_n => value_n;
A class is a built-in if/then test, and if it is specified, the rule will hold only if that class is true for that machine. Examples of built-in classes can be: “Linux”, “Solaris”, “CentOS”, “Thursday”, “2:00am-3:00am”, a particular IP address on the host, etc. Examples of user-defined classes can be “database server” or all machines administered by our department.
Example: Hello World.Â
commands:
"/bin/echo hello world";
The promise type is “commands”, the promiser is the command string.
List of promise types
- commands – Run external commands
- files – Handle files (permissions, copying, etc.)
- edit_line – Handle files (content)
- interfaces – Network configuration
- methods – Methods are compound promises that refer to whole bundles of promises.
- packages – Package management
- processes – Process management
- storage – Disk and filesystem management
Another simple example:Â
files:
"/tmp/test_plain" -> "John Smith",
comment => "Make sure John's /tmp/test_plain exists",
create => "true";
Here we have the promisee on the right of the -> sign.
The promisee is “the abstract object to whom the promise is made”. This is for documentation. The commercial version of cfengine uses promisees to generate automated knowledge maps. The object can be the handle of another promise, recognizing an interest in the outcome, or an affected person who you might want to contact in case of emergency.
Example of a handle (id tag):Â
files:
"/tmp/test_plain" -> "John Smith",
handle => "file_check",
comment => "Make sure John's /tmp/test_plain exists",
create => "true";
Documenting a dependency with a handle:Â
files:
"/tmp/testcopy"
depends_on => { "file_check" },
copy_from => mycopy("/tmp/test_plain");
These are contrived examples; they document John Smith as somehow involved in this activity and show how handles can be used to document dependencies.
The above are not working examples. But this is, and you can run it to get familiar with Cfengine 3:
Make sure /tmp/test_plain exists.Â
########################################################
body common control
{
version => "1.0";
bundlesequence => { "test1" };
}
########################################################
bundle agent test1
{
files:
"/tmp/test_plain" -> "John Smith",
comment => "Make sure /tmp/test_plain exists",
create => "true";
}
First is the mandatory control section, where you can set certain values, and specify which promise bundles to run.
The next section is a promise bundle, which means a group of one or more promises. The bundle type is “agent” which means it will result in action on the part of Cfengine, or will be picked up by the Cfengine agent when it runs (cf-agent).
Each promise bundle has a name, and that name is referenced in bundlesequence in control.
Thus the above promise bundle is a promise that /tmp/test_plain exists; and specifies John Smith as an involved party.
Put the above in test.cf and run it with
cf-agent -f test.cf
If the file does not exist, Cfengine will create it.
Promise that ntpd and portmap are running.Â
body common control
{
version => "1.0";
bundlesequence => { "check_service_running" };
}
bundle agent check_service_running
{
vars:
"service" slist => {"ntpd", "portmap"};
"daemon_path" string => "/etc/init.d";
processes:
"${service}"
comment => "Check processes running for '${service}'",
restart_class => "restart_$(service)";
commands:
"${daemon_path}/${service} start"
comment => "Execute the start command for the service",
ifvarclass => "restart_${service}";
}
This uses variables (lists and strings); and when cf-agent hits the ${service} variable, which is a list, it loops over the list. This implicit looping is part of the power of Cfengine.
Promise content of /etc/resolv.conf.Â
body common control
{
version => "1.0";
bundlesequence => { "checkresolver" };
}
bundle agent checkresolver
{
vars:
"resolvers" slist => { "128.39.89.10", "158.36.85.10", "129.241.1.99" };
files:
"${sys.resolv}"
edit_line => resolvconf("iu.hio.no cfengine.com",@{checkresolver.resolvers});
}
bundle edit_line resolvconf(search,list)
{
delete_lines:
"search.*";
insert_lines:
"search ${search}";
"${list}";
}
“body common control{}” is the control promise body, which affects the operational behavior of Cfengine. In it, we define a version string, used in errors and reports.
Next we have a promise bundle “checkresolver{}” which uses:
- An “slist”, a list of scalar strings,
- “${sys.resolv}”, a system variable (built in to Cfengine) that containes the path to our resolv.conf file.
- checkresolver{} calls the promise bundle “resolvconf{}” which is of the editline promise type. Cfengine has built-in functionality for editing files, as this is a common system administration task, and editlines promises handle that. For example:
- “delete_lines promise” will make sure we don’t end up with duplicate “search” lines which would be invalid for /etc/resolv.conf.
- The “insert_lines” promise will make sure the file contains the specified data, which are a string (the search path) and an array (list of resolvers).
Note: we have to reference the @resolvers array using its full name, @checkresolver.resolvers, otherwise resolvconf will fail to find a @resolvers array within its own scope. The @resolvers array is in the scope of “checkresolver{}”.
You may have noticed the above Cfengine configuration is in two kinds of parts: a body or a bundle. What are they?
Bundle: A promise bundle is a collection of promises.
Body: A promise body is the part of a promise which details and constrains its nature. The body of a promise explains what it is about. Think of the body of a contract, or the body of a document. Cfengine “body” declarations divide up these details into standardized, paramaterizable, library units, so we can just write:
Snippet example of cf-agent client copying a file from cf-serverd (not a full working example).Â
body copy_from my_secure_cp(from,server)
{
source => "$(from)";
servers => { "$(server)" };
compare => "digest";
encrypt => "true";
verify => "true";
force_ipv4 => "false";
collapse_destination_dir => "false";
copy_size => irange("0","50000");
findertype => "MacOSX";
# etc etc
}
Think of the declarations in the promise as:
(cfengine-word) ⇒ (user-data-pattern)
body cfengine-word user-data-pattern
{
details
}
Working example of copying a file with cfengine, call it test_copy.cf.Â
body common control
{
bundlesequence ⇒ { "testcopy" };
version ⇒ "1.2.3";
inputs ⇒ { "library.cf" };
}
bundle agent testcopy
{
files:
"/home/aleksey/testcopy1"
copy_from ⇒
my_copy_body_with_options("/home/aleksey/testcopy2","192.168.1.10");
}
body copy_from my_copy_body_with_options(sourcefile,sourceserver)
{
source ⇒ "$(sourcefile)";
servers ⇒ { "$(sourceserver)" };
copy_backup ⇒ "true";
purge ⇒ "true";
trustkey ⇒ "true";
compare ⇒ "digest";
encrypt ⇒ "true";
verify ⇒ "true";
force_ipv4 ⇒ "false";
collapse_destination_dir ⇒ "false";
copy_size ⇒ irange("0","50000");
# etc. etc.
}
Note: In order to get this example to work, we had to:
Modify “runagent control{}” and “server control{}” in promises.cf to remove mention of localhost (127.0.0.1 and ::1), replacing them with the IP address of the primary interface of 192.168.1.10.
Modify “server control{}” in promises.cf to add a non-root user to “allowusers” because we were running cf-serverd as a non-root user.
Here is the part of promises.cf we modified:Â
body runagent control
{
hosts => {
"192.168.1.10"
# , "myhost.example.com:5308", ...
};
}
#######################################################
body server control
{
allowconnects => { "192.168.1.10" };
allowallconnects => { "192.168.1.10" };
trustkeysfrom => { "192.168.1.10" };
# make updates and runs happen in one
cfruncommand => "$(sys.workdir)/bin/cf-agent -f failsafe.cf &&
$(sys.workdir)/bin/cf-agent";
allowusers => { "root" , "aleksey" };
}
We also had to modify “server access_rules{}” in site.cf to set up the ACL to allow the file transfer. Running cf-serverd in verbose mode with debugging set to 1 will show more information about how the server handles requests.
Here are our changes to site.cf: .Â
#######################################################
# server configuration
#######################################################
bundle server access_rules()
{
access:
"/home/aleksey/testcopy2"
admit => { "192.168.1.10" };
roles:
".*" authorize => { "aleksey" };
}
Generate a keypair for our cf-serverd:
cf-key
Start cf-serverd in verbose (non-forked) mode, debug level 1:
cf-serverd -v -d 1
Run our example code to copy the file from cf-serverd:
cf-agent -v test_copy.cf -k
More Information
cfengine contains far more features that we can touch upon in just this one introduction. To learn more about cfengine and how you can put it to use, check out the following resources:
Learning More
There will be a full day of Cfengine training at the LISA system administration conference in Boston in December 2011 http://www.usenix.org/event/lisa11/
Comments on "Intro to Automating System Administration with Cfengine 3"
Free binaries for a lot of Linux distros are available at the tech corner (free, registration required). http://www.cfengine.org/pages/software
Aleksey
CFengine is a great solution, a very powerful tool in my opinion, it’s enough here to mention only that it allows to control servers from a central Graham and Green location.
Oh, I don’t like at all registrations even when it’s all about free PR Agency stuff to be honest.
I think most of us will agree with the kind of headache one has to go when dealing with many farms. I think CFengine 3 can really change that condition from what I have read here. money,time and attendance of virtually all administrators are at the mercy of these organizations! Controlling and managing servers from a main location sounds really exciting and if this is a success, then lots of time and money can be saved!
I agree, Controlling and managing servers from a main location sounds really exciting and if this is a success, then lots of time and money can be saved! driving instructor training
This is a great engine. I have really felt the difference using it for my golf simulator engine programs.
Yes,I agree with you.Excited?if it can do,will save large of money and time.I look forward.pellet mill die
Its very cool if you could save some,check the ajleeonline for more tips.
Great post my friend, i really enjoyed reading your article.
the sudacademy seo
Congrats on the launch! Looks like a great resource for the community.
cuu du lieu
Interesting blog! Is your theme custom made or did you download it from somewhere? A theme like yours with a few simple tweeks would really make my blog shine. Please let me know where you got your theme. Bless you..
garment accessories
Many posts have been seen on American legion history and among all of these I think it is the best one in where all the topics are discussed that is related to the topic.Please let me know more about this as well as about Haircutters.I hope you will help me to get information about it.
Fantastic goods from you, man. Ive study your stuff ahead of and you are just as well amazing. I enjoy what you’ve got right here, adore what you are stating and the way you say it. You make it entertaining and you even now manage to help keep it wise. I cant wait to go through additional from you. That is really an incredible web blog and for that I want to get more blogs on it.I also want to get posts on Popular Restaurants.Is it possible for you?
I am really interested in your post, thanks for sharing.
Scot
Thank you for sharing this informations
Mark Antony
that black screen you’re using reminds me of the days when we all worked from DOS. Even to get into windows!
Jeff from Dallas CPR Certification
Looks like you could really automate something like a virus from this kind of software. Be careful what you wish for. You never know if a Miami car accident lawyer could come after you.
Appreciate your blog an exceptionally decent article, It happened to see your website page as well as several written piece. Is exceedingly good type publishing. writing service
Appreciate your blog an exceptionally decent article, It happened to see your website page as well as several written piece. Is exceedingly good type publishing. 8.1 update
that black screen you’re using reminds me of the days when we all worked from DOS. Even to get into windows! genuine pass
Thank you for sharing this informations pretty scary update
Very good article on using SSH, would be great to see a well explained document outlining the commands for our WordPress Agency