vos-dump-clone-and-vos-copy-support-20021026
[openafs.git] / src / volser / vos.c
index ce9a163..5eb30eb 100644 (file)
@@ -28,6 +28,15 @@ RCSID("$Header$");
 #include <sys/statfs.h>
 #endif
 #include <errno.h>
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#else
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
+#endif
+
 #include <lock.h>
 #include <afs/stds.h>
 #include <rx/xdr.h>
@@ -62,6 +71,8 @@ struct tqHead {
 };
 
 
+struct hostent *hostutil_GetHostByName(register char *ahost);
+
 #define COMMONPARMS     cmd_Seek(ts, 12);\
 cmd_AddParm(ts, "-cell", CMD_SINGLE, CMD_OPTIONAL, "cell name");\
 cmd_AddParm(ts, "-noauth", CMD_FLAG, CMD_OPTIONAL, "don't authenticate");\
@@ -78,7 +89,6 @@ afs_int32 tserver;
 extern struct ubik_client *cstruct;
 const char *confdir;
 extern struct rx_connection *UV_Bind();
-extern  struct rx_securityClass *rxnull_NewClientSecurityObject();
 extern int UV_SetSecurity();
 extern int UV_SetVolumeInfo();
 extern int vsu_SetCrypt();
@@ -370,7 +380,7 @@ int ReceiveFile(ufd, call, blksize)
     struct rx_call *call;
     long blksize;
 {
-    char *buffer = (char *) 0;
+    char *buffer = NULL;
     afs_int32  bytesread;
     afs_uint32  bytesleft, w;
     afs_int32 error = 0;
@@ -485,6 +495,18 @@ int fast,longlist, disp;
            fprintf(STDOUT,"    MaxQuota %10d K \n",pntr->maxquota);
            fprintf(STDOUT,"    Creation    %s",
                    ctime((time_t *)&pntr->creationDate));
+#ifdef FULL_LISTVOL_SWITCH
+           fprintf(STDOUT,"    Copy        %s",
+                   ctime((time_t *)&pntr->copyDate));
+           if(!pntr->backupDate)
+             fprintf(STDOUT,"    Backup      Never\n");
+           else
+             fprintf(STDOUT,"    Backup      %s",
+                     ctime((time_t *)&pntr->backupDate));
+           if (pntr->accessDate)
+             fprintf(STDOUT,"    Last Access %s",
+                     ctime((time_t *)&pntr->accessDate));
+#endif
            if(pntr->updateDate < pntr->creationDate)
                fprintf(STDOUT,"    Last Update %s",
                        ctime((time_t *)&pntr->creationDate));
@@ -622,6 +644,18 @@ static void XDisplayFormat(a_xInfoP, a_servID, a_partID, a_totalOKP,
                        a_xInfoP->maxquota);
                fprintf(STDOUT, "    Creation    %s",
                        ctime((time_t *)&a_xInfoP->creationDate));
+#ifdef FULL_LISTVOL_SWITCH
+               fprintf(STDOUT,"    Copy        %s",
+                       ctime((time_t *)&a_xInfoP->copyDate));
+               if(!a_xInfoP->backupDate)
+                   fprintf(STDOUT,"    Backup      Never\n");
+               else
+                   fprintf(STDOUT,"    Backup      %s",
+                           ctime((time_t *)&a_xInfoP->backupDate));
+               if (a_xInfoP->accessDate)
+                   fprintf(STDOUT,"    Last Access %s",
+                           ctime((time_t *)&a_xInfoP->accessDate));
+#endif
                if (a_xInfoP->updateDate < a_xInfoP->creationDate)
                    fprintf(STDOUT, "    Last Update %s",
                            ctime((time_t *)&a_xInfoP->creationDate));
@@ -1784,6 +1818,135 @@ register struct cmd_syndesc *as;
 
     return 0;
 }
+
+static CopyVolume(as)
+register struct cmd_syndesc *as;
+{
+    
+    afs_int32 volid, fromserver, toserver, tovolume, frompart, topart,code, err;
+    char fromPartName[10], toPartName[10];
+    struct nvldbentry entry;
+       struct diskPartition partition;         /* for space check */
+       volintInfo *p;
+
+       volid = vsu_GetVolumeID(as->parms[0].items->data, cstruct, &err);
+       if (volid == 0) {
+       if (err) PrintError("", err);
+       else  fprintf(STDERR, "vos: can't find volume ID or name '%s'\n",
+                   as->parms[0].items->data);
+           return ENOENT;
+       }
+       fromserver = GetServer(as->parms[1].items->data);
+       if (fromserver == 0) {
+           fprintf(STDERR,"vos: server '%s' not found in host table\n", as->parms[1].items->data);
+           return ENOENT;
+       }
+
+       toserver = GetServer(as->parms[4].items->data);
+       if (toserver == 0) {
+           fprintf(STDERR,"vos: server '%s' not found in host table\n", as->parms[3].items->data);
+           return ENOENT;
+       }
+
+       tovolume = as->parms[3].items->data;
+    if(!ISNAMEVALID(tovolume)) {
+       fprintf(STDERR,"vos: the name of the root volume %s exceeds the size limit of %d\n",
+               tovolume,VOLSER_OLDMAXVOLNAME - 10);
+       return E2BIG;
+    }
+    if(!VolNameOK(tovolume)){
+       fprintf(STDERR,"Illegal volume name %s, should not end in .readonly or .backup\n",tovolume);
+       return EINVAL;
+    }
+    if(IsNumeric(tovolume)){
+       fprintf(STDERR,"Illegal volume name %s, should not be a number\n",tovolume);
+       return EINVAL;
+    }
+    code = VLDB_GetEntryByName(tovolume, &entry);
+    if(!code) {
+       fprintf(STDERR,"Volume %s already exists\n",tovolume);
+       PrintDiagnostics("copy", code);
+       return EEXIST;
+    }
+
+       frompart = volutil_GetPartitionID(as->parms[2].items->data);
+       if (frompart < 0) {
+           fprintf(STDERR,"vos: could not interpret partition name '%s'\n", as->parms[2].items->data);
+           return EINVAL;
+       }
+       if (!IsPartValid(frompart,fromserver,&code)){/*check for validity of the partition */
+           if(code) PrintError("",code);
+           else fprintf(STDERR,"vos : partition %s does not exist on the server\n",as->parms[2].items->data);
+           return ENOENT;
+       }
+
+       topart = volutil_GetPartitionID(as->parms[5].items->data);
+       if (topart < 0) {
+           fprintf(STDERR,"vos: could not interpret partition name '%s'\n",as->parms[4].items->data);
+           return EINVAL;
+       }
+       if (!IsPartValid(topart,toserver,&code)){/*check for validity of the partition */
+           if(code) PrintError("",code);
+           else fprintf(STDERR,"vos : partition %s does not exist on the server\n",as->parms[4].items->data);
+           return ENOENT;
+       }
+
+       /*
+               check source partition for space to clone volume
+       */
+
+       MapPartIdIntoName(topart,toPartName);
+       MapPartIdIntoName(frompart, fromPartName);
+
+       /*
+               check target partition for space to move volume
+       */
+
+       code=UV_PartitionInfo(toserver,toPartName,&partition);
+       if(code)
+       {
+               fprintf(STDERR,"vos: cannot access partition %s\n",toPartName);
+               exit(1);
+       }
+       if(TESTM)
+               fprintf(STDOUT,"target partition %s free space %d\n",
+                       toPartName,partition.free);
+
+       p=(volintInfo *)0;
+       code=UV_ListOneVolume(fromserver,frompart,volid,&p);
+       if(code)
+       {
+               fprintf(STDERR,"vos:cannot access volume %u\n",volid);
+               free(p);
+               exit(1);
+       }
+
+       if(partition.free<=p->size)
+       {
+               fprintf(STDERR,"vos: no space on target partition %s to copy volume %u\n",
+                       toPartName,volid);
+               free(p);
+               exit(1);
+       }
+       free(p);
+
+       /* successful copy still not guaranteed but shoot for it */
+
+       code = UV_CopyVolume(volid, fromserver, frompart, tovolume, toserver, topart);
+       if (code) {
+           PrintDiagnostics("copy", code);
+           return code;
+       }
+       MapPartIdIntoName(topart,toPartName);
+       MapPartIdIntoName(frompart, fromPartName);
+       fprintf(STDOUT,"Volume %u copied from %s %s to %s on %s %s \n",volid,
+               as->parms[1].items->data,fromPartName,
+               tovolume, as->parms[4].items->data,toPartName);
+
+    return 0;
+}
+
+
 static BackupVolume(as)
 register struct cmd_syndesc *as;
 {
@@ -1942,7 +2105,12 @@ register struct cmd_syndesc *as;
        else{
            strcpy(filename,"");
        }
-       code = UV_DumpVolume(avolid, aserver, apart, fromdate, DumpFunction, filename);
+
+    if (as->parms[5].items) {
+               code = UV_DumpClonedVolume(avolid, aserver, apart, fromdate, DumpFunction, filename);
+       } else {
+               code = UV_DumpVolume(avolid, aserver, apart, fromdate, DumpFunction, filename);
+       }               
        if (code) {
            PrintDiagnostics("dump", code);
            return code;
@@ -2074,7 +2242,7 @@ register struct cmd_syndesc *as;
        else {                    /* volume exists - do we do a full incremental or abort */
            int Oserver, Opart, Otype, vol_elsewhere = 0;
            struct nvldbentry Oentry;
-           char   c, dc;
+           int   c, dc;
 
            if(avolid == 0) {
                avolid = entry.volumeId[voltype];
@@ -2183,9 +2351,10 @@ static AddSite(as)
 register struct cmd_syndesc *as;
 {
    afs_int32 avolid, aserver, apart,code, err;
-   char apartName[10];
+   char apartName[10], avolname[VOLSER_MAXVOLNAME+1];
 
-       avolid = vsu_GetVolumeID(as->parms[2].items->data, cstruct, &err);
+       vsu_ExtractName(avolname, as->parms[2].items->data);;
+       avolid = vsu_GetVolumeID(avolname, cstruct, &err);
        if (avolid == 0) {
            if (err) PrintError("", err);
            else fprintf(STDERR, "vos: can't find volume '%s'\n", as->parms[2].items->data);
@@ -2221,9 +2390,10 @@ register struct cmd_syndesc *as;
 { 
 
     afs_int32 avolid, aserver, apart, code, err;
-    char apartName[10];
+    char apartName[10], avolname[VOLSER_MAXVOLNAME+1];
 
-       avolid = vsu_GetVolumeID(as->parms[2].items->data, cstruct, &err);
+       vsu_ExtractName(avolname, as->parms[2].items->data);
+       avolid = vsu_GetVolumeID(avolname, cstruct, &err);
        if (avolid == 0) {
            if (err) PrintError("", err);
            else fprintf(STDERR, "vos: can't find volume '%s'\n", as->parms[2].items->data);
@@ -3793,33 +3963,26 @@ register struct cmd_syndesc *as;
     return 0;
 }
 
-static ListAddrs(as)
-register struct cmd_syndesc *as;
-
+static void
+print_addrs(const bulkaddrs *addrs, const afsUUID *m_uuid, int nentries, int print, int noresolve)
 {
   afs_int32 vcode;
   afs_int32 i, j;
   struct VLCallBack    unused;
-  afs_int32                nentries, *addrp;
-  bulkaddrs            addrs, m_addrs;
+  afs_int32            *addrp;
+  bulkaddrs            m_addrs;
   ListAddrByAttributes m_attrs;
-  afsUUID              m_uuid;
-  afs_int32                m_unique, m_nentries, *m_addrp;
-  afs_int32                base, index;
+  afs_int32            m_unique, m_nentries, *m_addrp;
+  afs_int32            base, index;
+  char buf[1024];
 
-  /* Get the list of non multihomed fileservers */
-  addrs.bulkaddrs_val = 0;
-  addrs.bulkaddrs_len = 0;
-  vcode = ubik_Call_New(VL_GetAddrs, cstruct, 0,
-                       0, 0, &unused, &nentries, &addrs);
-  if (vcode) {
-     fprintf(STDERR,"vos: could not list the server addresses\n");
-     PrintError("",vcode);
-     return( vcode );
+  if (print) {
+      afsUUID_to_string(m_uuid, buf, sizeof(buf));
+      printf("UUID: %s\n", buf);
   }
 
   /* print out the list of all the server */
-  addrp = (afs_int32 *)addrs.bulkaddrs_val;
+  addrp = (afs_int32 *)addrs->bulkaddrs_val;
   for (i=0; i<nentries; i++, addrp++) {
      /* If it is a multihomed address, then we will need to 
       * get the addresses for this multihomed server from
@@ -3848,7 +4011,12 @@ register struct cmd_syndesc *as;
           m_addrp = (afs_int32 *)m_addrs.bulkaddrs_val;
           for (j=0; j<m_nentries; j++, m_addrp++) {
              *m_addrp = htonl(*m_addrp);       
-             printf("%s ", hostutil_GetNameByINet(*m_addrp));
+             if (noresolve) {
+                 char hoststr[16];
+                 printf("%s ", afs_inet_ntoa_r(*m_addrp,hoststr));
+             } else {
+                 printf("%s ", hostutil_GetNameByINet(*m_addrp));
+             }
           }
           if (j==0) {
              printf("<unknown>\n");
@@ -3863,12 +4031,110 @@ register struct cmd_syndesc *as;
      /* Otherwise, it is a non-multihomed entry and contains
       * the IP address of the server - print it.
       */
-     printf ("%s\n", hostutil_GetNameByINet(htonl(*addrp)));
+     *addrp = htonl(*addrp);   
+     if (noresolve) {
+        char hoststr[16];
+        printf("%s\n", afs_inet_ntoa_r(*addrp,hoststr));
+     } else {
+        printf("%s\n", hostutil_GetNameByINet(*addrp));
+     }
+  }
+
+  if (print) {
+      printf("\n");
   }
+  return;
+}
+
+static ListAddrs(as)
+register struct cmd_syndesc *as;
+{
+  afs_int32 vcode;
+  afs_int32 i, j, noresolve=0, printuuid=0;
+  struct VLCallBack    unused;
+  afs_int32                nentries, *addrp;
+  bulkaddrs            addrs, m_addrs;
+  ListAddrByAttributes m_attrs;
+  afsUUID              m_uuid, askuuid;
+  afs_int32                m_unique, m_nentries, *m_addrp;
+  afs_int32                base, index;
+
+  memset(&m_attrs, 0, sizeof(struct ListAddrByAttributes));
+  m_attrs.Mask = VLADDR_INDEX;
+
+  memset(&m_addrs, 0, sizeof(bulkaddrs));
+  memset(&askuuid, 0, sizeof(afsUUID));
+  if (as->parms[0].items) {
+      /* -uuid */
+      afsUUID_from_string(as->parms[0].items->data, &askuuid);
+      m_attrs.Mask = VLADDR_UUID;
+      m_attrs.uuid = askuuid;
+  }
+  if (as->parms[1].items) {
+      /* -host */
+      struct hostent       *he; 
+      afs_int32 saddr;
+      he = hostutil_GetHostByName((char*)as->parms[1].items->data);
+      if (he == NULL) {
+         fprintf(stderr,
+                 "Can't get host info for '%s'\n",
+                 as->parms[1].items->data);
+         exit(-1);
+      }
+      memcpy(&saddr, he->h_addr, 4);
+      m_attrs.Mask = VLADDR_IPADDR;
+      m_attrs.ipaddr = ntohl(saddr);
+  }
+  if (as->parms[2].items) {
+      noresolve=1;
+  }
+  if (as->parms[3].items) {
+      printuuid=1;
+  }
+
+  m_addrs.bulkaddrs_val = 0;
+  m_addrs.bulkaddrs_len = 0;
 
-  if (addrs.bulkaddrs_val) {
-     free (addrs.bulkaddrs_val);
+  vcode = ubik_Call_New(VL_GetAddrs, cstruct, 0,
+                        0, 0, &m_unique, &nentries, &m_addrs);
+  if (vcode) {
+    fprintf(STDERR,"vos: could not list the server addresses\n");
+    PrintError("",vcode);
+    return( vcode );
   }
+
+  m_nentries            = 0;
+  m_addrs.bulkaddrs_val = 0;
+  m_addrs.bulkaddrs_len = 0;
+  i=1;
+  while (1) {
+      m_attrs.index = i;
+
+      vcode = ubik_Call_New(VL_GetAddrsU, cstruct, 0, &m_attrs, &m_uuid, 
+                       &m_unique, &m_nentries, &m_addrs);
+      if(vcode == VL_NOENT) {
+         i++;
+          nentries++;
+          continue;
+      }
+
+      if (vcode == VL_INDEXERANGE) {
+         break;
+      }
+
+      if (vcode) {
+         fprintf(STDERR,"vos: could not list the server addresses\n");
+         PrintError("",vcode);
+         return( vcode );
+      }
+
+      print_addrs(&m_addrs, &m_uuid, m_nentries, printuuid, noresolve);
+      i++;
+
+      if ((as->parms[1].items)||(as->parms[0].items)||(i>nentries))
+         break;
+  }
+    
   return 0;
 }
 
@@ -3922,7 +4188,7 @@ char *arock; {
     cstruct = (struct ubik_client *)0;
 
     sauth = 0;
-    tcell = (char *) 0;
+    tcell = NULL;
     if (as->parms[12].items)   /* if -cell specified */
        tcell = as->parms[12].items->data;
     if(as->parms[14].items)    /* -serverauth specified */
@@ -3975,7 +4241,7 @@ char **argv; {
 
     confdir = AFSDIR_CLIENT_ETC_DIRPATH;
 
-    cmd_SetBeforeProc(MyBeforeProc,  (char *) 0);
+    cmd_SetBeforeProc(MyBeforeProc,  NULL);
 
     ts = cmd_CreateSyntax("create", CreateVolume, 0, "create a new volume");
     cmd_AddParm(ts, "-server", CMD_SINGLE, 0, "machine name");
@@ -4002,6 +4268,15 @@ char **argv; {
     cmd_AddParm(ts, "-topartition", CMD_SINGLE, 0, "partition name on destination");
     COMMONPARMS;
 
+    ts = cmd_CreateSyntax("copy", CopyVolume, 0, "copy a volume");
+    cmd_AddParm(ts, "-id", CMD_SINGLE, 0, "volume name or ID on source");
+    cmd_AddParm(ts, "-fromserver", CMD_SINGLE, 0, "machine name on source");
+    cmd_AddParm(ts, "-frompartition", CMD_SINGLE, 0, "partition name on source");
+       cmd_AddParm(ts, "-toname", CMD_SINGLE, 0, "volume name on destination");
+    cmd_AddParm(ts, "-toserver", CMD_SINGLE, 0, "machine name on destination");
+    cmd_AddParm(ts, "-topartition", CMD_SINGLE, 0, "partition name on destination");
+    COMMONPARMS;
+
     ts = cmd_CreateSyntax("backup", BackupVolume, 0, "make backup of a volume");
     cmd_AddParm(ts, "-id", CMD_SINGLE, 0, "volume name or ID");
     COMMONPARMS;
@@ -4017,6 +4292,7 @@ char **argv; {
     cmd_AddParm(ts, "-file", CMD_SINGLE, CMD_OPTIONAL, "dump file");
     cmd_AddParm(ts, "-server", CMD_SINGLE, CMD_OPTIONAL, "server");
     cmd_AddParm(ts, "-partition", CMD_SINGLE, CMD_OPTIONAL, "partition");
+    cmd_AddParm(ts, "-clone", CMD_FLAG, CMD_OPTIONAL, "dump a clone of the volume");
     COMMONPARMS;
 
     ts = cmd_CreateSyntax("restore", RestoreVolume, 0, "restore a volume");
@@ -4179,6 +4455,10 @@ char **argv; {
     COMMONPARMS;
 
     ts = cmd_CreateSyntax("listaddrs", ListAddrs, 0, "list the IP address of all file servers registered in the VLDB");
+    cmd_AddParm(ts, "-uuid", CMD_SINGLE, CMD_OPTIONAL, "uuid of server");
+    cmd_AddParm(ts, "-host", CMD_SINGLE, CMD_OPTIONAL, "address of host");
+    cmd_AddParm(ts, "-noresolve", CMD_FLAG, CMD_OPTIONAL, "don't resolve addresses");
+    cmd_AddParm(ts, "-printuuid", CMD_FLAG, CMD_OPTIONAL, "print uuid of hosts");
     COMMONPARMS;
 
     code = cmd_Dispatch(argc, argv);