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 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 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
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
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 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 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 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 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 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( )
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)
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()
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)
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)
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)