help-cfengine
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: providing custom actions


From: Phil D'Amore
Subject: Re: providing custom actions
Date: Sat, 30 Oct 2004 20:19:18 -0400
User-agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.3) Gecko/20030314

I'm not sure how it would fit in to all of the dpkg manipulation you speak of, but I have been sitting on a patch for 2.1.10-ish that adds an action= argument to packages: actions. Right now it supports an install action pretty fully. I added the framework for a remove action, but have not really implemented it yet, because the nuances of dealing with deps on a package remove operation can be more complex and order sensitive.

I've been sitting on it because I've been having some difficulty getting the base docs to build, and therefore having trouble testing my docs definitions for it.

Given some of the things threads I've seen on this list, it seems time to throw this over the wall for coment, so here it is. The way this works is pretty simple:

Any package action that does not evaluate to being equal to what is installed on the machine, *and* has the action=install argument added to it gets added to a list. After all packages: actions are executed, the packages added to this second list are installed, all at once. The command used for this is specified by either the RPMInstallCommand or DPKGInstallCommand variable. You can see in the code that this is pretty pagkage manager agnostic. If someone adds a Solaris capability to this later it should be easy to integrate it.

You set the variable as follows:

control:
   DefaultPkgMgr = ( rpm )
   RPMInstallCommand = ( "/usr/sbin/up2date %s --force" )

The %s of course is replaced by the list of packages.  Then in packages:

stat define=define elsedefine=elsedefine action=install

If you don't specify action=install, then the action works as before. Like I said, there is framework to support action=remove, but no real code behind it. The way I added the hooks should be obvious to anyone who ever looks at cfengine code.

This modification makes a package list per package manager. So you could conceivable mix any number of supported package managers with the pkgmgr= arg on each action, and the needed packages for each package manager will be installed with the correct command.

Lemme know if this helps anyone, and I may be motivated to try to find a machine to build/test the docs, and finish modifying them :). The nice thing about this patch is that now that the work has been done to add the action= arg to the action, it should be simple to add arbitrary new stuff :).

martin f krafft wrote:

also sprach Mark Burgess <Mark.Burgess@iu.hio.no> [2004.10.30.1704 +0200]:
It would make sense to do this through the packages action.

Providing a deb extension would be no problem. However, from what
I can tell, the packages section merely sets additional classes
based on the set of installed packages.

I would like to provide complete dpkg manipulation capabilities.

Would this have to go into the source code? In that case, I am going
to try to include it with the Debian cfengine2 package at first,
unless you are interested in incorporating it upstream.

Am I to assume that cfengine uses Savannah's subversion repository?

------------------------------------------------------------------------

_______________________________________________
Help-cfengine mailing list
Help-cfengine@gnu.org
http://lists.gnu.org/mailman/listinfo/help-cfengine

--
Phil D'Amore                             "Sometimes there is a fine line
Senior System Administrator               between criminally abusive
Red Hat, Inc                              behavior and fun."
Office: 919.754.3700 x44395                 -- Ted the Generic Guy
Pager: 877.383.8795                            (Dilbert 4/19/2003)

diff -Naur cfengine-2.1.10.orig/src/cf.defs.h cfengine-2.1.10/src/cf.defs.h
--- cfengine-2.1.10.orig/src/cf.defs.h  Tue Aug  3 06:09:57 2004
+++ cfengine-2.1.10/src/cf.defs.h       Thu Aug 26 23:04:19 2004
@@ -1148,6 +1148,15 @@
 
 /*******************************************************************/
 
+enum pkgactions /* What to do with a package if it is found/not found */
+    {
+    pkgaction_install,
+    pkgaction_remove,
+    pkgaction_none
+    };
+
+/*******************************************************************/
+
 typedef char flag;
 
 enum socks
@@ -1816,6 +1825,7 @@
    char              *ver;
    enum cmpsense     cmp;
    enum pkgmgrs      pkgmgr;
+   enum pkgactions   action;
    struct Package    *next;
    int ifelapsed;
    int expireafter;
diff -Naur cfengine-2.1.10.orig/src/cf.extern.h cfengine-2.1.10/src/cf.extern.h
--- cfengine-2.1.10.orig/src/cf.extern.h        Mon Aug  2 08:14:04 2004
+++ cfengine-2.1.10/src/cf.extern.h     Thu Aug 26 23:04:19 2004
@@ -456,6 +456,7 @@
 extern char *VRESOURCES[];
 extern char *CMPSENSETEXT[];
 extern char *PKGMGRTEXT[];
+extern char *PKGACTIONTEXT[];
 
 extern int VTIMEOUT;
 extern mode_t UMASK;
@@ -479,6 +480,7 @@
 extern enum cmpsense CMPSENSE;
 extern enum pkgmgrs PKGMGR;
 extern enum pkgmgrs DEFAULTPKGMGR;
+extern enum pkgactions PKGACTION;
 
 extern unsigned short PORTNUMBER;
 
diff -Naur cfengine-2.1.10.orig/src/do.c cfengine-2.1.10/src/do.c
--- cfengine-2.1.10.orig/src/do.c       Sun Aug 15 01:38:39 2004
+++ cfengine-2.1.10/src/do.c    Thu Aug 26 23:04:19 2004
@@ -2680,6 +2680,10 @@
 
 { struct Package *ptr;
   int match = 0;
+  int i;
+  /* pkgmgr_none will always be the highest number in the enum so set
+     the array size with that */
+  char *package_install_list[pkgmgr_none] = { NULL };
 
 for (ptr = VPKG; ptr != NULL; ptr=ptr->next)
    {
@@ -2719,6 +2723,38 @@
          CfLog(cferror,OUTPUT,"");
          break;
      }
+
+   /* Handle install/remove logic now. */
+   if (match)
+     {
+     if (ptr->action == pkgaction_remove)
+       {
+       match = match;
+       }
+     }
+   else
+     {
+     if (ptr->action == pkgaction_install)
+       {
+         /* Initial allocation of memory if we have not yet allocated any */
+         if(package_install_list[ptr->pkgmgr] == NULL)
+         {
+         package_install_list[ptr->pkgmgr] = malloc(CF_BUFSIZE);
+         ((char **)package_install_list[ptr->pkgmgr])[0] = NULL;
+         }
+
+         /* Make sure we don't overflow the buffer */
+         if(strlen(ptr->name) >
+           (CF_BUFSIZE - strlen(package_install_list[ptr->pkgmgr])))
+         {
+            Verbose("Package list exceeds CF_BUFSIZE.  Skipping %s", 
ptr->name);
+         }
+
+         /* Finally add the name to the list. */
+         strcat(package_install_list[ptr->pkgmgr], ptr->name);
+         strcat(package_install_list[ptr->pkgmgr], " ");
+       }
+     }
    
    if (match)
       {
@@ -2733,6 +2769,19 @@
    ReleaseCurrentLock();
    }
 
+/* Run through the package managers, and execute the package install
+ * for each of them... */
+for(i=0; i < pkgmgr_none; i++)
+{
+    if(package_install_list[i] != NULL)
+    {
+        Verbose("Package install list for %s is: %s\n", PKGMGRTEXT[i],
+                    package_install_list[i]);
+        InstallPackage(package_install_list[i], i);
+        free(package_install_list[i]);
+    }
+}
+
 }
 
 /*******************************************************************/
diff -Naur cfengine-2.1.10.orig/src/globals.c cfengine-2.1.10/src/globals.c
--- cfengine-2.1.10.orig/src/globals.c  Mon Aug  2 08:06:01 2004
+++ cfengine-2.1.10/src/globals.c       Thu Aug 26 23:04:19 2004
@@ -639,6 +639,15 @@
       NULL
       };
 
+  /*********************************************************************/
+  /* The names of the possible package-related actions */
+  PRIVATE char *PKGACTIONTEXT[] =
+      {
+      "install",
+      "remove",
+      NULL
+      };
+
 /*******************************************************************/
 /*                                                                 */
 /* parse object : variables belonging to the Parse object          */
@@ -791,6 +800,7 @@
   PRIVATE enum cmpsense CMPSENSE = cmpsense_eq; /* Comparison for packages: */
   PRIVATE enum pkgmgrs PKGMGR = pkgmgr_none;  /* Which package mgr to query */
   PRIVATE enum pkgmgrs DEFAULTPKGMGR = pkgmgr_none;
+  PRIVATE enum pkgactions PKGACTION = pkgaction_none;
 
   PRIVATE flag ACTION_IS_LINK = false;
   PRIVATE flag ACTION_IS_LINKCHILDREN = false;
diff -Naur cfengine-2.1.10.orig/src/install.c cfengine-2.1.10/src/install.c
--- cfengine-2.1.10.orig/src/install.c  Wed Aug 11 16:50:46 2004
+++ cfengine-2.1.10/src/install.c       Thu Aug 26 23:04:19 2004
@@ -1342,7 +1342,9 @@
                    break;
    case cfexpaft:  HandleIntSwitch("expireafter",value,&PEXPIREAFTER,0,999999);
                    break;
-
+   case cfaction:
+                   PKGACTION = (enum pkgactions) GetPkgAction(value);
+                   break;
    default:        yyerror("Illegal packages attribute");
    }
 }
@@ -2648,7 +2650,7 @@
        break;
        
    case packages:
-       InstallPackagesItem(CURRENTOBJECT,PKGVER,CMPSENSE,PKGMGR);
+       InstallPackagesItem(CURRENTOBJECT,PKGVER,CMPSENSE,PKGMGR,PKGACTION);
        break;
    }
 
@@ -4640,7 +4642,7 @@
 
 /*******************************************************************/
 
-void InstallPackagesItem(char *name,char *ver,enum cmpsense sense,enum pkgmgrs 
mgr)
+void InstallPackagesItem(char *name,char *ver,enum cmpsense sense,enum pkgmgrs 
mgr,enum pkgactions action)
 
 { struct Package *ptr;
   char buffer[CF_EXPANDSIZE];
@@ -4661,8 +4663,8 @@
    return;
    }
 
-Debug1("InstallPackagesItem(%s,%s,%s,%s)\n",
-        name,ver,CMPSENSETEXT[sense],PKGMGRTEXT[mgr]);
+Debug1("InstallPackagesItem(%s,%s,%s,%s,%s)\n",
+        name,ver,CMPSENSETEXT[sense],PKGMGRTEXT[mgr],PKGACTIONTEXT[action]);
 
 if ((ptr = (struct Package *)malloc(sizeof(struct Package))) == NULL)
    {
@@ -4732,6 +4734,7 @@
 ptr->inform = INFORMP;
 ptr->cmp = sense;
 ptr->pkgmgr = mgr;
+ptr->action = action;
 ptr->done = 'n';
 ptr->scope = strdup(CONTEXTID);
 
@@ -4776,6 +4779,23 @@
 }
 
 /*******************************************************************/
+
+int GetPkgAction(char *pkgaction)
+
+{ int i;
+for (i = 0; PKGACTIONTEXT[i] != '\0'; i++)
+   {
+   if (strcmp(pkgaction,PKGACTIONTEXT[i]) == 0)
+      {
+      return i;
+      }
+   }
+
+yyerror("Unknown package action");
+return (int) pkgaction_none;
+}
+
+/*******************************************************************/
 
 void InstallImageItem(char *cf_findertype,char *path,mode_t plus,mode_t 
minus,char *destination,char *action,char *uidnames,char *gidnames,int 
size,char comp,int rec,char type,char lntype,char *server)
 
diff -Naur cfengine-2.1.10.orig/src/package.c cfengine-2.1.10/src/package.c
--- cfengine-2.1.10.orig/src/package.c  Wed Aug 11 17:02:06 2004
+++ cfengine-2.1.10/src/package.c       Thu Aug 26 23:04:19 2004
@@ -264,6 +264,94 @@
 return 0;
 }
 
+int InstallPackage(char *name, enum pkgmgrs pkgmgr)
+{
+    char rawinstcmd[CF_BUFSIZE];
+    /* Make the instcmd twice the normal buffer size since the package list
+       limit is CF_BUFSIZE so this can obviously get larger! */
+    char instcmd[CF_BUFSIZE*2];
+    char line[CF_BUFSIZE];
+    char *percent;
+    char *ptr;
+    FILE *pp;
+
+    /* Determine the command to use for the install. */
+    switch(pkgmgr)
+    {
+        /* RPM */
+        case pkgmgr_rpm:
+        if (!GetMacroValue(CONTEXTID,"RPMInstallCommand"))
+          {
+          Verbose("RPMInstallCommand NOT Set.  Package Installation Not 
Possible!\n");
+          return 0;
+          }
+        strncpy(rawinstcmd, GetMacroValue(CONTEXTID,"RPMInstallCommand"),
+                    CF_BUFSIZE);
+        break;
+
+        /* Debian */
+        case pkgmgr_dpkg:
+        if (!GetMacroValue(CONTEXTID,"DPKGInstallCommand"))
+          {
+          Verbose("DPKGInstallCommand NOT Set.  Package Installation Not 
Possible!\n");
+          return 0;
+          }
+        strncpy(rawinstcmd, GetMacroValue(CONTEXTID,"DPKGInstallCommand"),
+                    CF_BUFSIZE);
+        break;
+
+        /* Default */
+        default:
+        Verbose("InstallPackage(): Unknown package manager %d\n",
+                    pkgmgr);
+        break;
+    }
+
+    /* Common to all pkg managers */
+
+    /* This could probably be a bit more complete, but I don't think
+        that anyone would want to expand the package name more than
+        once in a single command invocation anyhow. */
+    if (percent = strstr(rawinstcmd, "%s"))
+      {
+      *percent = '\0';
+      strncpy(instcmd, rawinstcmd, CF_BUFSIZE*2);
+      ptr = instcmd + strlen(rawinstcmd);
+      *percent = '%';
+      strcat(ptr, name);
+      ptr += strlen(name);
+      percent += 2;
+      strncpy(ptr, percent, (CF_BUFSIZE*2 - (ptr-instcmd)));
+      }
+    else
+      {
+      sprintf(instcmd, "%s %s", rawinstcmd, name);
+      }
+    Verbose("Installing package(s) %s using %s\n", name, instcmd);
+    if ((pp = cfpopen(instcmd, "r")) == NULL)
+      {
+      Verbose("Could not execute package install command\n");
+      /* Return that the package is still not installed */
+      return 0;
+      }
+    while (!feof(pp))
+      {
+      ReadLine(line,CF_BUFSIZE-1,pp);
+      printf("%s:package install: %s\n",VPREFIX,line);
+      }
+    if (cfpclose(pp) != 0)
+      {
+      Verbose("Package install command was not successful\n");
+      return 0;
+      }
+    return 1;
+}
+
+int RemovePackage(char *name, enum pkgmgrs pkgmgr)
+{
+    Verbose("Package removal not yet implemented");
+    return 1;
+}
 
 /*********************************************************************/
 /* Debian */
diff -Naur cfengine-2.1.10.orig/src/parse.c cfengine-2.1.10/src/parse.c
--- cfengine-2.1.10.orig/src/parse.c    Tue Aug 10 18:51:38 2004
+++ cfengine-2.1.10/src/parse.c Thu Aug 26 23:04:19 2004
@@ -1238,6 +1238,7 @@
  VTIMEOUT=0;
 
  PKGMGR = DEFAULTPKGMGR; /* pkgmgr_none */
+ PKGACTION = pkgaction_none;
  CMPSENSE = cmpsense_eq;
  PKGVER[0] = '\0';
 
diff -Naur cfengine-2.1.10.orig/src/prototypes.h 
cfengine-2.1.10/src/prototypes.h
--- cfengine-2.1.10.orig/src/prototypes.h       Tue Aug 10 18:50:43 2004
+++ cfengine-2.1.10/src/prototypes.h    Thu Aug 26 23:04:19 2004
@@ -501,7 +501,7 @@
 void InstallImageItem ARGLIST((char *cf_findertype, char *path, mode_t plus, 
mode_t minus, char *destination, char *action, char *uidnames, char *gidnames, 
int size, char comp, int rec, char type, char lntype, char *server));
 void InstallMethod ARGLIST((char *function, char *file));
 void InstallAuthItem ARGLIST((char *path, char *attribute, struct Auth **list, 
struct Auth **listtop, char *classes));
-void InstallPackagesItem ARGLIST((char *name, char *ver, enum cmpsense sense, 
enum pkgmgrs mgr));
+void InstallPackagesItem ARGLIST((char *name, char *ver, enum cmpsense sense, 
enum pkgmgrs mgr, enum pkgactions action));
 int GetCmpSense ARGLIST((char *sense));
 int GetPkgMgr ARGLIST((char *mgr));
 int GetCommAttribute ARGLIST((char *s));
@@ -853,6 +853,8 @@
 /* package.c */
 int RPMPackageCheck ARGLIST((char *package, char *version, enum cmpsense cmp));
 int DPKGPackageCheck ARGLIST((char *package, char *version, enum cmpsense 
cmp));
+int InstallPackage  ARGLIST((char *name, enum pkgmgrs pkgmgr));
+int RemovePackage  ARGLIST((char *name, enum pkgmgrs pkgmgr));
 
 /* popen.c */
 

reply via email to

[Prev in Thread] Current Thread [Next in Thread]