]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/scripts/dvd-simulator.in
Backport from Bacula Enterprise
[bacula/bacula] / bacula / scripts / dvd-simulator.in
index a023ee5d5846ca432af96e8ce03498eaefbe3894..a3033f0255f5ace09f885981081a6872cb7c26a1 100644 (file)
@@ -1,7 +1,22 @@
 #!@PYTHON@
 #
-# Copyright (C) 2000-2015, Kern Sibbald
-# License: BSD 2-Clause
+#   Bacula(R) - The Network Backup Solution
+#
+#   Copyright (C) 2000-2015 Kern Sibbald
+#   Copyright (C) 2000-2014 Free Software Foundation Europe e.V.
+#
+#   The original author of Bacula is Kern Sibbald, with contributions
+#   from many others, a complete list can be found in the file AUTHORS.
+#
+#   You may use this file and others of this release according to the
+#   license defined in the LICENSE file, which includes the Affero General
+#   Public License, v3.0 ("AGPLv3") and some additional permissions and
+#   terms pursuant to its AGPLv3 Section 7.
+#
+#   This notice must be preserved when any source code is 
+#   conveyed and/or propagated.
+#
+#   Bacula(R) is a registered trademark of Kern Sibbald.
 #
 #  Modified version of dvd-handler used to simulate reading/writing
 #    to a DVD but using disk storage. This is a pretty crude implementation
 #  operations used by Bacula:
 #
 #   free  (no arguments)
-#            Scan the device and report the available space.
+#             Scan the device and report the available space.
 #
 #   write  op filename
-#             Write a part file to disk.
-#             This operation needs two additional arguments.
-#             The first (op) indicates to
-#                 0 -- append
-#                 1 -- first write to a blank disk
-#                 2 -- blank or truncate a disk
+#              Write a part file to disk.
+#              This operation needs two additional arguments.
+#              The first (op) indicates to
+#                  0 -- append
+#                  1 -- first write to a blank disk
+#                  2 -- blank or truncate a disk
 #
-#              The second is the filename to write
+#               The second is the filename to write
 #
 #   operations available but not used by Bacula:
 #
 #   test      Scan the device and report the information found.
-#             This operation needs no further arguments.
+#              This operation needs no further arguments.
 #   prepare   Prepare a DVD+/-RW for being used by Bacula.
-#             Note: This is only useful if you already have some
-#             non-Bacula data on a medium, and you want to use
-#             it with Bacula. Don't run this on blank media, it
-#             is useless.
+#              Note: This is only useful if you already have some
+#              non-Bacula data on a medium, and you want to use
+#              it with Bacula. Don't run this on blank media, it
+#              is useless.
 #
 #
 # in case of operation ``free'' returns:
@@ -77,23 +92,23 @@ class disk:
 # dvd-writepart doesn't not always need to know the free space).
 #
 # The following methods are implemented:
-# __init__      we need that...
-# __repr__      this seems to be a good idea to have.
-#               Quite minimalistic implementation, though.
-# __str__       For casts to string. Return the current disk information
-# is_empty      Returns TRUE if the disk is empty, blank... this needs more
-#               work, especially concerning non-RW media and blank vs. no
-#               filesystem considerations. Here, we should also look for
-#               other filesystems - probably we don't want to silently
-#               overwrite UDF or ext2 or anything not mentioned in fstab...
-#               (NB: I don't think it is a problem)
-# free          Returns the available free space.
-# write         Writes one part file to disk, either starting a new file
-#               system on disk, or appending to it.
-#               This method should also prepare a blank disk so that a
-#               certain part of the disk is used to allow detection of a
-#               used disk by all / more disk drives.
-# blank         Blank the device
+# __init__       we need that...
+# __repr__       this seems to be a good idea to have.
+#                Quite minimalistic implementation, though.
+# __str__        For casts to string. Return the current disk information
+# is_empty       Returns TRUE if the disk is empty, blank... this needs more
+#                work, especially concerning non-RW media and blank vs. no
+#                filesystem considerations. Here, we should also look for
+#                other filesystems - probably we don't want to silently
+#                overwrite UDF or ext2 or anything not mentioned in fstab...
+#                (NB: I don't think it is a problem)
+# free           Returns the available free space.
+# write          Writes one part file to disk, either starting a new file
+#                system on disk, or appending to it.
+#                This method should also prepare a blank disk so that a
+#                certain part of the disk is used to allow detection of a
+#                used disk by all / more disk drives.
+# blank          Blank the device
 #
 ###############################################################################
    def __init__(self, devicename):
@@ -113,10 +128,10 @@ class disk:
       self.growcmd += " -quiet"
 
       if self.is4gbsupported():
-        self.growcmd += " -use-the-force-luke=4gms"
+         self.growcmd += " -use-the-force-luke=4gms"
 
       self.growparams = " -A 'Bacula Data' -input-charset=default -iso-level 3 -pad " + \
-                       "-p 'dvd-handler / growisofs' -sysid 'BACULADATA' -R"
+                        "-p 'dvd-handler / growisofs' -sysid 'BACULADATA' -R"
 
       return
 
@@ -125,9 +140,9 @@ class disk:
 
    def __str__(self):
       if not self.freespace_collected:
-        self.collect_freespace();
+         self.collect_freespace();
       if not self.mediumtype_collected:
-        self.collect_mediumtype();
+         self.collect_mediumtype();
       
       self.me  = "Class disk, initialized with device '" + self.device + "'\n"
       self.me += "type = '" + self.disktype + "' mode='" + self.diskmode + "' status = '" + self.diskstatus + "'\n"
@@ -141,18 +156,18 @@ class disk:
       processi = popen2.Popen4("uname -s -r")
       status = processi.wait()
       if not os.WIFEXITED(status):
-        return 1
+         return 1
       if os.WEXITSTATUS(status) != 0:
-        return 1
+         return 1
       strres = processi.fromchild.readline()[0:-1]
       version = re.search(r"Linux (\d+)\.(\d+)\.(\d+)", strres)
       if not version: # Non-Linux: allow
-        return 1
+         return 1
       
       if (int(version.group(1)) > 2) or (int(version.group(2)) > 6) or ((int(version.group(1)) == 2) and (int(version.group(2)) == 6) and (int(version.group(3)) >= 8)):
-        return 1
+         return 1
       else:
-        return 0
+         return 0
 
    def collect_freespace(self): # Collects current free space
       self.next_session = 0
@@ -160,19 +175,19 @@ class disk:
       self.freespace_collected = 1
 
       cmd = "du -sb " + self.device
-      processi = popen2.Popen4(cmd)       
+      processi = popen2.Popen4(cmd)        
       status = processi.wait()
       if not os.WIFEXITED(status):
-        return 1;
+         return 1;
       if os.WEXITSTATUS(status) != 0:
-        return 1;
+         return 1;
       result = processi.fromchild.read()
       
       used = re.search(r"(\d+)\s", result, re.MULTILINE)
 
       self.capacity = self.maxcapacity - long(used.group(1))
       if self.capacity < 0:
-        self.capacity = 0
+         self.capacity = 0
 
       return 0
    
@@ -182,10 +197,10 @@ class disk:
       processi = popen2.Popen4(cmd)
       status = processi.wait()
       if not os.WIFEXITED(status):
-        raise DVDError(0, self.dvdrwmediainfo + " process did not exit correctly.")
+         raise DVDError(0, self.dvdrwmediainfo + " process did not exit correctly.")
       if os.WEXITSTATUS(status) != 0:
-        raise DVDError(0, "Cannot get media info from " + self.dvdrwmediainfo)
-        return
+         raise DVDError(0, "Cannot get media info from " + self.dvdrwmediainfo)
+         return
       result = processi.fromchild.read()
       
       hardware = re.search(r"INQUIRY:\s+(.*)\n", result, re.MULTILINE)
@@ -194,23 +209,23 @@ class disk:
       status = re.search(r"\sDisc status:\s+(.*)\n", result, re.MULTILINE)
       
       if hardware:
-        self.hardwaredevice = hardware.group(1)
+         self.hardwaredevice = hardware.group(1)
       
       if mediatype:
-        self.disktype = mediatype.group(2)
+         self.disktype = mediatype.group(2)
       else:
-        raise DVDError(0, "Media type not found in " + self.dvdrwmediainfo + " output")
+         raise DVDError(0, "Media type not found in " + self.dvdrwmediainfo + " output")
       
       if self.disktype == "DVD-RW":
-        if mediamode:
-           self.diskmode = mediamode.group(1)
-        else:
-           raise DVDError(0, "Media mode not found for DVD-RW in " + self.dvdrwmediainfo + " output")
+         if mediamode:
+            self.diskmode = mediamode.group(1)
+         else:
+            raise DVDError(0, "Media mode not found for DVD-RW in " + self.dvdrwmediainfo + " output")
       
       if status:
-        self.diskstatus = status.group(1)
+         self.diskstatus = status.group(1)
       else:
-        raise DVDError(0, "Disc status not found in " + self.dvdrwmediainfo + " output")
+         raise DVDError(0, "Disc status not found in " + self.dvdrwmediainfo + " output")
 
       
       self.mediumtype_collected = 1
@@ -218,84 +233,84 @@ class disk:
 
    def is_empty(self):
       if not self.freespace_collected:
-        self.collect_freespace();
+         self.collect_freespace();
       
       return 0 == self.next_session
 
    def is_RW(self):
       if not self.mediumtype_collected:
-        self.collect_mediumtype();
+         self.collect_mediumtype();
       return "DVD-RW" == self.disktype or "DVD+RW" == self.disktype or "DVD-RAM" == self.disktype
 
    def is_plus_RW(self):
       if not self.mediumtype_collected:
-        self.collect_mediumtype();
+         self.collect_mediumtype();
       return "DVD+RW" == self.disktype
 
    def is_minus_RW(self):
       if not self.mediumtype_collected:
-        self.collect_mediumtype();
+         self.collect_mediumtype();
       return "DVD-RW" == self.disktype
       
    def is_restricted_overwrite(self):
       if not self.mediumtype_collected:
-        self.collect_mediumtype();
+         self.collect_mediumtype();
       return self.diskmode == "Restricted Overwrite"
 
    def is_blank(self):
       if not self.mediumtype_collected:
-        self.collect_mediumtype();
+         self.collect_mediumtype();
       
       return self.diskstatus == "blank"
 
    def free(self):
       if not self.freespace_collected:
-        self.collect_freespace();
+         self.collect_freespace();
       
       fr = self.capacity-self.next_session-self.margin
       if fr < 0:
-        return 0
+         return 0
       else:
-        return fr
+         return fr
 
    def term_handler(self, signum, frame):
       print 'dvd-handler: Signal term_handler called with signal', signum
       if self.pid != 0:
-        print "dvd-handler: Sending SIGTERM to pid", self.pid
-        os.kill(self.pid, signal.SIGTERM)
-        time.sleep(10)
-        print "dvd-handler: Sending SIGKILL to pid", self.pid
-        os.kill(self.pid, signal.SIGKILL)
-        sys.exit(1)
+         print "dvd-handler: Sending SIGTERM to pid", self.pid
+         os.kill(self.pid, signal.SIGTERM)
+         time.sleep(10)
+         print "dvd-handler: Sending SIGKILL to pid", self.pid
+         os.kill(self.pid, signal.SIGKILL)
+         sys.exit(1)
 
    def write(self, newvol, partfile):
       if newvol:
-        print "Newvol", newvol
-        print "Zap everything ..."
-        os.system("rm -f "+self.device+"/*")
+         print "Newvol", newvol
+         print "Zap everything ..."
+         os.system("rm -f "+self.device+"/*")
       print "cp", partfile, self.device
       shutil.copy(partfile,self.device)
 
    def prepare(self):
       if not self.is_RW():
-        raise DVDError(0, "I won't prepare a non-rewritable medium")
+         raise DVDError(0, "I won't prepare a non-rewritable medium")
       
       # Blank DVD+RW when there is no data on it
       if self.is_plus_RW() and self.is_blank():
-        print "DVD+RW looks brand-new, blank it to fix some DVD-writers bugs."
-        self.blank()
-        return # It has been completely blanked: Medium is ready to be used by Bacula
+         print "DVD+RW looks brand-new, blank it to fix some DVD-writers bugs."
+         self.blank()
+         return # It has been completely blanked: Medium is ready to be used by Bacula
       
       if self.is_minus_RW() and (not self.is_restricted_overwrite()):
-        print "DVD-RW is in " + self.diskmode + " mode, reformating it to Restricted Overwrite"
-        self.reformat_minus_RW()
-        return # Reformated: Medium is ready to be used by Bacula
+         print "DVD-RW is in " + self.diskmode + " mode, reformating it to Restricted Overwrite"
+         self.reformat_minus_RW()
+         return # Reformated: Medium is ready to be used by Bacula
       
       # TODO: Check if /dev/fd/0 and /dev/zero exists, otherwise, run self.blank()
       if not os.path.exists("/dev/fd/0") or not os.path.exists("/dev/zero"):
-        print "/dev/fd/0 or /dev/zero doesn't exist, blank the medium completely."
-        self.blank()
-        return
+         print "/dev/fd/0 or /dev/zero doesn't exist, blank the medium completely."
+         self.blank()
+         return
       
       cmd = self.dd + " if=/dev/zero bs=1024 count=512 | " + self.growcmd + " -Z " + self.device + "=/dev/fd/0"
       print "Running " + cmd
@@ -304,17 +319,17 @@ class disk:
       self.pid = proc.pid
       status = proc.poll() 
       while status == -1:
-        line = proc.fromchild.readline()
-        while len(line) > 0:
-           print line,
-           line = proc.fromchild.readline()
-        time.sleep(1)
-        status = proc.poll()
+         line = proc.fromchild.readline()
+         while len(line) > 0:
+            print line,
+            line = proc.fromchild.readline()
+         time.sleep(1)
+         status = proc.poll()
       self.pid = 0
       print
       signal.signal(signal.SIGTERM, oldsig)
       if os.WEXITSTATUS(status) != 0:
-        raise DVDError(os.WEXITSTATUS(status), cmd + " exited with status " + str(os.WEXITSTATUS(status)) + ", signal/status " + str(status))
+         raise DVDError(os.WEXITSTATUS(status), cmd + " exited with status " + str(os.WEXITSTATUS(status)) + ", signal/status " + str(status))
 
    def blank(self):
       cmd = self.growcmd + " -Z " + self.device + "=/dev/zero"
@@ -324,17 +339,17 @@ class disk:
       self.pid = proc.pid
       status = proc.poll()
       while status == -1:
-        line = proc.fromchild.readline()
-        while len(line) > 0:
-           print line,
-           line = proc.fromchild.readline()
-        time.sleep(1)
-        status = proc.poll()
+         line = proc.fromchild.readline()
+         while len(line) > 0:
+            print line,
+            line = proc.fromchild.readline()
+         time.sleep(1)
+         status = proc.poll()
       self.pid = 0
       print
       signal.signal(signal.SIGTERM, oldsig)
       if os.WEXITSTATUS(status) != 0:
-        raise DVDError(os.WEXITSTATUS(status), cmd + " exited with status " + str(os.WEXITSTATUS(status)) + ", signal/status " + str(status))
+         raise DVDError(os.WEXITSTATUS(status), cmd + " exited with status " + str(os.WEXITSTATUS(status)) + ", signal/status " + str(status))
 
    def reformat_minus_RW(self):
       cmd = self.dvdrwformat + " -force " + self.device
@@ -344,17 +359,17 @@ class disk:
       self.pid = proc.pid
       status = proc.poll()
       while status == -1:
-        line = proc.fromchild.readline()
-        while len(line) > 0:
-           print line,
-           line = proc.fromchild.readline()
-        time.sleep(1)
-        status = proc.poll()
+         line = proc.fromchild.readline()
+         while len(line) > 0:
+            print line,
+            line = proc.fromchild.readline()
+         time.sleep(1)
+         status = proc.poll()
       self.pid = 0
       print
       signal.signal(signal.SIGTERM, oldsig)
       if os.WEXITSTATUS(status) != 0:
-        raise DVDError(os.WEXITSTATUS(status), cmd + " exited with status " + str(os.WEXITSTATUS(status)) + ", signal/status " + str(status))
+         raise DVDError(os.WEXITSTATUS(status), cmd + " exited with status " + str(os.WEXITSTATUS(status)) + ", signal/status " + str(status))
 
 # class disk ends here.
 
@@ -363,7 +378,7 @@ class DVDError(Exception):
       self.errno = errno
       self.value = value
       if self.value[-1] == '\n':
-        self.value = self.value[0:-1]
+         self.value = self.value[0:-1]
    def __str__(self):
       return str(self.value) + " || errno = " + str(self.errno) + " (" + os.strerror(self.errno & 0x7F) + ")"
 
@@ -380,19 +395,19 @@ dvd-handler DEVICE blank
 where DEVICE is a device name like /dev/sr0 or /dev/dvd.
 
 Operations:
-test     Scan the device and report the information found.
-          This operation needs no further arguments.
-free     Scan the device and report the available space.
-write    Write a part file to disk.
-          This operation needs two additional arguments.
-          The first indicates to append (0), restart the
-          disk (1) or restart existing disk (2). The second
-          is the file to write.
+test      Scan the device and report the information found.
+           This operation needs no further arguments.
+free      Scan the device and report the available space.
+write     Write a part file to disk.
+           This operation needs two additional arguments.
+           The first indicates to append (0), restart the
+           disk (1) or restart existing disk (2). The second
+           is the file to write.
 prepare   Prepare a DVD+/-RW for being used by Bacula.
-          Note: This is only useful if you already have some
-          non-Bacula data on a medium, and you want to use
-          it with Bacula. Don't run this on blank media, it
-          is useless.
+           Note: This is only useful if you already have some
+           non-Bacula data on a medium, and you want to use
+           it with Bacula. Don't run this on blank media, it
+           is useless.
 """
    sys.exit(1)
 
@@ -404,16 +419,16 @@ dvd = disk(sys.argv[1])
 if "free" == sys.argv[2]:
    if len(sys.argv) == 3:
       try:
-        free = dvd.free()
+         free = dvd.free()
       except DVDError, e:
-        if e.errno != 0:
-           print -e.errno
-        else:
-           print errno.EPIPE
-        print str(e)
+         if e.errno != 0:
+            print -e.errno
+         else:
+            print errno.EPIPE
+         print str(e)
       else:
-        print free
-        print "No Error reported."
+         print free
+         print "No Error reported."
    else:
       print "Wrong number of arguments for free operation. Wanted 3 got", len(sys.argv)
       print sys.argv[1], sys.argv[2], sys.argv[3]
@@ -421,15 +436,15 @@ if "free" == sys.argv[2]:
 elif "prepare" == sys.argv[2]:
    if len(sys.argv) == 3:
       try:
-        dvd.prepare()
+         dvd.prepare()
       except DVDError, e:
-        print "Error while preparing medium: ", str(e)
-        if e.errno != 0:
-           sys.exit(e.errno & 0x7F)
-        else:
-           sys.exit(errno.EPIPE)
+         print "Error while preparing medium: ", str(e)
+         if e.errno != 0:
+            sys.exit(e.errno & 0x7F)
+         else:
+            sys.exit(errno.EPIPE)
       else:
-        print "Medium prepared successfully."
+         print "Medium prepared successfully."
    else:
       print "Wrong number of arguments for prepare operation."
       usage()
@@ -443,15 +458,15 @@ elif "test" == sys.argv[2]:
 elif "write" == sys.argv[2]:
    if len(sys.argv) == 5:
       try:
-        dvd.write(long(sys.argv[3]), sys.argv[4])
+         dvd.write(long(sys.argv[3]), sys.argv[4])
       except DVDError, e:
-        print "Error while writing part file: ", str(e)
-        if e.errno != 0:
-           sys.exit(e.errno & 0x7F)
-        else:
-           sys.exit(errno.EPIPE)
+         print "Error while writing part file: ", str(e)
+         if e.errno != 0:
+            sys.exit(e.errno & 0x7F)
+         else:
+            sys.exit(errno.EPIPE)
       else:
-        print "Part file " + sys.argv[4] + " successfully written to disk."
+         print "Part file " + sys.argv[4] + " successfully written to disk."
    else:
       print "Wrong number of arguments for write operation."
       usage()