def RunWatcherHooks(): """Run the watcher hooks. """ hooks_dir = utils.PathJoin(pathutils.HOOKS_BASE_DIR, constants.HOOKS_NAME_WATCHER) if not os.path.isdir(hooks_dir): return try: results = utils.RunParts(hooks_dir) except Exception as err: # pylint: disable=W0703 logging.exception("RunParts %s failed: %s", hooks_dir, err) return for (relname, status, runresult) in results: if status == constants.RUNPARTS_SKIP: logging.debug("Watcher hook %s: skipped", relname) elif status == constants.RUNPARTS_ERR: logging.warning("Watcher hook %s: error (%s)", relname, runresult) elif status == constants.RUNPARTS_RUN: if runresult.failed: logging.warning( "Watcher hook %s: failed (exit: %d) (output: %s)", relname, runresult.exit_code, runresult.output) else: logging.debug("Watcher hook %s: success (output: %s)", relname, runresult.output) else: raise errors.ProgrammerError( "Unknown status %s returned by RunParts", status)
def testSingleLine(self): testfile = utils.PathJoin(self.tmpdir, "data") for nl in range(0, 10): utils.WriteFile(testfile, data="Hello World" + ("\n" * nl)) self.assertEqual(ssconf.ReadSsconfFile(testfile), "Hello World")
def testLargeFile(self): testfile = utils.PathJoin(self.tmpdir, "data") for size in [ssconf._MAX_SIZE + 1, ssconf._MAX_SIZE * 2]: utils.WriteFile(testfile, data="A" * size) self.assertTrue(os.path.getsize(testfile) > ssconf._MAX_SIZE) self.assertRaises(RuntimeError, ssconf.ReadSsconfFile, testfile)
def _MigrateInstanceCmd(self, cluster_name, instance_name, target, port, live, fail, cmd): if cmd == [self.CMD, "list"]: output = testutils.ReadTestData( "xen-xm-list-4.0.1-four-instances.txt") elif cmd[:2] == [self.CMD, "migrate"]: if self.CMD == constants.XEN_CMD_XM: args = ["-p", str(port)] if live: args.append("-l") elif self.CMD == constants.XEN_CMD_XL: args = [ "-s", constants.XL_SSH_CMD % cluster_name, "-C", utils.PathJoin(self.tmpdir, instance_name), ] else: self.fail("Unknown Xen command '%s'" % self.CMD) args.extend([instance_name, target]) self.assertEqual(cmd[2:], args) if fail: return self._FailingCommand(cmd) output = "" else: self.fail("Unhandled command: %s" % (cmd, )) return self._SuccessCommand(output, cmd)
def testMatchingName(self): tmpfile = utils.PathJoin(self.tmpdir, "ssconf_cluster_name") for content in ["cluster.example.com", "cluster.example.com\n\n"]: utils.WriteFile(tmpfile, data=content) ssconf.VerifyClusterName("cluster.example.com", _cfg_location=self.tmpdir)
def testStartInstance(self): (inst, disks) = self._MakeInstance() pathutils.LOG_XEN_DIR = self.tmpdir for failcreate in [False, True]: for paused in [False, True]: run_cmd = compat.partial(self._StartInstanceCommand, inst, paused, failcreate) hv = self._GetHv(run_cmd=run_cmd) # Ensure instance is not listed self.assertTrue(inst.name not in hv.ListInstances()) # Remove configuration cfgfile = utils.PathJoin(self.tmpdir, inst.name) utils.RemoveFile(cfgfile) if failcreate: self.assertRaises(errors.HypervisorError, hv.StartInstance, inst, disks, paused) # Check whether a stale config file is left behind self.assertFalse(os.path.exists(cfgfile)) else: hv.StartInstance(inst, disks, paused) # Check if configuration was updated lines = utils.ReadFile(cfgfile).splitlines() if constants.HV_VNC_PASSWORD_FILE in inst.hvparams: self.assertTrue(("vncpasswd = '%s'" % self.vncpw) in lines) else: extra = inst.hvparams[constants.HV_KERNEL_ARGS] self.assertTrue(("extra = '%s'" % extra) in lines)
def testMissingFile(self): cert_path = testutils.TestDataFilename("cert1.pem") nodecert = utils.PathJoin(self.tmpdir, "does-not-exist") utils.CheckNodeCertificate(NotImplemented, _noded_cert_file=nodecert) self.assertFalse(os.path.exists(nodecert))
def Create(self, max_connections=1): """ Creates a bound and ready socket, cleaning up in case of failure. @type max_connections: int @param max_connections: The number of max connections allowed for the socket. @rtype: tuple of socket, string @return: The socket object and the path to reach it with. """ # Using a temporary directory as there's no easy way to create temporary # sockets without writing a custom loop around tempfile.mktemp and # socket.bind self.tmpdir = tempfile.mkdtemp() try: tmpsock = utils.PathJoin(self.tmpdir, "sock") logging.debug("Creating temporary socket at %s", tmpsock) self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) try: self.sock.bind(tmpsock) self.sock.listen(max_connections) except: self.sock.close() raise except: shutil.rmtree(self.tmpdir) raise return self.sock, tmpsock
def testRemovingAutoConfigFile(self): name = "inst8206.example.com" cfgfile = utils.PathJoin(self.tmpdir, name) autodir = utils.PathJoin(self.tmpdir, "auto") autocfgfile = utils.PathJoin(autodir, name) os.mkdir(autodir) utils.WriteFile(autocfgfile, data="") hv = self._GetHv() self.assertTrue(os.path.isfile(autocfgfile)) hv._WriteConfigFile(name, "content") self.assertFalse(os.path.exists(autocfgfile)) self.assertEqual(utils.ReadFile(cfgfile), "content")
def fn(args, env=NotImplemented, reset_env=NotImplemented, postfork_fn=NotImplemented): self.assertEqual(args, [utils.PathJoin(self.tmpdir, "test3079")]) self.assertEqual(env, {}) self.assertTrue(reset_env) self.assertTrue(callable(postfork_fn)) trylock = utils.FileLock.Open(lockfile) try: # See if lockfile is still held self.assertRaises(EnvironmentError, trylock.Exclusive, blocking=False) # Call back to release lock postfork_fn(NotImplemented) # See if lockfile can be acquired trylock.Exclusive(blocking=False) finally: trylock.Close() # Simulate a failed command return utils.RunResult(constants.EXIT_FAILURE, None, "stdout", "stderr406328567", utils.ShellQuoteArgs(args), NotImplemented, NotImplemented)
def testRunCmdSucceeds(self): lockfile = utils.PathJoin(self.tmpdir, "lock") def fn(args, env=NotImplemented, reset_env=NotImplemented, postfork_fn=NotImplemented): self.assertEqual(args, [utils.PathJoin(self.tmpdir, "test5667")]) self.assertEqual(env, {}) self.assertTrue(reset_env) # Call back to release lock postfork_fn(NotImplemented) # Simulate a successful command return utils.RunResult(constants.EXIT_SUCCESS, None, "stdout14463", "", utils.ShellQuoteArgs(args), NotImplemented, NotImplemented) sleep_fn = testutils.CallCounter(_SleepForRestrictedCmd) prepare_fn = testutils.CallCounter(self._SuccessfulPrepare) runcmd_fn = testutils.CallCounter(fn) result = backend.RunRestrictedCmd("test5667", _lock_timeout=1.0, _lock_file=lockfile, _path=self.tmpdir, _runcmd_fn=runcmd_fn, _sleep_fn=sleep_fn, _prepare_fn=prepare_fn, _enabled=True) self.assertEqual(result, "stdout14463") self.assertEqual(sleep_fn.Count(), 0) self.assertEqual(prepare_fn.Count(), 1) self.assertEqual(runcmd_fn.Count(), 1)
def testCanNotStat(self): tmpname = utils.PathJoin(self.tmpdir, "foobar") self.assertFalse(os.path.exists(tmpname)) (status, msg) = \ backend._VerifyRestrictedCmdDirectory(tmpname, _owner=NotImplemented) self.assertFalse(status) self.assertTrue(msg.startswith("Can't stat(2) '"))
def _CheckExtStorageFile(base_dir, filename, required): """Check prereqs for an ExtStorage file. Check if file exists, if it is a regular file and in case it is one of extstorage scripts if it is executable. @type base_dir: string @param base_dir: Base directory containing ExtStorage installations. @type filename: string @param filename: The basename of the ExtStorage file. @type required: bool @param required: Whether the file is required or not. @rtype: String @return: The file path if the file is found and is valid, None if the file is not found and not required. @raises BlockDeviceError: In case prereqs are not met (found and not valid/executable, not found and required) """ file_path = utils.PathJoin(base_dir, filename) try: st = os.stat(file_path) except EnvironmentError, err: if not required: logging.info("Optional file '%s' under path '%s' is missing", filename, base_dir) return None base.ThrowError("File '%s' under path '%s' is missing (%s)" % (filename, base_dir, utils.ErrnoOrStr(err)))
def GetAllInstancesInfo(self, hvparams=None): """Get properties of all instances. @type hvparams: dict of strings @param hvparams: hypervisor parameter @return: list of tuples (name, id, memory, vcpus, stat, times) """ data = [] for file_name in os.listdir(self._ROOT_DIR): try: fh = open(utils.PathJoin(self._ROOT_DIR, file_name), "r") inst_id = "-1" memory = 0 vcpus = 1 stat = hv_base.HvInstanceState.SHUTDOWN times = -1 try: inst_id = fh.readline().strip() memory = utils.TryConvert(int, fh.readline().strip()) vcpus = utils.TryConvert(int, fh.readline().strip()) stat = hv_base.HvInstanceState.RUNNING times = 0 finally: fh.close() data.append((file_name, inst_id, memory, vcpus, stat, times)) except IOError as err: raise errors.HypervisorError("Failed to list instances: %s" % err) return data
def testFileNotExecutable(self): fname = utils.PathJoin(self.tmpdir, "file") utils.WriteFile(fname, data="#!/bin/bash", mode=0o600) assert os.path.exists(fname) self.assertFalse(utils.IsExecutable(fname)) self.assertFalse(self._TestSymlink(fname))
def testStopInstance(self): name = "inst4284.example.com" cfgfile = utils.PathJoin(self.tmpdir, name) cfgdata = "config file content\n" for force in [False, True]: for fail in [False, True]: utils.WriteFile(cfgfile, data=cfgdata) run_cmd = compat.partial(self._StopInstanceCommand, name, force, fail) hv = self._GetHv(run_cmd=run_cmd) self.assertTrue(os.path.isfile(cfgfile)) if fail: try: hv._StopInstance(name, force, None, constants.DEFAULT_SHUTDOWN_TIMEOUT) except errors.HypervisorError, err: self.assertTrue( str(err).startswith("listing instances failed"), msg=str(err)) else: self.fail("Exception was not raised") self.assertEqual( utils.ReadFile(cfgfile), cfgdata, msg=("Configuration was removed when stopping" " instance failed")) else: hv._StopInstance(name, force, None, constants.DEFAULT_SHUTDOWN_TIMEOUT) self.assertFalse(os.path.exists(cfgfile))
def _MountCgroupSubsystem(cls, subsystem): """Mount the cgroup subsystem fs under the cgroup root dir. @type subsystem: string @param subsystem: cgroup subsystem name to mount @rtype string @return path of subsystem mount point """ subsys_dir = utils.PathJoin(cls._GetCgroupMountPoint(), subsystem) if not os.path.isdir(subsys_dir): try: os.makedirs(subsys_dir) except EnvironmentError as err: raise HypervisorError("Failed to create directory %s: %s" % (subsys_dir, err)) mount_cmd = [ "mount", "-t", "cgroup", "-o", subsystem, subsystem, subsys_dir ] result = utils.RunCmd(mount_cmd) if result.failed: raise HypervisorError("Failed to mount cgroup subsystem '%s': %s" % (subsystem, result.output)) return subsys_dir
def testMismatchInNodeCert(self): cert1_path = testutils.TestDataFilename("cert1.pem") cert2_path = testutils.TestDataFilename("cert2.pem") tmpfile = utils.PathJoin(self.tmpdir, "cert") # Extract certificate cert1 = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, utils.ReadFile(cert1_path)) cert1_pem = OpenSSL.crypto.dump_certificate( OpenSSL.crypto.FILETYPE_PEM, cert1) # Extract mismatching key key2 = OpenSSL.crypto.load_privatekey(OpenSSL.crypto.FILETYPE_PEM, utils.ReadFile(cert2_path)) key2_pem = OpenSSL.crypto.dump_privatekey(OpenSSL.crypto.FILETYPE_PEM, key2) # Write to file utils.WriteFile(tmpfile, data=cert1_pem + key2_pem) try: utils.CheckNodeCertificate(cert1, _noded_cert_file=tmpfile) except errors.X509CertError, err: self.assertEqual( err.args, (tmpfile, "Certificate does not match with private key"))
def testBackup(self): self.tmpdir = tempfile.mkdtemp() testfile = utils.PathJoin(self.tmpdir, "test") self.assertEqual(utils.WriteFile(testfile, data="foo", backup=True), None) self.assertEqual(utils.ReadFile(testfile), "foo") self.assertEqual(os.listdir(self.tmpdir), ["test"]) # Write again assert os.path.isfile(testfile) self.assertEqual(utils.WriteFile(testfile, data="bar", backup=True), None) self.assertEqual(utils.ReadFile(testfile), "bar") self.assertEqual(len(glob.glob("%s.backup*" % testfile)), 1) self.assertTrue("test" in os.listdir(self.tmpdir)) self.assertEqual(len(os.listdir(self.tmpdir)), 2) # Write again as dry-run assert os.path.isfile(testfile) self.assertEqual( utils.WriteFile(testfile, data="000", backup=True, dry_run=True), None) self.assertEqual(utils.ReadFile(testfile), "bar") self.assertEqual(len(glob.glob("%s.backup*" % testfile)), 1) self.assertTrue("test" in os.listdir(self.tmpdir)) self.assertEqual(len(os.listdir(self.tmpdir)), 2)
def GetUserFiles(user, mkdir=False, dircheck=True, kind=constants.SSHK_DSA, _homedir_fn=None): """Return the paths of a user's SSH files. @type user: string @param user: Username @type mkdir: bool @param mkdir: Whether to create ".ssh" directory if it doesn't exist @type dircheck: bool @param dircheck: Whether to check if ".ssh" directory exists @type kind: string @param kind: One of L{constants.SSHK_ALL} @rtype: tuple; (string, string, string) @return: Tuple containing three file system paths; the private SSH key file, the public SSH key file and the user's C{authorized_keys} file @raise errors.OpExecError: When home directory of the user can not be determined @raise errors.OpExecError: Regardless of the C{mkdir} parameters, this exception is raised if C{~$user/.ssh} is not a directory and C{dircheck} is set to C{True} """ if _homedir_fn is None: _homedir_fn = utils.GetHomeDir user_dir = _homedir_fn(user) if not user_dir: raise errors.OpExecError("Cannot resolve home of user '%s'" % user) if kind == constants.SSHK_DSA: suffix = "dsa" elif kind == constants.SSHK_RSA: suffix = "rsa" elif kind == constants.SSHK_ECDSA: suffix = "ecdsa" else: raise errors.ProgrammerError("Unknown SSH key kind '%s'" % kind) ssh_dir = utils.PathJoin(user_dir, ".ssh") if mkdir: utils.EnsureDirs([(ssh_dir, constants.SECURE_DIR_MODE)]) elif dircheck and not os.path.isdir(ssh_dir): raise errors.OpExecError("Path %s is not a directory" % ssh_dir) return [utils.PathJoin(ssh_dir, base) for base in ["id_%s" % suffix, "id_%s.pub" % suffix, "authorized_keys"]]
def LocalExport(self, dest_node, compress): """Intra-cluster instance export. @type dest_node: L{objects.Node} @param dest_node: Destination node @type compress: string @param compress: Compression tool to use """ instance = self._instance src_node_uuid = instance.primary_node assert len(self._snap_disks) == len(instance.disks) transfers = [] for idx, dev in enumerate(self._snap_disks): if not dev: transfers.append(None) continue path = utils.PathJoin(pathutils.EXPORT_DIR, "%s.new" % instance.name, dev.logical_id[1]) finished_fn = compat.partial(self._TransferFinished, idx) if instance.os: src_io = constants.IEIO_SCRIPT src_ioargs = ((dev, instance), idx) else: src_io = constants.IEIO_RAW_DISK src_ioargs = (dev, instance) # FIXME: pass debug option from opcode to backend dt = DiskTransfer("snapshot/%s" % idx, src_io, src_ioargs, constants.IEIO_FILE, (path, ), finished_fn) transfers.append(dt) # Actually export data dresults = TransferInstanceData(self._lu, self._feedback_fn, src_node_uuid, dest_node.uuid, dest_node.secondary_ip, compress, instance, transfers) assert len(dresults) == len(instance.disks) self._feedback_fn("Finalizing export on %s" % dest_node.name) result = self._lu.rpc.call_finalize_export(dest_node.uuid, instance, self._snap_disks) msg = result.fail_msg fin_resu = not msg if msg: self._lu.LogWarning("Could not finalize export for instance %s" " on node %s: %s", instance.name, dest_node.name, msg) return (fin_resu, dresults)
def testFailRename(self): self.tmpdir = tempfile.mkdtemp() target = utils.PathJoin(self.tmpdir, "target") os.mkdir(target) self.assertRaises(OSError, utils.WriteFile, target, data="abc") self.assertTrue(os.path.isdir(target)) self.assertEqual(os.listdir(self.tmpdir), ["target"]) self.assertFalse(os.listdir(target))
def testNewFileMode(self): self.tmpdir = tempfile.mkdtemp() target = utils.PathJoin(self.tmpdir, "target") utils.WriteFile(target, data="data", mode=0400, keep_perms=utils.KP_IF_EXISTS) self.assertFileMode(target, 0400)
def testFailRenameDryRun(self): self.tmpdir = tempfile.mkdtemp() target = utils.PathJoin(self.tmpdir, "target") os.mkdir(target) self.assertEqual(utils.WriteFile(target, data="abc", dry_run=True), None) self.assertTrue(os.path.isdir(target)) self.assertEqual(os.listdir(self.tmpdir), ["target"]) self.assertFalse(os.listdir(target))
def setUp(self): self.tmpdir = tempfile.mkdtemp() self.sockpath = utils.PathJoin(self.tmpdir, "sock") self.listener = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) self.listener.settimeout(10) self.listener.bind(self.sockpath) self.listener.listen(1)
def ListInstances(self, hvparams=None): """Get the list of running instances. """ return [ name for name in os.listdir(self._ROOT_DIR) if self._IsDirLive(utils.PathJoin(self._ROOT_DIR, name)) ]
def _InstanceLogFilePath(cls, instance): """Return the log file for an instance. @type instance: L{objects.Instance} """ filename = "%s.%s.log" % (instance.name, instance.uuid) return utils.PathJoin(cls._LOG_DIR, filename)
def setUp(self): # Since we are comparing large dictionaries here, this is vital to getting # useful feedback about differences in config content using assertEquals. self.maxDiff = None self.tmpdir = tempfile.mkdtemp() self.config_path = utils.PathJoin(self.tmpdir, "config.data") self.noded_cert_path = utils.PathJoin(self.tmpdir, "server.pem") self.rapi_cert_path = utils.PathJoin(self.tmpdir, "rapi.pem") self.rapi_users_path = utils.PathJoin(self.tmpdir, "rapi", "users") self.rapi_users_path_pre24 = utils.PathJoin(self.tmpdir, "rapi_users") self.known_hosts_path = utils.PathJoin(self.tmpdir, "known_hosts") self.confd_hmac_path = utils.PathJoin(self.tmpdir, "hmac.key") self.cds_path = utils.PathJoin(self.tmpdir, "cluster-domain-secret") self.ss_master_node_path = utils.PathJoin(self.tmpdir, "ssconf_master_node") self.file_storage_paths = utils.PathJoin(self.tmpdir, "file-storage-paths")
def _InstanceStashFilePath(cls, instance_name): """Return the stash file path for an instance. The stash file is used to keep information needed to clean up after the destruction of the instance. """ return utils.PathJoin(cls._InstanceDir(instance_name), "stash")
def testInvalidCertificate(self): tmpfile = utils.PathJoin(self.tmpdir, "cert") utils.WriteFile(tmpfile, data="not a certificate") self.assertRaises(errors.X509CertError, utils.CheckNodeCertificate, NotImplemented, _noded_cert_file=tmpfile)