Esempio n. 1
0
 def testIsWindows(self):
     self.assertFalse(OS.is_windows('fedora'))
     self.assertFalse(OS.is_windows('rhel'))
     self.assertFalse(OS.is_windows('centos'))
     self.assertFalse(OS.is_windows('ubuntu'))
     self.assertFalse(OS.is_windows('debian'))
     self.assertFalse(OS.is_windows('mock'))
     self.assertTrue(OS.is_windows('windows'))
     self.assertTrue(OS.is_windows('mock_windows'))
Esempio n. 2
0
 def testIsWindows(self):
     self.assertFalse(OS.is_windows('fedora'))
     self.assertFalse(OS.is_windows('rhel'))
     self.assertFalse(OS.is_windows('centos'))
     self.assertFalse(OS.is_windows('ubuntu'))
     self.assertFalse(OS.is_windows('debian'))
     self.assertFalse(OS.is_windows('mock'))
     self.assertTrue(OS.is_windows('windows'))
     self.assertTrue(OS.is_windows('mock_windows'))
Esempio n. 3
0
 def os_dispatcher():
     '''helper to get the os specific dispatcher'''
     if OS.is_windows():
         import snap.backends.services.windowsdispatcher
         return snap.backends.services.windowsdispatcher.WindowsDispatcher
     else:
         import snap.backends.services.linuxdispatcher
         return snap.backends.services.linuxdispatcher.LinuxDispatcher
Esempio n. 4
0
 def os_dispatcher():
     '''helper to get the os specific dispatcher'''
     if OS.is_windows():
         import snap.backends.services.windowsdispatcher
         return snap.backends.services.windowsdispatcher.WindowsDispatcher
     else:
         import snap.backends.services.linuxdispatcher
         return snap.backends.services.linuxdispatcher.LinuxDispatcher
Esempio n. 5
0
 def testOSDispatcher(self):
     if OS.is_windows():
         self.assertEqual(
             snap.backends.services.dispatcher.Dispatcher.os_dispatcher(),
             snap.backends.services.windowsdispatcher.WindowsDispatcher)
     elif OS.is_linux():
         self.assertEqual(
             snap.backends.services.dispatcher.Dispatcher.os_dispatcher(),
             snap.backends.services.linuxdispatcher.LinuxDispatcher)
Esempio n. 6
0
    def setUp(self):
        self.basedir = os.path.join(os.path.dirname(__file__), "data", "basedir")
        if os.path.isdir(self.basedir):
            shutil.rmtree(self.basedir)
        os.mkdir(self.basedir)

        if OS.is_windows():
            self.dispatcher = snap.backends.services.windowsdispatcher.WindowsDispatcher()
        else:
            self.dispatcher = snap.backends.services.linuxdispatcher.LinuxDispatcher()
Esempio n. 7
0
 def testOSDispatcher(self):
     if OS.is_windows():
         self.assertEqual(
             snap.backends.services.dispatcher.Dispatcher.os_dispatcher(),
             snap.backends.services.windowsdispatcher.WindowsDispatcher,
         )
     elif OS.is_linux():
         self.assertEqual(
             snap.backends.services.dispatcher.Dispatcher.os_dispatcher(),
             snap.backends.services.linuxdispatcher.LinuxDispatcher,
         )
Esempio n. 8
0
 def testStartStopRunningService(self):
     if OS.is_windows():
         service = "WPCsvc"  # windows parental controls
     else:
         service = snap.backends.services.adapters.httpd.Httpd.DAEMON
     is_running = self.dispatcher.service_running(service)
     self.dispatcher.start_service(service)
     self.assertTrue(self.dispatcher.service_running(service))
     self.dispatcher.stop_service(service)
     self.assertFalse(self.dispatcher.service_running(service))
     if is_running:
         self.dispatcher.start_service(service)
Esempio n. 9
0
 def testStartStopRunningService(self):
     if OS.is_windows():
         service = "WPCsvc"  # windows parental controls
     else:
         service = snap.backends.services.adapters.httpd.Httpd.DAEMON
     is_running = self.dispatcher.service_running(service)
     self.dispatcher.start_service(service)
     self.assertTrue(self.dispatcher.service_running(service))
     self.dispatcher.stop_service(service)
     self.assertFalse(self.dispatcher.service_running(service))
     if is_running:
         self.dispatcher.start_service(service)
Esempio n. 10
0
    def setUp(self):
        self.basedir = os.path.join(os.path.dirname(__file__), "data",
                                    "basedir")
        if os.path.isdir(self.basedir):
            shutil.rmtree(self.basedir)
        os.mkdir(self.basedir)

        if OS.is_windows():
            self.dispatcher = snap.backends.services.windowsdispatcher.WindowsDispatcher(
            )
        else:
            self.dispatcher = snap.backends.services.linuxdispatcher.LinuxDispatcher(
            )
Esempio n. 11
0
class OsRegistryTest(unittest.TestCase):
    def setUp(self):
        self.basedir = os.path.join(os.path.dirname(__file__), "data",
                                    "osrtest")
        if not os.path.isdir(self.basedir):
            os.mkdir(self.basedir)

    def tearDown(self):
        if os.path.isdir(self.basedir):
            shutil.rmtree(self.basedir)

    def testIsLinux(self):
        self.assertTrue(OS.is_linux('fedora'))
        self.assertTrue(OS.is_linux('rhel'))
        self.assertTrue(OS.is_linux('centos'))
        self.assertTrue(OS.is_linux('ubuntu'))
        self.assertTrue(OS.is_linux('debian'))
        self.assertTrue(OS.is_linux('mock'))
        self.assertFalse(OS.is_linux('windows'))
        self.assertFalse(OS.is_linux('mock_windows'))

    def testIsWindows(self):
        self.assertFalse(OS.is_windows('fedora'))
        self.assertFalse(OS.is_windows('rhel'))
        self.assertFalse(OS.is_windows('centos'))
        self.assertFalse(OS.is_windows('ubuntu'))
        self.assertFalse(OS.is_windows('debian'))
        self.assertFalse(OS.is_windows('mock'))
        self.assertTrue(OS.is_windows('windows'))
        self.assertTrue(OS.is_windows('mock_windows'))

    def testAptBased(self):
        self.assertTrue(OS.apt_based('ubuntu'))
        self.assertTrue(OS.apt_based('debian'))
        self.assertFalse(OS.apt_based('fedora'))
        self.assertFalse(OS.apt_based('rhel'))
        self.assertFalse(OS.apt_based('centos'))
        self.assertFalse(OS.apt_based('windows'))

    def testYumBased(self):
        self.assertFalse(OS.yum_based('ubuntu'))
        self.assertFalse(OS.yum_based('debian'))
        self.assertTrue(OS.yum_based('fedora'))
        self.assertTrue(OS.yum_based('rhel'))
        self.assertTrue(OS.yum_based('centos'))
        self.assertFalse(OS.yum_based('windows'))

    def testOsRoot(self):
        self.assertEqual('/', OS.get_root('fedora'))
        self.assertEqual('/', OS.get_root('ubuntu'))
        self.assertEqual('C:\\', OS.get_root('windows'))

    @unittest.skipUnless(OS.is_windows(), "only relevant for windows")
    def testWindowsRoot(self):
        self.assertEqual('C:\\', OS.get_root())

    @unittest.skipUnless(OS.is_linux(), "only relevant for linux")
    def testLinuxRoot(self):
        self.assertEqual('/', OS.get_root())

    def testPathSeperator(self):
        self.assertEqual('/', OS.get_path_seperator('fedora'))
        self.assertEqual('/', OS.get_path_seperator('ubuntu'))
        self.assertEqual('\\', OS.get_path_seperator('windows'))

    @unittest.skipUnless(OS.is_windows(), "only relevant for windows")
    def testWindowsPathSeperator(self):
        self.assertEqual('\\', OS.get_path_seperator())

    @unittest.skipUnless(OS.is_linux(), "only relevant for linux")
    def testLinuxPathSeperator(self):
        self.assertEqual('/', OS.get_path_seperator())

    #def testDefaultBackendForTarget(self):

    @unittest.skipUnless(OS.is_windows(), "only relevant for windows")
    def testWindowsNullFile(self):
        self.assertEqual("nul", OSUtils.null_file())

    @unittest.skipUnless(OS.is_linux(), "only relevant for linux")
    def testLinuxNullFile(self):
        self.assertEqual("/dev/null", OSUtils.null_file())

    @unittest.skipUnless(OS.is_windows(), "only relevant for windows")
    def testWindowsChown(self):
        basefile = os.path.join(self.basedir, "foo")
        f = open(basefile, "w")
        f.write("foo")
        f.close
        OSUtils.chown(self.basedir, username="******")

        null = open(OSUtils.null_file(), 'w')
        tfile = tempfile.TemporaryFile()
        popen = subprocess.Popen(["icacls", self.basedir],
                                 stdout=tfile,
                                 stderr=null)
        popen.wait()
        tfile.seek(0)
        c = tfile.read()
        self.assertNotEqual(1, len(re.findall(".*mmorsi.*(F).*\n.*", c)))
        tfile.close()

        tfile = tempfile.TemporaryFile()
        popen = subprocess.Popen(["icacls", basefile],
                                 stdout=tfile,
                                 stderr=null)
        popen.wait()
        tfile.seek(0)
        c = tfile.read()
        self.assertNotEqual(1, len(re.findall(".*mmorsi.*(F).*\n.*", c)))
        tfile.close()

    @unittest.skipUnless(OS.is_linux(), "only relevant for linux")
    def testLinuxChown(self):
        basefile = os.path.join(self.basedir, "foo")
        f = open(basefile, "w")
        f.write("foo")
        f.close
        OSUtils.chown(self.basedir, uid=100, gid=100)

        st = os.stat(self.basedir)
        self.assertEqual(100, st.st_uid)
        self.assertEqual(100, st.st_gid)
        st = os.stat(basefile)
        self.assertEqual(100, st.st_uid)
        self.assertEqual(100, st.st_gid)

        import pwd
        pwo = pwd.getpwnam("nobody")
        uid = pwo.pw_uid
        gid = pwo.pw_gid
        OSUtils.chown(self.basedir, username="******")
        st = os.stat(self.basedir)
        self.assertEqual(uid, st.st_uid)
        self.assertEqual(gid, st.st_gid)
        st = os.stat(basefile)
        self.assertEqual(uid, st.st_uid)
        self.assertEqual(gid, st.st_gid)

    #@unittest.skipUnless(OS.is_windows(), "only relevant for windows")
    #def testWindowsIsSuperUser(self):
    # not sure how to switch users on windows to test this

    @unittest.skipUnless(OS.is_linux(), "only relevant for linux")
    def testLinuxIsSuperUser(self):
        ouid = os.geteuid()
        self.assertTrue(OSUtils.is_superuser())

        os.seteuid(100)
        self.assertFalse(OSUtils.is_superuser())

        os.seteuid(ouid)
Esempio n. 12
0
class Postgresql:

    if OS.yum_based():
        DATADIR = '/var/lib/pgsql/data'
        DAEMON = 'postgresql'
        PSQL_CMD = '/usr/bin/psql'
        PGDUMPALL_CMD = '/usr/bin/pg_dumpall'

        # hack until we re-introduce package system abstraction:
        PREREQ_INSTALL_COMMAND = 'yum install -y postgresql-server postgresql'

    elif OS.apt_based() and os.path.isdir('/var/lib/postgresql'):
        VERSION = os.listdir('/var/lib/postgresql')[0]
        DATADIR = '/var/lib/postgresql/' + VERSION + '/main'
        DAEMON = 'postgresql'
        PSQL_CMD = '/usr/bin/psql'
        PGDUMPALL_CMD = '/usr/bin/pg_dumpall'

        # hack until we re-introduce package system abstraction:
        PREREQ_INSTALL_COMMAND = 'apt-get install -y postgresql'

    elif OS.is_windows() and os.path.isdir("C:\Program Files\PostgreSQL"):
        VERSION = os.listdir('C:\Program Files\PostgreSQL')[0]
        DATADIR = os.path.join("C:\Program Files\PostgreSQL", VERSION, "data")
        DAEMON = 'postgresql-x64-' + VERSION  # FIXME also support 32 bit
        PSQL_CMD = os.path.join("C:\Program Files\PostgreSQL", VERSION,
                                "bin\psql.exe")
        PGDUMPALL_CMD = os.path.join("C:\Program Files\PostgreSQL", VERSION,
                                     "bin\pg_dumpall.exe")

    else:
        VERSION = None
        DATADIR = None
        DAEMON = None
        PSQL_CMD = None
        PGDUMPALL_CMD = None

    def set_pgpassword_env():
        '''helper to set the postgres password in the env from the config'''
        pgpassword = snap.config.options.service_options['postgresql_password']
        penv = os.environ
        penv['PGPASSWORD'] = pgpassword
        return penv

    set_pgpassword_env = staticmethod(set_pgpassword_env)

    def db_exists(dbname):
        '''helper to return boolean indicating if the db w/ the specified name exists'''
        # get the env containing the postgres password
        penv = Postgresql.set_pgpassword_env()

        # retrieve list of db names from postgres
        c = FileManager.capture_output([
            Postgresql.PSQL_CMD, "--username", "postgres", "-t", "-c",
            "select datname from pg_database"
        ],
                                       env=penv)

        # determine if the specified one is among them
        has_db = len(re.findall(dbname, c))

        return has_db

    db_exists = staticmethod(db_exists)

    def create_db(dbname):
        '''helper to create the specified database'''
        null = open(OSUtils.null_file(), 'w')

        # get env containing the postgres password
        penv = Postgresql.set_pgpassword_env()

        # create the db
        popen = subprocess.Popen([
            Postgresql.PSQL_CMD, "--username", "postgres", "-c",
            "CREATE DATABASE " + dbname
        ],
                                 env=penv,
                                 stdout=null,
                                 stderr=null)
        popen.wait()

    create_db = staticmethod(create_db)

    def drop_db(dbname):
        '''helper to drop the specified database'''
        null = open(OSUtils.null_file(), 'w')

        # get env containing the postgres password
        penv = Postgresql.set_pgpassword_env()

        # destroy the db
        popen = subprocess.Popen([
            Postgresql.PSQL_CMD, "--username", "postgres", "-c",
            "DROP DATABASE " + dbname
        ],
                                 env=penv,
                                 stdout=null,
                                 stderr=null)
        popen.wait()

    drop_db = staticmethod(drop_db)

    def set_root_pass():
        '''helper to set the postgresql root password'''
        # !!!FIXME!!! implement, can be accomplished by su'ing to the postgres user on linux

    set_root_pass = staticmethod(set_root_pass)

    def init_db():
        '''helper to initialize the database server'''

        # db already initialized, just return
        if os.path.isdir(Postgresql.DATADIR) and len(
                os.listdir(Postgresql.DATADIR)) > 0:
            return

        null = open(OSUtils.null_file(), 'w')

        # FIXME should run initdb manually
        popen = subprocess.Popen(["service", "postgresql", "initdb"],
                                 stdout=null)
        popen.wait()

    init_db = staticmethod(init_db)

    def is_available(self):
        '''return true postgres is available locally'''
        return Postgresql.DATADIR and os.path.isdir(Postgresql.DATADIR)

    def install_prereqs(self):
        if OS.is_linux():
            popen = subprocess.Popen(Postgresql.PREREQ_INSTALL_COMMAND.split())
            popen.wait()
        # !!!FIXME!!! it is possible to install postgresql in an automated /
        # non-interactive method on windows, implement this!!!

    def backup(self, basedir):
        dispatcher = Dispatcher.os_dispatcher()
        null = open(OSUtils.null_file(), 'w')

        if OS.is_linux():
            Postgresql.set_root_pass()

        # check to see if service is running
        already_running = dispatcher.service_running(Postgresql.DAEMON)

        # start the postgresql server
        dispatcher.start_service(Postgresql.DAEMON)

        # get env containing postgres password
        penv = Postgresql.set_pgpassword_env()

        outfile = file(basedir + "/dump.psql", "w")
        pipe = subprocess.Popen(
            [Postgresql.PGDUMPALL_CMD, "--username", "postgres"],
            env=penv,
            stdout=outfile,
            stderr=null)
        pipe.wait()

        # if postgresql was running b4hand, start up again
        if not already_running:
            dispatcher.stop_service(Postgresql.DAEMON)

    def restore(self, basedir):
        dispatcher = Dispatcher.os_dispatcher()
        null = open(OSUtils.null_file(), 'w')

        if OS.is_linux():
            Postgresql.set_root_pass()

        # init the postgresql db
        Postgresql.init_db()

        # start the postgresql service
        dispatcher.start_service(Postgresql.DAEMON)

        # get env containing the postgresql password
        penv = Postgresql.set_pgpassword_env()

        # use pipe to invoke postgres, restoring database
        infile = file(basedir + "/dump.psql", "r")
        popen = subprocess.Popen(
            [Postgresql.PSQL_CMD, "--username", "postgres"],
            env=penv,
            stdin=infile,
            stdout=null,
            stderr=null)
        popen.wait()
Esempio n. 13
0
class SFileMetadataTest(unittest.TestCase):
    def setUp(self):
        self.source = ''
        self.dest = ''
        self.source_dir = ''
        self.dest_dir = ''

    def tearDown(self):
        if os.path.isdir(self.source_dir):
            shutil.rmtree(self.source_dir)
        if os.path.isdir(self.dest_dir):
            shutil.rmtree(self.dest_dir)
        if os.path.isfile(self.source):
            os.remove(self.source)
        if os.path.isfile(self.dest):
            os.remove(self.dest)

    def testWriteFilesRecordFile(self):
        path1 = os.path.join("some", "path")
        path2 = os.path.join("another", "path")
        self.dest = os.path.join(os.path.dirname(__file__), "data",
                                 "files-out.xml")
        files = [SFile(path=path1), SFile(path=path2)]

        files_record_file = FilesRecordFile(self.dest)
        files_record_file.write(files)
        contents = FileManager.read_file(self.dest)

        self.assertEqual(
            "<files><file>" + path1 + "</file><file>" + path2 +
            "</file></files>", contents)

    def testReadFilesRecordFile(self):
        file_path = os.path.join(os.path.dirname(__file__), "data",
                                 "recordfile.xml")
        files = FilesRecordFile(file_path).read()
        file_paths = []
        for sfile in files:
            file_paths.append(sfile.path)
        self.assertIn('/tmp/file1', file_paths)
        self.assertIn('/tmp/subdir/file2', file_paths)

    def testSFileCopyTo(self):
        basedir = os.path.join(os.path.dirname(__file__), "data")
        self.source_dir = os.path.join(basedir, "source", "subdir")
        self.dest_dir = os.path.join(basedir, "dest")

        os.makedirs(self.source_dir)
        f = open(os.path.join(self.source_dir, "foo"), 'w')
        f.write("foo")
        f.close()

        dest_file = os.path.join(self.dest_dir, self.source_dir, "foo")

        sfile = SFile(path=os.path.join(self.source_dir, "foo"))
        sfile.copy_to(self.dest_dir)
        self.assertTrue(os.path.exists(dest_file))

        contents = FileManager.read_file(dest_file)

        self.assertEqual("foo", contents)

        shutil.rmtree(os.path.join(basedir, "source"))

    def testSFileCopyToWithPrefix(self):
        basedir = os.path.join(os.path.dirname(__file__), "data")
        self.source_dir = os.path.join(basedir, "source", "subdir")
        self.dest_dir = os.path.join(basedir, "dest")

        os.makedirs(self.source_dir)
        f = open(os.path.join(self.source_dir, "foo"), 'w')
        f.write("foo")
        f.close()

        dest_file = os.path.join(self.dest_dir, "source", "subdir", "foo")

        sfile = SFile(path=os.path.join("source", "subdir", "foo"))
        sfile.copy_to(self.dest_dir, path_prefix=basedir)
        self.assertTrue(os.path.exists(dest_file))

        shutil.rmtree(os.path.join(basedir, "source"))

    @unittest.skipIf(OS.is_windows(),
                     "symbolic links not currently supported on windows")
    def testSFileCopyLinkTo(self):
        basedir = os.path.join(os.path.dirname(__file__), "data")
        self.source = os.path.join(basedir, "sourcelink")
        self.dest_dir = os.path.join(basedir, "destdir")

        os.makedirs(self.dest_dir)

        if os.path.islink(self.source):
            os.remove(self.source)

        os.symlink("/foobar", self.source)
        sfile = SFile(self.source)
        sfile.copy_to(self.dest_dir)

        self.assertTrue(os.path.islink(self.dest_dir + self.source))
        self.assertEqual("/foobar",
                         os.path.realpath(self.dest_dir + self.source))

    @unittest.skipUnless(OS.is_windows(), "only needed on windows platform")
    def testSFileWindowsPathEscape(self):
        orig_path = "C:\\Program Files\\myfile"

        path = SFile.windows_path_escape(orig_path)
        self.assertEqual("C___Program Files\\myfile", path)

        path = SFile.windows_path_escape(path)
        self.assertEqual(orig_path, path)
Esempio n. 14
0
class Httpd:

    if OS.yum_based():
        DAEMON = 'httpd'
        CONF_D = '/etc/httpd'
        DOCUMENT_ROOT = '/var/www'

        # hack until we re-introduce package system abstraction:
        PREREQ_INSTALL_COMMAND = 'yum install -y httpd'

    elif OS.apt_based():
        DAEMON = 'apache2'
        CONF_D = '/etc/apache2'
        DOCUMENT_ROOT = '/var/www'

        # hack until we re-introduce package system abstraction:
        PREREQ_INSTALL_COMMAND = 'apt-get install -y apache2'

    elif OS.is_windows() and os.path.isdir(
            "C:\Program Files (x86)\Apache Software Foundation"):
        DAEMON = 'Apache2.2'
        CONF_D = "C:\\Program Files (x86)\\Apache Software Foundation\\Apache2.2\\conf"
        DOCUMENT_ROOT = "C:\\Program Files (x86)\\Apache Software Foundation\\Apache2.2\\htdocs"

    else:
        DAEMON = None
        CONF_D = None
        DOCUMENT_ROOT = None

    def is_available(self):
        '''return true if we're on a linux system and the init script is available'''
        return (Httpd.CONF_D and os.path.isdir(Httpd.CONF_D)
                and Httpd.DOCUMENT_ROOT and os.path.isdir(Httpd.DOCUMENT_ROOT))

    def install_prereqs(self):
        if OS.is_linux():
            popen = subprocess.Popen(Httpd.PREREQ_INSTALL_COMMAND.split())
            popen.wait()
        # !!!FIXME!!! it is possible to install httpd in an automated /
        # non-interactive method on windows, implement this!!!

    def backup(self, basedir):
        # backup the webroot, confd
        sfiles = []
        files = snap.filemanager.FileManager.get_all_files(
            include=[Httpd.DOCUMENT_ROOT, Httpd.CONF_D])
        for tfile in files:
            if os.access(tfile, os.R_OK):
                sfile = SFile(tfile)
                sfile.copy_to(basedir)
                sfiles.append(sfile)

        # write record file to basedir
        record = FilesRecordFile(os.path.join(basedir, "service-http.xml"))
        record.write(sfiles)

    def restore(self, basedir):
        dispatcher = Dispatcher.os_dispatcher()

        record_file = os.path.join(basedir, "service-http.xml")

        # if files record file isn't found, simply return
        if not os.path.isfile(record_file):
            return

        # stop the httpd service if already running
        if dispatcher.service_running(Httpd.DAEMON):
            dispatcher.stop_service(Httpd.DAEMON)

        # read files from the record file
        record = FilesRecordFile(record_file)
        sfiles = record.read()

        # restore those to their original locations
        for sfile in sfiles:
            sfile.copy_to(path_prefix=basedir)

        # ensure the various subdirs exists even if empty
        if OS.is_linux() and not os.path.isdir(
                os.path.join(Httpd.DOCUMENT_ROOT, "html")):
            os.mkdir(os.path.join(Httpd.DOCUMENT_ROOT, "html"))
        if OS.is_linux() and not os.path.isdir(
                os.path.join(Httpd.CONF_D, "logs")):
            os.mkdir(os.path.join(Httpd.CONF_D, "logs"))
        if OS.is_linux() and not os.path.isdir(
                os.path.join(Httpd.CONF_D, "run")):
            os.mkdir(os.path.join(Httpd.CONF_D, "run"))

        # start the httpd service
        dispatcher.start_service(Httpd.DAEMON)
Esempio n. 15
0
class ServiceDispatcherTest(unittest.TestCase):
    def setUp(self):
        self.basedir = os.path.join(os.path.dirname(__file__), "data",
                                    "basedir")
        if os.path.isdir(self.basedir):
            shutil.rmtree(self.basedir)
        os.mkdir(self.basedir)

        if OS.is_windows():
            self.dispatcher = snap.backends.services.windowsdispatcher.WindowsDispatcher(
            )
        else:
            self.dispatcher = snap.backends.services.linuxdispatcher.LinuxDispatcher(
            )

    def tearDown(self):
        shutil.rmtree(self.basedir)

    def testStartStopRunningService(self):
        if OS.is_windows():
            service = "WPCsvc"  # windows parental controls
        else:
            service = snap.backends.services.adapters.httpd.Httpd.DAEMON
        is_running = self.dispatcher.service_running(service)
        self.dispatcher.start_service(service)
        self.assertTrue(self.dispatcher.service_running(service))
        self.dispatcher.stop_service(service)
        self.assertFalse(self.dispatcher.service_running(service))
        if is_running:
            self.dispatcher.start_service(service)

    def testLoadServices(self):
        services_path = os.path.join(os.path.dirname(__file__), "..", "snap",
                                     "backends", "services", "adapters")
        services = os.listdir(services_path)
        service_classes = []

        dispatcher = snap.backends.services.dispatcher.Dispatcher()

        for service in services:
            if service[0:8] != "__init__" and fnmatch.fnmatch(service, "*.py"):
                service = service.replace(".py", "")
                service_classes.append(
                    dispatcher.load_service(service).__class__)

        # TODO for now just have services tested here statically set, perhaps a better way TODO this?
        self.assertIn(snap.backends.services.adapters.iptables.Iptables,
                      service_classes)
        self.assertIn(snap.backends.services.adapters.postgresql.Postgresql,
                      service_classes)
        self.assertIn(snap.backends.services.adapters.mysql.Mysql,
                      service_classes)
        self.assertIn(snap.backends.services.adapters.mock.Mock,
                      service_classes)

    def testDispatcherBackup(self):
        snap.backends.services.adapters.mock.Mock.mock_is_available = True
        snap.backends.services.adapters.mock.Mock.is_available_called = False
        snap.backends.services.adapters.mock.Mock.backup_called = False

        dispatcher = snap.backends.services.dispatcher.Dispatcher()
        dispatcher.backup(self.basedir, include=['mock'])

        self.assertTrue(
            snap.backends.services.adapters.mock.Mock.is_available_called)
        self.assertTrue(
            snap.backends.services.adapters.mock.Mock.backup_called)
        self.assertTrue(
            os.path.isfile(os.path.join(self.basedir, "services.xml")))

        record = ServicesRecordFile(os.path.join(self.basedir, "services.xml"))
        services = record.read()
        service_names = []
        for service in services:
            service_names.append(service.name)
        self.assertIn("mock", service_names)

    def testNoBackupIfNotAvailable(self):
        snap.backends.services.adapters.mock.Mock.mock_is_available = False
        snap.backends.services.adapters.mock.Mock.is_available_called = False
        snap.backends.services.adapters.mock.Mock.backup_called = False

        dispatcher = snap.backends.services.dispatcher.Dispatcher()
        dispatcher.backup(self.basedir, include=['mock'])

        self.assertTrue(
            snap.backends.services.adapters.mock.Mock.is_available_called)
        self.assertFalse(
            snap.backends.services.adapters.mock.Mock.backup_called)

    def testOSDispatcher(self):
        if OS.is_windows():
            self.assertEqual(
                snap.backends.services.dispatcher.Dispatcher.os_dispatcher(),
                snap.backends.services.windowsdispatcher.WindowsDispatcher)
        elif OS.is_linux():
            self.assertEqual(
                snap.backends.services.dispatcher.Dispatcher.os_dispatcher(),
                snap.backends.services.linuxdispatcher.LinuxDispatcher)

    def testDispatcherRestore(self):
        # first backup the mock service
        dispatcher = snap.backends.services.dispatcher.Dispatcher()
        dispatcher.backup(self.basedir, include=['mock'])

        snap.backends.services.adapters.mock.Mock.mock_is_available = True
        snap.backends.services.adapters.mock.Mock.is_available_called = False
        snap.backends.services.adapters.mock.Mock.install_prereqs_called = False
        snap.backends.services.adapters.mock.Mock.restore_called = False

        # then restore it
        dispatcher.restore(self.basedir)
        self.assertTrue(
            snap.backends.services.adapters.mock.Mock.is_available_called)
        self.assertFalse(
            snap.backends.services.adapters.mock.Mock.install_prereqs_called)
        self.assertTrue(
            snap.backends.services.adapters.mock.Mock.restore_called)

        # ensure not restored if prereqs is not avaiable
        snap.backends.services.adapters.mock.Mock.mock_is_available = False
        snap.backends.services.adapters.mock.Mock.restore_called = False
        dispatcher.restore(self.basedir)
        self.assertFalse(
            snap.backends.services.adapters.mock.Mock.restore_called)

    def testNoInstallPrereqsIfAvailable(self):
        snap.backends.services.adapters.mock.Mock.mock_is_available = True
        snap.backends.services.adapters.mock.Mock.is_available_called = False
        snap.backends.services.adapters.mock.Mock.install_prereqs_called = False
        snap.backends.services.adapters.mock.Mock.restore_called = False

        # first backup the mock service
        dispatcher = snap.backends.services.dispatcher.Dispatcher()
        dispatcher.backup(self.basedir, include=['mock'])

        # then restore it
        dispatcher.restore(self.basedir)
        self.assertTrue(
            snap.backends.services.adapters.mock.Mock.is_available_called)
        self.assertFalse(
            snap.backends.services.adapters.mock.Mock.install_prereqs_called)
        self.assertTrue(
            snap.backends.services.adapters.mock.Mock.restore_called)

    def testSetPostgresEnvPassword(self):
        self.assertEqual(
            snap.backends.services.adapters.postgresql.Postgresql.
            set_pgpassword_env()['PGPASSWORD'],
            snap.config.options.service_options['postgresql_password'])

    def testPostgresqlDbExists(self):
        is_running = self.dispatcher.service_running('postgresql')
        self.dispatcher.start_service('postgresql')
        self.assertTrue(
            snap.backends.services.adapters.postgresql.Postgresql.db_exists(
                'postgres'))
        self.assertFalse(
            snap.backends.services.adapters.postgresql.Postgresql.db_exists(
                'non-existant-db'))
        if not is_running:
            self.dispatcher.stop_service('postgresql')

    def testPostgresqlCreateDropDb(self):
        is_running = self.dispatcher.service_running('postgresql')
        self.dispatcher.start_service('postgresql')
        snap.backends.services.adapters.postgresql.Postgresql.create_db(
            'test_db')
        self.assertTrue(
            snap.backends.services.adapters.postgresql.Postgresql.db_exists(
                'test_db'))
        snap.backends.services.adapters.postgresql.Postgresql.drop_db(
            'test_db')
        self.assertFalse(
            snap.backends.services.adapters.postgresql.Postgresql.db_exists(
                'test_db'))
        if not is_running:
            self.dispatcher.stop_service('postgresql')

    def testPostgresqlService(self):
        # first start the service if it isn't running
        already_running = self.dispatcher.service_running(
            snap.backends.services.adapters.postgresql.Postgresql.DAEMON)
        if not already_running:
            self.dispatcher.start_service(
                snap.backends.services.adapters.postgresql.Postgresql.DAEMON)

        # create a test database
        snap.backends.services.adapters.postgresql.Postgresql.create_db(
            'snaptest')

        # restore to original state
        if not already_running:
            self.dispatcher.stop_service(
                snap.backends.services.adapters.postgresql.Postgresql.DAEMON)

        backend = snap.backends.services.adapters.postgresql.Postgresql()
        backend.backup(self.basedir)

        # ensure the process is in its original state
        currently_running = self.dispatcher.service_running(
            snap.backends.services.adapters.postgresql.Postgresql.DAEMON)
        self.assertEqual(already_running, currently_running)

        # assert the db dump exists and has the db dump
        self.assertTrue(os.path.isfile(self.basedir + "/dump.psql"))
        c = FileManager.read_file(self.basedir + "/dump.psql")
        self.assertEqual(1, len(re.findall('CREATE DATABASE snaptest', c)))

        # finally cleanup
        self.dispatcher.start_service(
            snap.backends.services.adapters.postgresql.Postgresql.DAEMON)
        snap.backends.services.adapters.postgresql.Postgresql.drop_db(
            'snaptest')

        # stop the service, backup the datadir
        self.dispatcher.stop_service(
            snap.backends.services.adapters.postgresql.Postgresql.DAEMON)
        shutil.copytree(
            snap.backends.services.adapters.postgresql.Postgresql.DATADIR,
            snap.backends.services.adapters.postgresql.Postgresql.DATADIR +
            ".bak")

        # test restore
        backend.restore(self.basedir)

        # ensure service is running, datadir has been initialized
        self.assertTrue(
            self.dispatcher.service_running(
                snap.backends.services.adapters.postgresql.Postgresql.DAEMON))
        self.assertTrue(
            os.path.isdir(
                snap.backends.services.adapters.postgresql.Postgresql.DATADIR))

        # ensure the db exists
        self.assertTrue(
            snap.backends.services.adapters.postgresql.Postgresql.db_exists(
                'snaptest'))

        # stop the service, restore the db
        self.dispatcher.stop_service(
            snap.backends.services.adapters.postgresql.Postgresql.DAEMON)
        shutil.rmtree(
            snap.backends.services.adapters.postgresql.Postgresql.DATADIR)
        shutil.move(
            snap.backends.services.adapters.postgresql.Postgresql.DATADIR +
            ".bak",
            snap.backends.services.adapters.postgresql.Postgresql.DATADIR)

        # XXX dirty hack make sure the datadir is owned by postgres
        data_dir = None
        if snap.osregistry.OS.yum_based():
            data_dir = snap.backends.services.adapters.postgresql.Postgresql.DATADIR + "/../"
        elif snap.osregistry.OS.apt_based():
            data_dir = snap.backends.services.adapters.postgresql.Postgresql.DATADIR + "/../../"
        elif snap.osregistry.OS.is_windows():
            data_dir = snap.backends.services.adapters.postgresql.Postgresql.DATADIR
        snap.osregistry.OSUtils.chown(data_dir, username='******')

        # cleanup, restore to original state
        if already_running:
            self.dispatcher.start_service(
                snap.backends.services.adapters.postgresql.Postgresql.DAEMON)

    def testMysqlDbExists(self):
        is_running = self.dispatcher.service_running(
            snap.backends.services.adapters.mysql.Mysql.DAEMON)
        self.dispatcher.start_service(
            snap.backends.services.adapters.mysql.Mysql.DAEMON)
        self.assertTrue(
            snap.backends.services.adapters.mysql.Mysql.db_exists('mysql'))
        self.assertFalse(
            snap.backends.services.adapters.mysql.Mysql.db_exists(
                'non-existant-db'))
        if not is_running:
            self.dispatcher.stop_service(
                snap.backends.services.adapters.mysql.Mysql.DAEMON)

    def testMysqlCreateDropDb(self):
        is_running = self.dispatcher.service_running(
            snap.backends.services.adapters.mysql.Mysql.DAEMON)
        self.dispatcher.start_service(
            snap.backends.services.adapters.mysql.Mysql.DAEMON)
        snap.backends.services.adapters.mysql.Mysql.create_db('snap_test_db')
        self.assertTrue(
            snap.backends.services.adapters.mysql.Mysql.db_exists(
                'snap_test_db'))
        snap.backends.services.adapters.mysql.Mysql.drop_db('snap_test_db')
        self.assertFalse(
            snap.backends.services.adapters.mysql.Mysql.db_exists(
                'snap_test_db'))
        if not is_running:
            self.dispatcher.stop_service(
                snap.backends.services.adapters.mysql.Mysql.DAEMON)

    def testMysqlService(self):
        # first start the service if it isn't running
        already_running = self.dispatcher.service_running(
            snap.backends.services.adapters.mysql.Mysql.DAEMON)
        if not already_running:
            self.dispatcher.start_service(
                snap.backends.services.adapters.mysql.Mysql.DAEMON)

        # create a test database
        snap.backends.services.adapters.mysql.Mysql.create_db('snaptest')

        # restore to original state
        if not already_running:
            self.dispatcher.stop_service(
                snap.backends.services.adapters.mysql.Mysql.DAEMON)

        backend = snap.backends.services.adapters.mysql.Mysql()
        backend.backup(self.basedir)

        # ensure the process is in its original state
        currently_running = self.dispatcher.service_running(
            snap.backends.services.adapters.mysql.Mysql.DAEMON)
        self.assertEqual(already_running, currently_running)

        # assert the db dump exists and has the db dump
        self.assertTrue(os.path.isfile(self.basedir + "/dump.mysql"))
        c = FileManager.read_file(self.basedir + "/dump.mysql")
        self.assertEqual(1, len(re.findall('CREATE DATABASE.*snaptest', c)))

        # finally cleanup
        self.dispatcher.start_service(
            snap.backends.services.adapters.mysql.Mysql.DAEMON)
        snap.backends.services.adapters.mysql.Mysql.drop_db('snaptest')

        # stop the service, backup the datadir
        self.dispatcher.stop_service(
            snap.backends.services.adapters.mysql.Mysql.DAEMON)
        shutil.copytree(
            snap.backends.services.adapters.mysql.Mysql.DATADIR,
            snap.backends.services.adapters.mysql.Mysql.DATADIR + ".bak")

        # test restore
        backend.restore(self.basedir)

        # ensure service is running, datadir has been initialized
        self.assertTrue(
            self.dispatcher.service_running(
                snap.backends.services.adapters.mysql.Mysql.DAEMON))
        self.assertTrue(
            os.path.isdir(snap.backends.services.adapters.mysql.Mysql.DATADIR))

        # ensure the db exists
        self.assertTrue(
            snap.backends.services.adapters.mysql.Mysql.db_exists('snaptest'))

        # stop the service, restore the db
        self.dispatcher.stop_service(
            snap.backends.services.adapters.mysql.Mysql.DAEMON)
        shutil.rmtree(snap.backends.services.adapters.mysql.Mysql.DATADIR)
        shutil.move(
            snap.backends.services.adapters.mysql.Mysql.DATADIR + ".bak",
            snap.backends.services.adapters.mysql.Mysql.DATADIR)

        # XXX dirty hack make sure the datadir is owned by mysql
        data_dir = None
        if snap.osregistry.OS.yum_based():
            data_dir = snap.backends.services.adapters.mysql.Mysql.DATADIR
        elif snap.osregistry.OS.apt_based():
            data_dir = snap.backends.services.adapters.mysql.Mysql.DATADIR
        elif snap.osregistry.OS.is_windows():
            data_dir = snap.backends.services.adapters.mysql.Mysql.DATADIR
        snap.osregistry.OSUtils.chown(data_dir, username='******')

        # cleanup, restore to original state
        if already_running:
            self.dispatcher.start_service(
                snap.backends.services.adapters.mysql.Mysql.DAEMON)

    @unittest.skipIf(OS.is_windows(), "windows doesn't support iptables")
    def testIptablesService(self):
        # manually backup iptalbes to restore after the test
        f = file(self.basedir + "/iptables-backup", 'w')
        popen = subprocess.Popen("iptables-save", stdout=f)
        popen.wait()
        self.assertEqual(0, popen.returncode)

        # flush the filter table (removes all rules)
        popen = subprocess.Popen(["iptables", "-F"])
        popen.wait()
        self.assertEqual(0, popen.returncode)

        # allow port 22 traffic
        popen = subprocess.Popen([
            "iptables", "-A", "INPUT", "-p", "tcp", "--dport", "22", "-j",
            "ACCEPT"
        ])
        popen.wait()
        self.assertEqual(0, popen.returncode)

        # perform the backup
        backend = snap.backends.services.adapters.iptables.Iptables()
        backend.backup(self.basedir)

        # assert we have our rule
        self.assertTrue(os.path.isfile(self.basedir + "/iptables.rules"))
        c = FileManager.read_file(self.basedir + "/iptables.rules")
        self.assertEqual(
            1, len(re.findall('-A INPUT -p tcp -m tcp --dport 22 -j ACCEP',
                              c)))

        # again flush the filter table
        popen = subprocess.Popen(["iptables", "-F"])
        popen.wait()
        self.assertEqual(0, popen.returncode)

        # perform the restoration
        backend.restore(self.basedir)

        # assert that we have registered port 22
        f = file(self.basedir + "/iptables-running", 'w')
        popen = subprocess.Popen(["iptables", "-nvL"], stdout=f)
        popen.wait()
        self.assertEqual(0, popen.returncode)
        c = re.sub("\s+", " ",
                   FileManager.read_file(self.basedir + "/iptables-running"))
        self.assertEqual(1, len(re.findall(
            "ACCEPT.*tcp dpt:22", c)))  # TODO prolly could be a better regex

        # finally fiush the chain one last time and restore the original rules
        popen = subprocess.Popen(["iptables", "-F"])
        popen.wait()
        self.assertEqual(0, popen.returncode)
        popen = subprocess.Popen(
            ["iptables-restore", self.basedir + "/iptables-backup"])
        popen.wait()
        self.assertEqual(0, popen.returncode)

    def testHttpdService(self):
        # backup the http conf directory and document roots
        test_backup_dir = os.path.join(self.basedir, "snap-http-test")
        if os.path.isdir(test_backup_dir):
            shutil.rmtree(test_backup_dir)
        shutil.copytree(snap.backends.services.adapters.httpd.Httpd.CONF_D,
                        os.path.join(test_backup_dir, "conf_d"))
        shutil.copytree(
            snap.backends.services.adapters.httpd.Httpd.DOCUMENT_ROOT,
            os.path.join(test_backup_dir, "doc_root"))

        # run the backup
        test_base_dir = os.path.join(self.basedir, "snap-http-basedir")
        backend = snap.backends.services.adapters.httpd.Httpd()
        backend.backup(test_base_dir)

        # ensure conf.d and document root were backed up
        bfiles = []
        for root, dirs, files in os.walk(
                snap.backends.services.adapters.httpd.Httpd.CONF_D):
            for hfile in files:
                rfile = os.path.join(root, hfile)
                ffile = os.path.join(test_base_dir, rfile)
                self.assertTrue(os.path.isfile(ffile))
                bfiles.append(os.path.join(root, hfile))
        for root, dirs, files in os.walk(
                snap.backends.services.adapters.httpd.Httpd.DOCUMENT_ROOT):
            for hfile in files:
                rfile = os.path.join(root, hfile)
                ffile = os.path.join(test_base_dir, rfile)
                self.assertTrue(os.path.isfile(ffile))
                bfiles.append(os.path.join(root, hfile))
        self.assertTrue(
            os.path.isfile(os.path.join(test_base_dir, "service-http.xml")))

        # run the restore
        shutil.rmtree(snap.backends.services.adapters.httpd.Httpd.CONF_D)
        shutil.rmtree(
            snap.backends.services.adapters.httpd.Httpd.DOCUMENT_ROOT)
        backend.restore(test_base_dir)

        # ensure the files backed up were restored
        for hfile in bfiles:
            self.assertTrue(os.path.isfile(hfile))

        # ensure the service is running
        self.assertTrue(
            self.dispatcher.service_running(
                snap.backends.services.adapters.httpd.Httpd.DAEMON))

        # restore backup
        shutil.rmtree(snap.backends.services.adapters.httpd.Httpd.CONF_D)
        shutil.rmtree(
            snap.backends.services.adapters.httpd.Httpd.DOCUMENT_ROOT)
        shutil.copytree(os.path.join(test_backup_dir, "conf_d"),
                        snap.backends.services.adapters.httpd.Httpd.CONF_D)
        shutil.copytree(
            os.path.join(test_backup_dir, "doc_root"),
            snap.backends.services.adapters.httpd.Httpd.DOCUMENT_ROOT)
        shutil.rmtree(test_backup_dir)

    @unittest.skipUnless(OS.is_windows(), "only windows support IIS")
    def testIisService(self):
        # backup the iis conf directory and document roots
        test_backup_dir = os.path.join(self.basedir, "snap-iis-test")
        if os.path.isdir(test_backup_dir):
            shutil.rmtree(test_backup_dir)
        shutil.copytree(snap.backends.services.adapters.iis.Iis.CONFIG_ROOT,
                        os.path.join(test_backup_dir, "conf"))

        # run the backup
        test_base_dir = os.path.join(self.basedir, "snap-iis-basedir")
        backend = snap.backends.services.adapters.iis.Iis()
        backend.backup(test_base_dir)

        # ensure conf.d and document root were backed up
        bfiles = []
        for root, dirs, files in os.walk(
                snap.backends.services.adapters.iis.Iis.CONFIG_ROOT):
            for hfile in files:
                rfile = os.path.join(root, hfile)
                ffile = os.path.join(test_base_dir, rfile)
                self.assertTrue(os.path.isfile(ffile))
                bfiles.append(os.path.join(root, hfile))
        self.assertTrue(
            os.path.isfile(os.path.join(test_base_dir, "service-iis.xml")))

        # run the restore
        shutil.rmtree(snap.backends.services.adapters.iis.Iis.CONFIG_ROOT,
                      ignore_errors=True)
        backend.restore(test_base_dir)

        # ensure the files backed up were restored
        for hfile in bfiles:
            self.assertTrue(os.path.isfile(hfile))

        # ensure the features are enabled
        self.assertTrue(
            snap.backends.services.windowsdispatcher.WindowsDispatcher.
            is_feature_enabled(
                snap.backends.services.adapters.iis.Iis.WEBSERVER_FEATURE))

        # restore backup
        shutil.rmtree(snap.backends.services.adapters.iis.Iis.CONFIG_ROOT,
                      ignore_errors=True)
        for root, dirs, files in os.walk(os.path.join(test_backup_dir,
                                                      "conf")):
            for idir in dirs:
                fdir = os.path.join(
                    snap.backends.services.adapters.iis.Iis.CONFIG_ROOT, idir)
                if not os.path.isdir(fdir):
                    os.makedirs(fdir)
            for ifile in files:
                sfile = os.path.join(root, ifile)

                ffile = os.path.join(
                    snap.backends.services.adapters.iis.Iis.CONFIG_ROOT, ifile)
                if not os.path.isfile(ffile):
                    shutil.copy(os.path.join(root, ifile), ffile)
                os.chmod(sfile, stat.S_IWRITE)
                os.remove(sfile)
        for bfile in bfiles:
            fbfile = os.path.join(test_base_dir,
                                  SFile.windows_path_escape(bfile))
            os.chmod(fbfile, stat.S_IWRITE)
            os.remove(fbfile)
        shutil.rmtree(test_backup_dir)