diff --git a/daemons/ganeti-noded b/daemons/ganeti-noded index 28c6edaadc130afb9040cda3670a4461b6808d2d..fe6a0df8366fbbd369ff3f88c760a1c04227c8fe 100755 --- a/daemons/ganeti-noded +++ b/daemons/ganeti-noded @@ -890,6 +890,13 @@ class NodeHttpServer(http.server.HttpServer): """ return backend.GetImportExportStatus(params[0]) + @staticmethod + def perspective_impexp_abort(params): + """Aborts an import or export. + + """ + return backend.AbortImportExport(params[0]) + @staticmethod def perspective_impexp_cleanup(params): """Cleans up after an import or export. diff --git a/lib/backend.py b/lib/backend.py index 69ac800c968ccd860ac442b78e742db32710ea21..897b557cb47affb7ad8eac435c03ee7be180d39b 100644 --- a/lib/backend.py +++ b/lib/backend.py @@ -47,6 +47,7 @@ import logging import tempfile import zlib import base64 +import signal from ganeti import errors from ganeti import utils @@ -2845,6 +2846,21 @@ def GetImportExportStatus(names): return result +def AbortImportExport(name): + """Sends SIGTERM to a running import/export daemon. + + """ + logging.info("Abort import/export %s", name) + + status_dir = utils.PathJoin(constants.IMPORT_EXPORT_DIR, name) + pid = utils.ReadLockedPidFile(utils.PathJoin(status_dir, _IES_PID_FILE)) + + if pid: + logging.info("Import/export %s is running with PID %s, sending SIGTERM", + name, pid) + os.kill(pid, signal.SIGTERM) + + def CleanupImportExport(name): """Cleanup after an import or export. diff --git a/lib/rpc.py b/lib/rpc.py index 23df3ec3f6762fa615160afc88b9a691137dee74..b7fff3d336077c9b52d0f65049a0f1a336007176 100644 --- a/lib/rpc.py +++ b/lib/rpc.py @@ -1288,6 +1288,19 @@ class RpcRunner(object): return result + def call_impexp_abort(self, node, name): + """Aborts an import or export. + + This is a single-node call. + + @type node: string + @param node: Node name + @type name: string + @param name: Import/export name + + """ + return self._SingleNodeCall(node, "impexp_abort", [name]) + def call_impexp_cleanup(self, node, name): """Cleans up after an import or export.