]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
tests: Make OSD tests compatible with Python 3
authorOleh Prypin <oleh@pryp.in>
Fri, 24 Jun 2016 12:51:55 +0000 (15:51 +0300)
committerOleh Prypin <oleh@pryp.in>
Thu, 21 Jul 2016 15:35:17 +0000 (18:35 +0300)
Signed-off-by: Oleh Prypin <oleh@pryp.in>
src/test/ceph_objectstore_tool.py

index d3f7d488080a566205d5bc2fe5b866d4a567b9a5..60b69f4da736de2db8332663b6d344302281cf9a 100755 (executable)
@@ -1,5 +1,6 @@
 #!/usr/bin/env python
 
+from __future__ import print_function
 from subprocess import call
 try:
     from subprocess import check_output
@@ -23,32 +24,44 @@ except ImportError:
 import filecmp
 import os
 import subprocess
-try:
-    from subprocess import DEVNULL
-except ImportError:
-    subprocess.DEVNULL = open(os.devnull, "w")
-
 import math
 import time
 import sys
 import re
-import string
 import logging
 import json
 import tempfile
+import io
+
+try:
+    from subprocess import DEVNULL
+except ImportError:
+    DEVNULL = open(os.devnull, "wb")
 
 logging.basicConfig(format='%(levelname)s:%(message)s', level=logging.WARNING)
 
 
+if sys.version_info[0] >= 3:
+    def decode(s):
+        return s.decode('utf-8')
+
+    def check_output(*args, **kwargs):
+        return decode(subprocess.check_output(*args, **kwargs))
+else:
+    def decode(s):
+        return s
+
+
+
 def wait_for_health():
-    print "Wait for health_ok...",
+    print("Wait for health_ok...", end="")
     tries = 0
     while call("{path}/ceph health 2> /dev/null | grep -v 'HEALTH_OK\|HEALTH_WARN' > /dev/null".format(path=CEPH_BIN), shell=True) == 0:
         tries += 1
         if tries == 150:
             raise Exception("Time exceeded to go to health")
         time.sleep(1)
-    print "DONE"
+    print("DONE")
 
 
 def get_pool_id(name, nullfd):
@@ -70,7 +83,7 @@ def get_osd_pgs(SUBDIR, ID):
 
 # return a sorted list of unique PGs given a directory
 def get_pgs(DIR, ID):
-    OSDS = [f for f in os.listdir(DIR) if os.path.isdir(os.path.join(DIR, f)) and string.find(f, "osd") == 0]
+    OSDS = [f for f in os.listdir(DIR) if os.path.isdir(os.path.join(DIR, f)) and f.find("osd") == 0]
     PGS = []
     for d in OSDS:
         SUBDIR = os.path.join(DIR, d)
@@ -80,7 +93,7 @@ def get_pgs(DIR, ID):
 
 # return a sorted list of PGS a subset of ALLPGS that contain objects with prefix specified
 def get_objs(ALLPGS, prefix, DIR, ID):
-    OSDS = [f for f in os.listdir(DIR) if os.path.isdir(os.path.join(DIR, f)) and string.find(f, "osd") == 0]
+    OSDS = [f for f in os.listdir(DIR) if os.path.isdir(os.path.join(DIR, f)) and f.find("osd") == 0]
     PGS = []
     for d in OSDS:
         DIRL2 = os.path.join(DIR, d)
@@ -98,7 +111,7 @@ def get_objs(ALLPGS, prefix, DIR, ID):
 
 # return a sorted list of OSDS which have data from a given PG
 def get_osds(PG, DIR):
-    ALLOSDS = [f for f in os.listdir(DIR) if os.path.isdir(os.path.join(DIR, f)) and string.find(f, "osd") == 0]
+    ALLOSDS = [f for f in os.listdir(DIR) if os.path.isdir(os.path.join(DIR, f)) and f.find("osd") == 0]
     OSDS = []
     for d in ALLOSDS:
         DIRL2 = os.path.join(DIR, d)
@@ -126,33 +139,33 @@ def get_lines(filename):
 def cat_file(level, filename):
     if level < logging.getLogger().getEffectiveLevel():
         return
-    print "File: " + filename
+    print("File: " + filename)
     with open(filename, "r") as f:
         while True:
             line = f.readline().rstrip('\n')
             if not line:
                 break
-            print line
-    print "<EOF>"
+            print(line)
+    print("<EOF>")
 
 
 def vstart(new, opt=""):
-    print "vstarting....",
+    print("vstarting....", end="")
     NEW = new and "-n" or ""
     call("MON=1 OSD=4 CEPH_PORT=7400 {path}/src/vstart.sh --short -l {new} -d mon osd {opt} > /dev/null 2>&1".format(new=NEW, opt=opt, path=CEPH_ROOT), shell=True)
-    print "DONE"
+    print("DONE")
 
 
 def test_failure(cmd, errmsg, tty=False):
     if tty:
         try:
-            ttyfd = open("/dev/tty", "rw")
-        except Exception, e:
+            ttyfd = open("/dev/tty", "rwb")
+        except Exception as e:
             logging.info(str(e))
             logging.info("SKIP " + cmd)
             return 0
     TMPFILE = r"/tmp/tmp.{pid}".format(pid=os.getpid())
-    tmpfd = open(TMPFILE, "w")
+    tmpfd = open(TMPFILE, "wb")
 
     logging.debug(cmd)
     if tty:
@@ -183,7 +196,6 @@ def get_nspace(num):
 
 def verify(DATADIR, POOL, NAME_PREFIX, db):
     TMPFILE = r"/tmp/tmp.{pid}".format(pid=os.getpid())
-    nullfd = open(os.devnull, "w")
     ERRORS = 0
     for rawnsfile in [f for f in os.listdir(DATADIR) if f.split('-')[1].find(NAME_PREFIX) == 0]:
         nsfile = rawnsfile.split("__")[0]
@@ -200,7 +212,7 @@ def verify(DATADIR, POOL, NAME_PREFIX, db):
             pass
         cmd = "{path}/rados -p {pool} -N '{nspace}' get {file} {out}".format(pool=POOL, file=file, out=TMPFILE, nspace=nspace, path=CEPH_BIN)
         logging.debug(cmd)
-        call(cmd, shell=True, stdout=nullfd, stderr=nullfd)
+        call(cmd, shell=True, stdout=DEVNULL, stderr=DEVNULL)
         cmd = "diff -q {src} {result}".format(src=path, result=TMPFILE)
         logging.debug(cmd)
         ret = call(cmd, shell=True)
@@ -211,10 +223,10 @@ def verify(DATADIR, POOL, NAME_PREFIX, db):
             os.unlink(TMPFILE)
         except:
             pass
-        for key, val in db[nspace][file]["xattr"].iteritems():
+        for key, val in db[nspace][file]["xattr"].items():
             cmd = "{path}/rados -p {pool} -N '{nspace}' getxattr {name} {key}".format(pool=POOL, name=file, key=key, nspace=nspace, path=CEPH_BIN)
             logging.debug(cmd)
-            getval = check_output(cmd, shell=True, stderr=nullfd)
+            getval = check_output(cmd, shell=True, stderr=DEVNULL)
             logging.debug("getxattr {key} {val}".format(key=key, val=getval))
             if getval != val:
                 logging.error("getxattr of key {key} returned wrong val: {get} instead of {orig}".format(key=key, get=getval, orig=val))
@@ -223,7 +235,7 @@ def verify(DATADIR, POOL, NAME_PREFIX, db):
         hdr = db[nspace][file].get("omapheader", "")
         cmd = "{path}/rados -p {pool} -N '{nspace}' getomapheader {name} {file}".format(pool=POOL, name=file, nspace=nspace, file=TMPFILE, path=CEPH_BIN)
         logging.debug(cmd)
-        ret = call(cmd, shell=True, stderr=nullfd)
+        ret = call(cmd, shell=True, stderr=DEVNULL)
         if ret != 0:
             logging.error("rados getomapheader returned {ret}".format(ret=ret))
             ERRORS += 1
@@ -238,10 +250,10 @@ def verify(DATADIR, POOL, NAME_PREFIX, db):
             if gethdr != hdr:
                 logging.error("getomapheader returned wrong val: {get} instead of {orig}".format(get=gethdr, orig=hdr))
                 ERRORS += 1
-        for key, val in db[nspace][file]["omap"].iteritems():
+        for key, val in db[nspace][file]["omap"].items():
             cmd = "{path}/rados -p {pool} -N '{nspace}' getomapval {name} {key} {file}".format(pool=POOL, name=file, key=key, nspace=nspace, file=TMPFILE, path=CEPH_BIN)
             logging.debug(cmd)
-            ret = call(cmd, shell=True, stderr=nullfd)
+            ret = call(cmd, shell=True, stderr=DEVNULL)
             if ret != 0:
                 logging.error("getomapval returned {ret}".format(ret=ret))
                 ERRORS += 1
@@ -272,7 +284,7 @@ def check_journal(jsondict):
         logging.error("Key 'max_size' not in dump-journal header")
         errors += 1
     else:
-        print "\tJournal max_size = {size}".format(size=jsondict['header']['max_size'])
+        print("\tJournal max_size = {size}".format(size=jsondict['header']['max_size']))
     if 'entries' not in jsondict:
         logging.error("Key 'entries' not in dump-journal output")
         errors += 1
@@ -348,7 +360,7 @@ def test_dump_journal(CFSD_PREFIX, osds):
         # Test --op dump-journal by loading json
         cmd = (CFSD_PREFIX + "--op dump-journal --format json").format(osd=osd)
         logging.debug(cmd)
-        tmpfd = open(TMPFILE, "w")
+        tmpfd = open(TMPFILE, "wb")
         ret = call(cmd, shell=True, stdout=tmpfd)
         if ret != 0:
             logging.error("Bad exit status {ret} from {cmd}".format(ret=ret, cmd=cmd))
@@ -400,7 +412,7 @@ def check_data(DATADIR, TMPFILE, OSDDIR, SPLIT_NAME):
         if clone != "head":
             continue
         path = os.path.join(DATADIR, rawnsfile)
-        tmpfd = open(TMPFILE, "w")
+        tmpfd = open(TMPFILE, "wb")
         cmd = "find {dir} -name '{file}_*_{nspace}_*'".format(dir=OSDDIR, file=file, nspace=nspace)
         logging.debug(cmd)
         ret = call(cmd, shell=True, stdout=tmpfd)
@@ -438,8 +450,8 @@ def set_osd_weight(CFSD_PREFIX, osd_ids, osd_path, weight):
     old_crush_file = tempfile.NamedTemporaryFile(delete=True)
     ret = call("{path}/osdmaptool --export-crush {crush_file} {osdmap_file}".format(osdmap_file=osdmap_file.name,
                                                                           crush_file=old_crush_file.name, path=CEPH_BIN),
-               stdout=subprocess.DEVNULL,
-               stderr=subprocess.DEVNULL,
+               stdout=DEVNULL,
+               stderr=DEVNULL,
                shell=True)
     assert(ret == 0)
 
@@ -448,7 +460,7 @@ def set_osd_weight(CFSD_PREFIX, osd_ids, osd_path, weight):
                                                                                                           crush_file=old_crush_file.name,
                                                                                                           weight=weight,
                                                                                                           new_crush_file=new_crush_file.name, path=CEPH_BIN)
-        ret = call(cmd, stdout=subprocess.DEVNULL, shell=True)
+        ret = call(cmd, stdout=DEVNULL, shell=True)
         assert(ret == 0)
         old_crush_file, new_crush_file = new_crush_file, old_crush_file
 
@@ -458,22 +470,22 @@ def set_osd_weight(CFSD_PREFIX, osd_ids, osd_path, weight):
 
     ret = call("{path}/osdmaptool --import-crush {crush_file} {osdmap_file}".format(osdmap_file=osdmap_file.name,
                                                                                crush_file=new_crush_file.name, path=CEPH_BIN),
-               stdout=subprocess.DEVNULL,
-               stderr=subprocess.DEVNULL,
+               stdout=DEVNULL,
+               stderr=DEVNULL,
                shell=True)
     assert(ret == 0)
 
     # Minimum test of --dry-run by using it, but not checking anything
     cmd = CFSD_PREFIX + "--op set-osdmap --file {osdmap_file} --epoch {epoch} --force --dry-run"
     cmd = cmd.format(osd=osd_path, osdmap_file=osdmap_file.name, epoch=epoch)
-    ret = call(cmd, stdout=subprocess.DEVNULL, shell=True)
+    ret = call(cmd, stdout=DEVNULL, shell=True)
     assert(ret == 0)
 
     # osdmaptool increases the epoch of the changed osdmap, so we need to force the tool
     # to use use a different epoch than the one in osdmap
     cmd = CFSD_PREFIX + "--op set-osdmap --file {osdmap_file} --epoch {epoch} --force"
     cmd = cmd.format(osd=osd_path, osdmap_file=osdmap_file.name, epoch=epoch)
-    ret = call(cmd, stdout=subprocess.DEVNULL, shell=True)
+    ret = call(cmd, stdout=DEVNULL, shell=True)
 
     return ret == 0
 
@@ -481,7 +493,7 @@ def get_osd_weights(CFSD_PREFIX, osd_ids, osd_path):
     osdmap_file = tempfile.NamedTemporaryFile(delete=True)
     cmd = (CFSD_PREFIX + "--op get-osdmap --file {osdmap_file}").format(osd=osd_path,
                                                                         osdmap_file=osdmap_file.name)
-    ret = call(cmd, stdout=subprocess.DEVNULL, shell=True)
+    ret = call(cmd, stdout=DEVNULL, shell=True)
     if ret != 0:
         return None
     # we have to read the weights from the crush map, even we can query the weights using
@@ -490,12 +502,12 @@ def get_osd_weights(CFSD_PREFIX, osd_ids, osd_path):
     crush_file = tempfile.NamedTemporaryFile(delete=True)
     ret = call("{path}/osdmaptool --export-crush {crush_file} {osdmap_file}".format(osdmap_file=osdmap_file.name,
                                                                                crush_file=crush_file.name, path=CEPH_BIN),
-               stdout=subprocess.DEVNULL,
+               stdout=DEVNULL,
                shell=True)
     assert(ret == 0)
     output = check_output("{path}/crushtool --tree -i {crush_file} | tail -n {num_osd}".format(crush_file=crush_file.name,
                                                                                           num_osd=len(osd_ids), path=CEPH_BIN),
-                          stderr=subprocess.DEVNULL,
+                          stderr=DEVNULL,
                           shell=True)
     weights = []
     for line in output.strip().split('\n'):
@@ -506,7 +518,7 @@ def get_osd_weights(CFSD_PREFIX, osd_ids, osd_path):
 
 
 def test_get_set_osdmap(CFSD_PREFIX, osd_ids, osd_paths):
-    print "Testing get-osdmap and set-osdmap"
+    print("Testing get-osdmap and set-osdmap")
     errors = 0
     kill_daemons()
     weight = 1 / math.e           # just some magic number in [0, 1]
@@ -576,11 +588,14 @@ def test_get_set_inc_osdmap(CFSD_PREFIX, osd_path):
 
 
 def main(argv):
-    sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)
+    if sys.version_info[0] < 3:
+        sys.stdout = stdout = os.fdopen(sys.stdout.fileno(), 'wb', 0)
+    else:
+        stdout = sys.stdout.buffer
     if len(argv) > 1 and argv[1] == "debug":
-        nullfd = sys.stdout
+        nullfd = stdout
     else:
-        nullfd = open(os.devnull, "w")
+        nullfd = DEVNULL
 
     call("rm -fr {dir}; mkdir {dir}".format(dir=CEPH_DIR), shell=True)
     os.environ["CEPH_DIR"] = CEPH_DIR
@@ -623,7 +638,7 @@ def main(argv):
     call(cmd, shell=True, stdout=nullfd, stderr=nullfd)
     REPID = get_pool_id(REP_POOL, nullfd)
 
-    print "Created Replicated pool #{repid}".format(repid=REPID)
+    print("Created Replicated pool #{repid}".format(repid=REPID))
 
     cmd = "{path}/ceph osd erasure-code-profile set {prof} ruleset-failure-domain=osd".format(prof=PROFNAME, path=CEPH_BIN)
     logging.debug(cmd)
@@ -636,9 +651,9 @@ def main(argv):
     call(cmd, shell=True, stdout=nullfd, stderr=nullfd)
     ECID = get_pool_id(EC_POOL, nullfd)
 
-    print "Created Erasure coded pool #{ecid}".format(ecid=ECID)
+    print("Created Erasure coded pool #{ecid}".format(ecid=ECID))
 
-    print "Creating {objs} objects in replicated pool".format(objs=(NUM_REP_OBJECTS*NUM_NSPACES))
+    print("Creating {objs} objects in replicated pool".format(objs=(NUM_REP_OBJECTS*NUM_NSPACES)))
     cmd = "mkdir -p {datadir}".format(datadir=DATADIR)
     logging.debug(cmd)
     call(cmd, shell=True)
@@ -762,7 +777,7 @@ def main(argv):
                 logging.critical("Rados put command failed with {ret}".format(ret=ret))
                 return 1
 
-    print "Creating {objs} objects in erasure coded pool".format(objs=(NUM_EC_OBJECTS*NUM_NSPACES))
+    print("Creating {objs} objects in erasure coded pool".format(objs=(NUM_EC_OBJECTS*NUM_NSPACES)))
 
     objects = range(1, NUM_EC_OBJECTS + 1)
     nspaces = range(NUM_NSPACES)
@@ -843,7 +858,7 @@ def main(argv):
     ONEOSD = osds[0]
     logging.debug(ONEOSD)
 
-    print "Test invalid parameters"
+    print("Test invalid parameters")
     # On export can't use stdout to a terminal
     cmd = (CFSD_PREFIX + "--op export --pgid {pg}").format(osd=ONEOSD, pg=ONEPG)
     ERRORS += test_failure(cmd, "stdout is a tty and no --file filename specified", tty=True)
@@ -963,15 +978,15 @@ def main(argv):
     OSDS = get_osds(ALLPGS[0], OSDDIR)
     osd = OSDS[0]
 
-    print "Test all --op dump-journal"
-    ALLOSDS = [f for f in os.listdir(OSDDIR) if os.path.isdir(os.path.join(OSDDIR, f)) and string.find(f, "osd") == 0]
+    print("Test all --op dump-journal")
+    ALLOSDS = [f for f in os.listdir(OSDDIR) if os.path.isdir(os.path.join(OSDDIR, f)) and f.find("osd") == 0]
     ERRORS += test_dump_journal(CFSD_PREFIX, ALLOSDS)
 
     # Test --op list and generate json for all objects
-    print "Test --op list variants"
+    print("Test --op list variants")
 
     # retrieve all objects from all PGs
-    tmpfd = open(TMPFILE, "w")
+    tmpfd = open(TMPFILE, "wb")
     cmd = (CFSD_PREFIX + "--op list --format json").format(osd=osd)
     logging.debug(cmd)
     ret = call(cmd, shell=True, stdout=tmpfd)
@@ -984,7 +999,7 @@ def main(argv):
     (pgid, coll, jsondict) = json.loads(JSONOBJ[0])[0]
 
     # retrieve all objects in a given PG
-    tmpfd = open(OTHERFILE, "a")
+    tmpfd = open(OTHERFILE, "ab")
     cmd = (CFSD_PREFIX + "--op list --pgid {pg} --format json").format(osd=osd, pg=pgid)
     logging.debug(cmd)
     ret = call(cmd, shell=True, stdout=tmpfd)
@@ -1002,7 +1017,7 @@ def main(argv):
         ERRORS += 1
 
     # retrieve all objects with a given name in a given PG
-    tmpfd = open(OTHERFILE, "w")
+    tmpfd = open(OTHERFILE, "wb")
     cmd = (CFSD_PREFIX + "--op list --pgid {pg} {object} --format json").format(osd=osd, pg=pgid, object=jsondict['oid'])
     logging.debug(cmd)
     ret = call(cmd, shell=True, stdout=tmpfd)
@@ -1019,11 +1034,11 @@ def main(argv):
                       "from the first line of --op list --pgid {pg} {object}".format(pg=pgid, object=jsondict['oid']))
         ERRORS += 1
 
-    print "Test --op list by generating json for all objects using default format"
+    print("Test --op list by generating json for all objects using default format")
     for pg in ALLPGS:
         OSDS = get_osds(pg, OSDDIR)
         for osd in OSDS:
-            tmpfd = open(TMPFILE, "a")
+            tmpfd = open(TMPFILE, "ab")
             cmd = (CFSD_PREFIX + "--op list --pgid {pg}").format(osd=osd, pg=pg)
             logging.debug(cmd)
             ret = call(cmd, shell=True, stdout=tmpfd)
@@ -1041,12 +1056,12 @@ def main(argv):
             continue
         db[jsondict['namespace']][jsondict['oid']]['json'] = json.dumps((pgid, jsondict))
         # print db[jsondict['namespace']][jsondict['oid']]['json']
-        if string.find(jsondict['oid'], EC_NAME) == 0 and 'shard_id' not in jsondict:
+        if jsondict['oid'].find(EC_NAME) == 0 and 'shard_id' not in jsondict:
             logging.error("Malformed JSON {json}".format(json=JSON))
             ERRORS += 1
 
     # Test get-bytes
-    print "Test get-bytes and set-bytes"
+    print("Test get-bytes and set-bytes")
     for nspace in db.keys():
         for basename in db[nspace].keys():
             file = os.path.join(DATADIR, nspace + "-" + basename + "__head")
@@ -1093,7 +1108,7 @@ def main(argv):
                     if ret != 0:
                         logging.error("Bad exit status {ret} from set-bytes".format(ret=ret))
                         ERRORS += 1
-                    fd = open(TESTNAME, "w")
+                    fd = open(TESTNAME, "wb")
                     cmd = (CFSD_PREFIX + "--pgid {pg} '{json}' get-bytes -").format(osd=osd, pg=pg, json=JSON)
                     logging.debug(cmd)
                     ret = call(cmd, shell=True, stdout=fd)
@@ -1123,7 +1138,7 @@ def main(argv):
                     if ret != 0:
                         logging.error("Bad exit status {ret} from set-bytes --dry-run".format(ret=ret))
                         ERRORS += 1
-                    fd = open(TESTNAME, "w")
+                    fd = open(TESTNAME, "wb")
                     cmd = (CFSD_PREFIX + "--pgid {pg} '{json}' get-bytes -").format(osd=osd, pg=pg, json=JSON)
                     logging.debug(cmd)
                     ret = call(cmd, shell=True, stdout=fd)
@@ -1142,7 +1157,7 @@ def main(argv):
                         cat_file(logging.DEBUG, SETNAME)
                         ERRORS += 1
 
-                    fd = open(file, "r")
+                    fd = open(file, "rb")
                     cmd = (CFSD_PREFIX + "--pgid {pg} '{json}' set-bytes").format(osd=osd, pg=pg, json=JSON)
                     logging.debug(cmd)
                     ret = call(cmd, shell=True, stdin=fd)
@@ -1169,7 +1184,7 @@ def main(argv):
         pass
 
     # Test get-attr, set-attr, rm-attr, get-omaphdr, set-omaphdr, get-omap, set-omap, rm-omap
-    print "Test get-attr, set-attr, rm-attr, get-omaphdr, set-omaphdr, get-omap, set-omap, rm-omap"
+    print("Test get-attr, set-attr, rm-attr, get-omaphdr, set-omaphdr, get-omap, set-omap, rm-omap")
     for nspace in db.keys():
         for basename in db[nspace].keys():
             file = os.path.join(DATADIR, nspace + "-" + basename + "__head")
@@ -1182,7 +1197,7 @@ def main(argv):
                               and f.split("_")[0] == basename and f.split("_")[4] == nspace]
                     if not fnames:
                         continue
-                    for key, val in db[nspace][basename]["xattr"].iteritems():
+                    for key, val in db[nspace][basename]["xattr"].items():
                         attrkey = "_" + key
                         cmd = (CFSD_PREFIX + " '{json}' get-attr {key}").format(osd=osd, json=JSON, key=attrkey)
                         logging.debug(cmd)
@@ -1295,7 +1310,7 @@ def main(argv):
                         ERRORS += 1
                         continue
 
-                    for omapkey, val in db[nspace][basename]["omap"].iteritems():
+                    for omapkey, val in db[nspace][basename]["omap"].items():
                         cmd = (CFSD_PREFIX + " '{json}' get-omap {key}").format(osd=osd, json=JSON, key=omapkey)
                         logging.debug(cmd)
                         getval = check_output(cmd, shell=True)
@@ -1361,7 +1376,7 @@ def main(argv):
                             continue
 
     # Test dump
-    print "Test dump"
+    print("Test dump")
     for nspace in db.keys():
         for basename in db[nspace].keys():
             file = os.path.join(DATADIR, nspace + "-" + basename + "__head")
@@ -1382,7 +1397,7 @@ def main(argv):
                         logging.error("Invalid dump for {json}".format(json=JSON))
                         ERRORS += 1
 
-    print "Test list-attrs get-attr"
+    print("Test list-attrs get-attr")
     ATTRFILE = r"/tmp/attrs.{pid}".format(pid=pid)
     VALFILE = r"/tmp/val.{pid}".format(pid=pid)
     for nspace in db.keys():
@@ -1397,7 +1412,7 @@ def main(argv):
                 for pg in OBJECPGS:
                     OSDS = get_osds(pg, OSDDIR)
                     # Fix shard_id since we only have one json instance for each object
-                    jsondict['shard_id'] = int(string.split(pg, 's')[1])
+                    jsondict['shard_id'] = int(pg.split('s')[1])
                     JSON = json.dumps(jsondict)
                     for osd in OSDS:
                         cmd = (CFSD_PREFIX + "--pgid {pg} '{json}' get-attr hinfo_key").format(osd=osd, pg=pg, json=JSON)
@@ -1406,7 +1421,7 @@ def main(argv):
                             out = check_output(cmd, shell=True, stderr=subprocess.STDOUT)
                             logging.debug("FOUND: {json} in {osd} has value '{val}'".format(osd=osd, json=JSON, val=out))
                             found += 1
-                        except subprocess.CalledProcessError, e:
+                        except subprocess.CalledProcessError as e:
                             if "No such file or directory" not in e.output and "No data available" not in e.output:
                                 raise
                 # Assuming k=2 m=1 for the default ec pool
@@ -1420,7 +1435,7 @@ def main(argv):
                     continue
                 if 'shard_id' in jsondict:
                     # Fix shard_id since we only have one json instance for each object
-                    jsondict['shard_id'] = int(string.split(pg, 's')[1])
+                    jsondict['shard_id'] = int(pg.split('s')[1])
                     JSON = json.dumps(jsondict)
                 OSDS = get_osds(pg, OSDDIR)
                 for osd in OSDS:
@@ -1429,7 +1444,7 @@ def main(argv):
                               and f.split("_")[0] == basename and f.split("_")[4] == nspace]
                     if not fnames:
                         continue
-                    afd = open(ATTRFILE, "w")
+                    afd = open(ATTRFILE, "wb")
                     cmd = (CFSD_PREFIX + "--pgid {pg} '{json}' list-attrs").format(osd=osd, pg=pg, json=JSON)
                     logging.debug(cmd)
                     ret = call(cmd, shell=True, stdout=afd)
@@ -1449,7 +1464,7 @@ def main(argv):
                             ERRORS += 1
                             continue
                         exp = values.pop(key)
-                        vfd = open(VALFILE, "w")
+                        vfd = open(VALFILE, "wb")
                         cmd = (CFSD_PREFIX + "--pgid {pg} '{json}' get-attr {key}").format(osd=osd, pg=pg, json=JSON, key="_" + key)
                         logging.debug(cmd)
                         ret = call(cmd, shell=True, stdout=vfd)
@@ -1465,10 +1480,10 @@ def main(argv):
                             ERRORS += 1
                     if len(values) != 0:
                         logging.error("Not all keys found, remaining keys:")
-                        print values
+                        print(values)
 
-    print "Test --op meta-list"
-    tmpfd = open(TMPFILE, "w")
+    print("Test --op meta-list")
+    tmpfd = open(TMPFILE, "wb")
     cmd = (CFSD_PREFIX + "--op meta-list").format(osd=ONEOSD)
     logging.debug(cmd)
     ret = call(cmd, shell=True, stdout=tmpfd)
@@ -1476,7 +1491,7 @@ def main(argv):
         logging.error("Bad exit status {ret} from --op meta-list request".format(ret=ret))
         ERRORS += 1
 
-    print "Test get-bytes on meta"
+    print("Test get-bytes on meta")
     tmpfd.close()
     lines = get_lines(TMPFILE)
     JSONOBJ = sorted(set(lines))
@@ -1509,7 +1524,7 @@ def main(argv):
     except:
         pass
 
-    print "Test pg info"
+    print("Test pg info")
     for pg in ALLREPPGS + ALLECPGS:
         for osd in get_osds(pg, OSDDIR):
             cmd = (CFSD_PREFIX + "--op info --pgid {pg} | grep '\"pgid\": \"{pg}\"'").format(osd=osd, pg=pg)
@@ -1519,12 +1534,12 @@ def main(argv):
                 logging.error("Getting info failed for pg {pg} from {osd} with {ret}".format(pg=pg, osd=osd, ret=ret))
                 ERRORS += 1
 
-    print "Test pg logging"
+    print("Test pg logging")
     if len(ALLREPPGS + ALLECPGS) == len(OBJREPPGS + OBJECPGS):
         logging.warning("All PGs have objects, so no log without modify entries")
     for pg in ALLREPPGS + ALLECPGS:
         for osd in get_osds(pg, OSDDIR):
-            tmpfd = open(TMPFILE, "w")
+            tmpfd = open(TMPFILE, "wb")
             cmd = (CFSD_PREFIX + "--op log --pgid {pg}").format(osd=osd, pg=pg)
             logging.debug(cmd)
             ret = call(cmd, shell=True, stdout=tmpfd)
@@ -1540,7 +1555,7 @@ def main(argv):
             if HASOBJ != MODOBJ:
                 logging.error("Bad log for pg {pg} from {osd}".format(pg=pg, osd=osd))
                 MSG = (HASOBJ and [""] or ["NOT "])[0]
-                print "Log should {msg}have a modify entry".format(msg=MSG)
+                print("Log should {msg}have a modify entry".format(msg=MSG))
                 ERRORS += 1
 
     try:
@@ -1548,8 +1563,8 @@ def main(argv):
     except:
         pass
 
-    print "Test list-pgs"
-    for osd in [f for f in os.listdir(OSDDIR) if os.path.isdir(os.path.join(OSDDIR, f)) and string.find(f, "osd") == 0]:
+    print("Test list-pgs")
+    for osd in [f for f in os.listdir(OSDDIR) if os.path.isdir(os.path.join(OSDDIR, f)) and f.find("osd") == 0]:
 
         CHECK_PGS = get_osd_pgs(os.path.join(OSDDIR, osd), None)
         CHECK_PGS = sorted(CHECK_PGS)
@@ -1566,7 +1581,7 @@ def main(argv):
             ERRORS += 1
 
     EXP_ERRORS = 0
-    print "Test pg export --dry-run"
+    print("Test pg export --dry-run")
     pg = ALLREPPGS[0]
     osd = get_osds(pg, OSDDIR)[0]
     fname = "/tmp/fname.{pid}".format(pid=pid)
@@ -1594,9 +1609,9 @@ def main(argv):
             EXP_ERRORS += 1
 
     os.mkdir(TESTDIR)
-    for osd in [f for f in os.listdir(OSDDIR) if os.path.isdir(os.path.join(OSDDIR, f)) and string.find(f, "osd") == 0]:
+    for osd in [f for f in os.listdir(OSDDIR) if os.path.isdir(os.path.join(OSDDIR, f)) and f.find("osd") == 0]:
         os.mkdir(os.path.join(TESTDIR, osd))
-    print "Test pg export"
+    print("Test pg export")
     for pg in ALLREPPGS + ALLECPGS:
         for osd in get_osds(pg, OSDDIR):
             mydir = os.path.join(TESTDIR, osd)
@@ -1615,7 +1630,7 @@ def main(argv):
 
     ERRORS += EXP_ERRORS
 
-    print "Test pg removal"
+    print("Test pg removal")
     RM_ERRORS = 0
     for pg in ALLREPPGS + ALLECPGS:
         for osd in get_osds(pg, OSDDIR):
@@ -1637,8 +1652,8 @@ def main(argv):
 
     IMP_ERRORS = 0
     if EXP_ERRORS == 0 and RM_ERRORS == 0:
-        print "Test pg import"
-        for osd in [f for f in os.listdir(OSDDIR) if os.path.isdir(os.path.join(OSDDIR, f)) and string.find(f, "osd") == 0]:
+        print("Test pg import")
+        for osd in [f for f in os.listdir(OSDDIR) if os.path.isdir(os.path.join(OSDDIR, f)) and f.find("osd") == 0]:
             dir = os.path.join(TESTDIR, osd)
             PGS = [f for f in os.listdir(dir) if os.path.isfile(os.path.join(dir, f))]
             for pg in PGS:
@@ -1668,24 +1683,24 @@ def main(argv):
     logging.debug(cmd)
 
     if EXP_ERRORS == 0 and RM_ERRORS == 0 and IMP_ERRORS == 0:
-        print "Verify replicated import data"
+        print("Verify replicated import data")
         data_errors, _ = check_data(DATADIR, TMPFILE, OSDDIR, REP_NAME)
         ERRORS += data_errors
     else:
         logging.warning("SKIPPING CHECKING IMPORT DATA DUE TO PREVIOUS FAILURES")
 
-    print "Test all --op dump-journal again"
-    ALLOSDS = [f for f in os.listdir(OSDDIR) if os.path.isdir(os.path.join(OSDDIR, f)) and string.find(f, "osd") == 0]
+    print("Test all --op dump-journal again")
+    ALLOSDS = [f for f in os.listdir(OSDDIR) if os.path.isdir(os.path.join(OSDDIR, f)) and f.find("osd") == 0]
     ERRORS += test_dump_journal(CFSD_PREFIX, ALLOSDS)
 
     vstart(new=False)
     wait_for_health()
 
     if EXP_ERRORS == 0 and RM_ERRORS == 0 and IMP_ERRORS == 0:
-        print "Verify erasure coded import data"
+        print("Verify erasure coded import data")
         ERRORS += verify(DATADIR, EC_POOL, EC_NAME, db)
         # Check replicated data/xattr/omap using rados
-        print "Verify replicated import data using rados"
+        print("Verify replicated import data using rados")
         ERRORS += verify(DATADIR, REP_POOL, REP_NAME, db)
 
     if EXP_ERRORS == 0:
@@ -1694,12 +1709,12 @@ def main(argv):
         logging.debug(cmd)
         ret = call(cmd, shell=True, stdout=nullfd, stderr=nullfd)
 
-        print "Test rados import"
+        print("Test rados import")
         first = True
-        for osd in [f for f in os.listdir(OSDDIR) if os.path.isdir(os.path.join(OSDDIR, f)) and string.find(f, "osd") == 0]:
+        for osd in [f for f in os.listdir(OSDDIR) if os.path.isdir(os.path.join(OSDDIR, f)) and f.find("osd") == 0]:
             dir = os.path.join(TESTDIR, osd)
             for pg in [f for f in os.listdir(dir) if os.path.isfile(os.path.join(dir, f))]:
-                if string.find(pg, "{id}.".format(id=REPID)) != 0:
+                if pg.find("{id}.".format(id=REPID)) != 0:
                     continue
                 file = os.path.join(dir, pg)
                 if first:
@@ -1742,7 +1757,7 @@ def main(argv):
     os.mkdir(DATADIR)
 
     # Cause SPLIT_POOL to split and test import with object/log filtering
-    print "Testing import all objects after a split"
+    print("Testing import all objects after a split")
     SPLIT_POOL = "split_pool"
     PG_COUNT = 1
     SPLIT_OBJ_COUNT = 5
@@ -1792,7 +1807,7 @@ def main(argv):
     wait_for_health()
     kill_daemons()
 
-    for osd in [f for f in os.listdir(OSDDIR) if os.path.isdir(os.path.join(OSDDIR, f)) and string.find(f, "osd") == 0]:
+    for osd in [f for f in os.listdir(OSDDIR) if os.path.isdir(os.path.join(OSDDIR, f)) and f.find("osd") == 0]:
         os.mkdir(os.path.join(TESTDIR, osd))
 
     pg = "{pool}.0".format(pool=SPLITID)
@@ -1850,7 +1865,7 @@ def main(argv):
 
         # Start up again to make sure imports didn't corrupt anything
         if IMP_ERRORS == 0:
-            print "Verify split import data"
+            print("Verify split import data")
             data_errors, count = check_data(DATADIR, TMPFILE, OSDDIR, SPLIT_NAME)
             ERRORS += data_errors
             if count != (SPLIT_OBJ_COUNT * SPLIT_NSPACE_COUNT * pool_size):
@@ -1863,23 +1878,24 @@ def main(argv):
     call("/bin/rm -rf {dir}".format(dir=DATADIR), shell=True)
 
     # vstart() starts 4 OSDs
-    ERRORS += test_get_set_osdmap(CFSD_PREFIX, range(4), ALLOSDS)
+    ERRORS += test_get_set_osdmap(CFSD_PREFIX, list(range(4)), ALLOSDS)
     ERRORS += test_get_set_inc_osdmap(CFSD_PREFIX, ALLOSDS[0])
     if ERRORS == 0:
-        print "TEST PASSED"
+        print("TEST PASSED")
         return 0
     else:
-        print "TEST FAILED WITH {errcount} ERRORS".format(errcount=ERRORS)
+        print("TEST FAILED WITH {errcount} ERRORS".format(errcount=ERRORS))
         return 1
 
 
 def remove_btrfs_subvolumes(path):
     result = subprocess.Popen("stat -f -c '%%T' %s" % path, shell=True, stdout=subprocess.PIPE)
-    filesystem = result.stdout.readlines()[0]
-    if filesystem.rstrip('\n') == "btrfs":
+    for line in result.stdout:
+        filesystem = decode(line).rstrip('\n')
+    if filesystem == "btrfs":
         result = subprocess.Popen("sudo btrfs subvolume list %s" % path, shell=True, stdout=subprocess.PIPE)
-        for line in result.stdout.readlines():
-            subvolume=line.split()[8]
+        for line in result.stdout:
+            subvolume = decode(line).split()[8]
             # extracting the relative volume name
             m = re.search(".*(%s.*)" % path, subvolume)
             if m: