diff --git a/lib/cmdlib.py b/lib/cmdlib.py index 73907c284abbb93a57f46cabd0d4df3b907fc95b..cdac3d0ed0be8e0ed6f382efb803c42ccc5420db 100644 --- a/lib/cmdlib.py +++ b/lib/cmdlib.py @@ -4436,7 +4436,7 @@ class LUExportInstance(LogicalUnit): def CheckPrereq(self): """Check prerequisites. - This checks that the instance name is a valid one. + This checks that the instance and node names are valid. """ instance_name = self.cfg.ExpandInstanceName(self.op.instance_name) @@ -4523,6 +4523,45 @@ class LUExportInstance(LogicalUnit): " on node %s" % (instance.name, node)) +class LURemoveExport(NoHooksLU): + """Remove exports related to the named instance. + + """ + _OP_REQP = ["instance_name"] + + def CheckPrereq(self): + """Check prerequisites. + """ + pass + + def Exec(self, feedback_fn): + """Remove any export. + + """ + instance_name = self.cfg.ExpandInstanceName(self.op.instance_name) + # If the instance was not found we'll try with the name that was passed in. + # This will only work if it was an FQDN, though. + fqdn_warn = False + if not instance_name: + fqdn_warn = True + instance_name = self.op.instance_name + + op = opcodes.OpQueryExports(nodes=[]) + exportlist = self.proc.ChainOpCode(op) + found = False + for node in exportlist: + if instance_name in exportlist[node]: + found = True + if not rpc.call_export_remove(node, instance_name): + logger.Error("could not remove export for instance %s" + " on node %s" % (instance_name, node)) + + if fqdn_warn and not found: + feedback_fn("Export not found. If trying to remove an export belonging" + " to a deleted instance please use its Fully Qualified" + " Domain Name.") + + class TagsLU(NoHooksLU): """Generic tags LU. diff --git a/lib/mcpu.py b/lib/mcpu.py index 99cd737f026a48336073b2cd065010979eb8e9e3..8ae71962b4ae2d7c2264bd177378a5e3788b6e97 100644 --- a/lib/mcpu.py +++ b/lib/mcpu.py @@ -80,6 +80,7 @@ class Processor(object): # exports lu opcodes.OpQueryExports: cmdlib.LUQueryExports, opcodes.OpExportInstance: cmdlib.LUExportInstance, + opcodes.OpRemoveExport: cmdlib.LURemoveExport, # tags lu opcodes.OpGetTags: cmdlib.LUGetTags, opcodes.OpSearchTags: cmdlib.LUSearchTags, diff --git a/lib/opcodes.py b/lib/opcodes.py index c629e0c91a43ad4e781eabbc3cc2afaf11c0a98e..289d971b16d0ed82b024ea5b9e86f23be5c8d6fe 100644 --- a/lib/opcodes.py +++ b/lib/opcodes.py @@ -395,6 +395,10 @@ class OpExportInstance(OpCode): OP_ID = "OP_BACKUP_EXPORT" __slots__ = ["instance_name", "target_node", "shutdown"] +class OpRemoveExport(OpCode): + """Remove an instance's export.""" + OP_ID = "OP_BACKUP_REMOVE" + __slots__ = ["instance_name"] # Tags opcodes class OpGetTags(OpCode): diff --git a/scripts/gnt-backup b/scripts/gnt-backup index c250e250d9626abfeed5273b2c1352215f03de90..538b9eca632a7a35599ef9bb3870dd753bfbf30c 100755 --- a/scripts/gnt-backup +++ b/scripts/gnt-backup @@ -105,6 +105,25 @@ def ImportInstance(opts, args): return 0 +def RemoveExport(opts, args): + """Remove an export from the cluster. + + Args: + opts - class with options as members + args - list with a single element, the exported instance to remove + Opts used: + + Returns: + 1 in case of error, 0 otherwise + + """ + instance = args[0] + op = opcodes.OpRemoveExport(instance_name=args[0]) + + SubmitOpCode(op) + return 0 + + # this is defined separately due to readability only import_opts = [ DEBUG_OPT, @@ -162,6 +181,10 @@ commands = { "Exports an instance to an image"), 'import': (ImportInstance, ARGS_ONE, import_opts, "[opts...] <name>", "Imports an instance from an exported image"), + 'remove': (RemoveExport, ARGS_ONE, + [DEBUG_OPT], + "<name>", + "Remove exports of named instance from the filesystem."), } if __name__ == '__main__':