330 likes | 459 Views
How to write LCFGng components for EDG. 10/2002 German.Cancio@cern.ch. Overview. LCFG – short reminder Slides stolen from Enrico and Massimo / INFN Writing LCFGng Components for EDG usage Examples Documentation and links. LCFG – short reminder. WP4 & LCFG.
E N D
How to write LCFGng components for EDG 10/2002 German.Cancio@cern.ch
Overview • LCFG – short reminder Slides stolen from Enrico and Massimo / INFN • Writing LCFGng Components for EDG usage • Examples • Documentation and links
WP4 & LCFG • LCFG is originally developed by the Computer Science Department of Edinburgh University • Handles automated installation, configuration and management of machines • Basic features: • automatic installation of O.S. • installation/upgrade/removal of all (rpm-based) software packages • centralized configuration and management of machines • extendible to configure and manage custom application software
<inet> <allow cfg:template="allow_$ tag_$ daemon_$"> <allow_RECORD cfg:name="telnet"> <allow>192.168., 192.135.30.</allow> </allow_RECORD> ..... </auth> <user_RECORD cfg:name="mickey"> <userhome>/home/MickeyMouseHome</userhome> <usershell>/bin/tcsh</usershell> </user_RECORD> XML profiles Config files +inet.services telnet login ftp +inet.allow telnet login ftp sshd +inet.allow_telnet ALLOWED_NETWORKS +inet.allow_login ALLOWED_NETWORKS +inet.allow_ftp ALLOWED_NETWORKS +inet.allow_sshd ALL +inet.daemon_sshd yes ..... +auth.users myckey +auth.userhome_mickey /home/mickey +auth.usershell_mickey /bin/tcsh LCFG Config Files Read Profile Load Profile HTTP rdxprof ldxprof /etc/shadow Profile Generic /etc/group Object Make XML Profile Component /etc/passwd .... mickey:x:999:20::/home/Mickey:/bin/tcsh .... Web Server Local cache /etc/services XML Profile LCFG Objects /etc/inetd.conf Profile /etc/hosts.allow in.telnetd : 192.168., 192.135.30. in.rlogind : 192.168., 192.135.30. in.ftpd : 192.168., 192.135.30. sshd : ALL Object Client nodes Server inet auth LCFG diagram Abstract configuration parameters for all nodes stored in a central repository A collection of agents read configuration parameters and either generate traditional config files or directly manipulate various services
LCFG configuration (I) • Most of the configuration data are common for a category of nodes (e.g. diskservers, computing nodes) and only a few are node-specific (e.g. hostname, IP-address) • Using the cpp preprocessor it is possible to build a hierarchical structure of config files containing directives like #define, #include, #ifdef, comments with /* */, etc... • The configuration of a typical LCFG node looks like this: #define HOSTNAME pc239 /* Host specific definitions */ #include "site.h" /* Site specific definitions */ #include "linuxdef.h" /* Common linux resources */ #include "client.h" /* LCFG client specific resources */
LCFG configuration (II) From "site.h" #define LCFGSRV grid01 #define URL_SERVER_CONFIG http://grid01/lcfg #define LOCALDOMAIN .lnl.infn.it #define DEFAULT_NAMESERVERS 192.135.30.245 [...] From "linuxdef.h" update.interfaces eth0 update.hostname_eth0 HOSTNAME update.netmask_eth0 NETMASK [...] From "client.h" update.disks hda update.partitions_hda hda1 hda2 update.pdetails_hda1 free / update.pdetails_hda2 128 swap auth.users mickey auth.usercomment_mickey Mickey Mouse auth.userhome_mickey /home/Mickey [...]
LCFG: configuration changes • Server-side: when the config files are modified, a tool (mkxprof) recreates the new xml profile for all the nodes affected by the changes • this can be done manually or with a daemon periodically checking for config changes and calling mkxprof • mkxprof can notify via UDP the nodes affected by the changes • Client-side: another tool (rdxprof) downloads the new profile from the server • usually activated by an LCFG component at boot • can be configured to work as • daemon periodically polling the server • daemon waiting for notifications • started by cron at predefined times
LCFG: what’s a component? • Component == object • It's a Perl script (also shell scripts accepted for historic reasons) • We recommend to phase out shell components. • A backwards compatibility module allows to import old-style components without any modifications. • Each component provides a Configure() method invoked on startup or when configuration changes • A simple and typical component behaviour: • Started when notified of a configuration change • Loads its configuration (locally cached) • Configures the appropriate services, by translating config parameters into a traditional config file and reloading a service if necessary (e.g. restarting a init.d service).
LCFG: custom components • LCFG provides components to manage the configuration of services of a machine: inet, auth, nfs, cron, ... • Admins can build new custom components to configure and manage their own applications: • define your custom “resources” (configuration parameters) • Write a script containing standard methods with your custom code. • Include in your script a generic library, which contains the definition of common function used by all components (config loading, log, output, ...) • For simple components usually just a few lines of code
Writing LCFG components for EDG • Software written for EDG should be portable to whatever farm management system is used. • It is therefore recommended to use whenever possible, standard SysV procedures for managing services: init.d scripts and chkconfig. • LCFG should not be used for replacing existing SysV init.d functionality! • LCFG should be used for • retrieving configuration information from the CDB and recreate local config files • Restarting services if needed via init.d scripts (restart/reload) • Enabling/disabling SysV services to match the configuration DB’s contents (using chkconfig)
LCFG component methods for EDG Only method to implement: • Configure(): Reconfigures the service and notifies running processes. • Methods not recommended for EDG, but available in LCFGng: • Start(), Stop(), Run(), Suspend(), Resume()
EDG / LCFG component template (I) #!/usr/bin/perl -w package LCFG::MyComp; @ISA = qw(LCFG::Component); use strict; use LCFG::Component; use LCFG::Config; # EDG specific sub Configure($$@) { my ($self,$res) = @_; my $config=LCFG::Config->new($res); my $age=$config->getValue('/persons/John/age'); $self->Fail( "too young") unless ($age>18); } new LCFG::MyComp() -> Dispatch();
LCFG component template (II) • Configure() method: # Do the configuration sub Configure($$@) { my ($self,$res) = @_; my $config=LCFG::Config->new($res); # do whatever is neccesary to reconfigure your service }
LCFG component template (IV) • The specific part in the configure() method will usually contain three steps: 1. Access my resources via a special API (NVA API – next slide) my $config=NVA::Config->new(); my $arch=$config->getValue('/system/architecture’); $self->Fail (“not supported") unless ($arch eq ‘i386’); 2. Generate (or update) config file open (MYCONFIG,’/etc/myconfig’); … close(MYCONFIG) 3. Reload/restart a service if neccessary if ($changed) { system(‘/sbin/service myservice reload’); … }
NVA API configuration access library (EDG only) New component configuration access library • This library allows true hierarchical configuration structure access on the client side • Implements a subset of the Node View Access API (v.1) • http://cern.ch/hep-proj-grid-fabric-config/documents/nva • Implemented only for Perl components. • Most popular methods: • $value=$config->getValue (‘/my/path/in/config’); #access value • $element=$config->getElement($path); #configuration element • while ($element->isNextElement()) { # iterations over element lists my $newel=$element->getNextElement();
EDG relevant built-in standard functions • $self->Fail(@array): prints out a [FAIL] message and exits • $self->Warn(@array): prints out [WARNING] message • $self->OK(@array): prints out [OK] message • $self->LogMessage(@array): Adds message to logfile (see also the LCFG/Component.pm file)
Configuration information (I) Configuration information is stored on the LCFG server in two types of files: • The resource definition files (.def) • The normal .h & machine configuration files.
Configuration information (II) 1. The .def files contain default resource information: mycomp.def /* EDG LCFG mycomponent: default resources */ /* schema version always=1 */ schema 1 /* defined resources and defaults */ myconfig1 myconfig2 defaultvalue2
Configuration information (III) 2. The normal .h & machine config files, where the default configuration is enhanced/overwritten: mycomponent.<resource> <value> mycomp.myconfig1 whatevervalue mycomp.myconfig2 whateverothervalue Some special resources have to be declared for including a component to be deployed: # add to profile (always needed) EXTRA(profile.components) mycomp # define XML profile version (always set to 1) profile.version_mycomp 1 # start on boot time (if required) EXTRA(boot.services) mycomp
Hierarchical configurations (I) • Sometimes, key-value pairs are not sufficient for the required configurations. • For example: arrays or lists • LCFG has a complex server side mechanism for mapping hierarchical structures into key-value pairs… • Table with person names, ages, and phone numbers (.def file) @persons age_$ phone_$ persons age_$ phone_$
Hierarchical configurations (II) Now we want to add the following to the node config: • John, 35, 12346 and Phil, 21, 54321 The node config file will look like: mycomp.persons John Phil mycomp.age_John 35 mycomp.phone_John 12346 mycomp.age_Phil 21 mycomp.phone_Phil 54321 The /persons/John/age, /persons/John/phone, /persons/Phil/age, /persons/Phil/phone resources will be accessible to the client via the NVA API.
Hierarchical configurations (III) The component accessing the info needs to do: my $personlist=$config->getElement(‘/persons’); while($personlist->isNextElement()) { my $person=$personlist->getNextElement(); my $phone=$config->getElement(‘/persons/’.$person.’/phone’); my $age=$config->getElement(‘/persons/’.$person.’/age’); print CONFIG “name: $i – age: $age – phone: $phone\n”; }
Hierarchical Configurations (IV) • Note that there is no limit in the nesting of resources (lists of lists are possible as well as lists of lists of lists) • There are some examples (eg. demo NVA API component) • However it is complex using the mkxprof language. Release 3 developments will include integration with the ‘pan’ HLDL language.
Some tips • Avoiddumping configuration files literally into the database @configlines configline_$ configlines 01 02 03 04 05 … configline_01 FARM=MOOH_BAR configline_02 MILK_NODE=COW_001 ... • This leads to some problems, eg. when you overwrite values for host specific values • How do you know that configline_324 is still the line you wanted to change? • Rather use a template configuration file shipped with the component RPM • Substitute relevant entries in the template cf file • Use the built-in template processor for this (see next slide). • Keep explicit configuration information in the LCFG config files.
Template processor • A template substitution processor allows for fast generation of config files • Special marked entries allow to substitute specific entries by LCFGng resources. • Example template file for resources in red: ## Myconfig configuration file# # directory where database management files are storeddatabaseDirectory = <%databaseDirectory%># directory where temporary files are storedtmpDataDirectory = <%tmpDataDirectory%># directory where lock files are storedlockDirectory = <%lockDirectory%> • The template processor is called using LCFG::Template::Substitute ( ‘/mypath/templatefile', ‘/mypath/myconfigfile', $fake, $res );
Example (I) Edg-lcfg-syslog – configures /etc/syslog.conf .def file: @additions add_$ Additions add_$ Resources defined on server: syslog.additions monitoring kernel syslog.add_monitoring local3.* |/var/obj/tmp/monitor.fifo syslog.add_kernel kern.* /var/log/kernel.log
Example (II) Component: Configure() method. First part: template generation sub Configure($$@) { my ($self,$res,@args)=@_; my $config=LCFG::Config->new($res); my $syslogconf='/etc/syslog.conf'; my $status = LCFG::Template::Substitute ( '/usr/lib/lcfg/conf/syslog/template', '/var/obj/conf/syslog/config', 0, $res ); unless (defined($status)) { $self->LogMessage($@); $self->Fail( "failed to create config file (see logfile)"); }
Example (III) Component: Configure() method. Second part: add missing resources # extra values from 'additions', using NVA API my $additions=$config->getElement('/additions'); my @add_array=(); while ($additions->isNextElement()) { my $add=$additions->getNextElement(); my $add_el=$config->getElement('/additions/'.$add.'/add'); push(@add_array,$add_el->getValue()); } if (scalar (@add_array)) { open (CFG, '>>/var/obj/conf/syslog/config') || $self->Fail('cannot open config file (see logfile)'); print CFG join("\n",@add_array)."\n"; close (CFG) || $self->Fail('cannot close config file (see logfile)'); }
Example (IV) Component: Configure() method. Third part: copy config file, restart service # copy over to definitive location if files are different if (system("/usr/bin/cmp -s $syslogconf /var/obj/conf/syslog/config")){ $self->LogMessage("updating config file"); system('cp -f '.$syslogconf.' '.$syslogconf.'.old'); system('cp -f /var/obj/conf/syslog/config '.$syslogconf) && $self->Fail("copying template to $syslogconf: ". $?); # restart service if (system('/sbin/service syslog restart')) { $self->Fail('init.d syslog restart failed: '. $?); } } return 1; #OK }
Packaging components • In order to generate components in RPM, SRPM, and tar format, the component has to be packaged according to some guidelines. • Read the COMPONENTS-HOWTO for details and links • If you want to test/develop/package your components without CVS access, you should copy the following from fabric_mgt/edg-lcfg: • Makefile • edg-lcfg-config directory • Create a directory below the makefile, called edg-lcfg-<name> • Populate it with the following files (take eg. edg-lcfg-syslog as template) • CHANGES, ChangeLog, LICENSE, MAINTAINER, Makefile, README, README.BUILD, config.mk, specfile, <name>.cin, <name>.def.cin, <name>.pod.cin • Use the make ‘devpack’ and ‘devrpm’ targets for generating the tar and RPM packages, respectively. • Once your package is ready, contact WP4 for getting it added to CVS.
Documentation and links • LCFGng ‘out of the box’: http://www.lcfg.org • EDG components and extensions: Check on the EDG CVS repository, http://datagrid.in2p3.fr -> fabric_mgt/edg-lcfg • EDG configuration access API (NVA API v1.0): • http://cern.ch/hep-proj-grid-fabric-config/documents/nva • edg-lcfg-nvaapi library module at the EDG CVS repository • Documentation (HOW-TO): • http://datagrid.in2p3.fr/cgi-bin/cvsweb.cgi/fabric_mgt/edg-lcfg/COMPONENTS-HOWTO • WP4-install homepage: http://cern.ch/wp4-install