Revision fbeb41e6
b/lib/cmdlib/backup.py | ||
---|---|---|
29 | 29 |
from ganeti import errors |
30 | 30 |
from ganeti import locking |
31 | 31 |
from ganeti import masterd |
32 |
from ganeti import qlang |
|
33 | 32 |
from ganeti import query |
34 | 33 |
from ganeti import utils |
35 | 34 |
|
36 | 35 |
from ganeti.cmdlib.base import QueryBase, NoHooksLU, LogicalUnit |
37 |
from ganeti.cmdlib.common import GetWantedNodes, ShareAll, CheckNodeOnline, \
|
|
36 |
from ganeti.cmdlib.common import CheckNodeOnline, \ |
|
38 | 37 |
ExpandNodeUuidAndName |
39 | 38 |
from ganeti.cmdlib.instance_storage import StartInstanceDisks, \ |
40 | 39 |
ShutdownInstanceDisks |
... | ... | |
49 | 48 |
SORT_FIELD = "node" |
50 | 49 |
|
51 | 50 |
def ExpandNames(self, lu): |
52 |
lu.needed_locks = {} |
|
53 |
|
|
54 |
# The following variables interact with _QueryBase._GetNames |
|
55 |
if self.names: |
|
56 |
(self.wanted, _) = GetWantedNodes(lu, self.names) |
|
57 |
else: |
|
58 |
self.wanted = locking.ALL_SET |
|
59 |
|
|
60 |
self.do_locking = self.use_locking |
|
61 |
|
|
62 |
if self.do_locking: |
|
63 |
lu.share_locks = ShareAll() |
|
64 |
lu.needed_locks = { |
|
65 |
locking.LEVEL_NODE: self.wanted, |
|
66 |
} |
|
67 |
|
|
68 |
if not self.names: |
|
69 |
lu.needed_locks[locking.LEVEL_NODE_ALLOC] = locking.ALL_SET |
|
51 |
raise NotImplementedError |
|
70 | 52 |
|
71 | 53 |
def DeclareLocks(self, lu, level): |
72 | 54 |
pass |
73 | 55 |
|
74 | 56 |
def _GetQueryData(self, lu): |
75 |
"""Computes the list of nodes and their attributes. |
|
76 |
|
|
77 |
""" |
|
78 |
# Locking is not used |
|
79 |
# TODO |
|
80 |
assert not (compat.any(lu.glm.is_owned(level) |
|
81 |
for level in locking.LEVELS |
|
82 |
if level != locking.LEVEL_CLUSTER) or |
|
83 |
self.do_locking or self.use_locking) |
|
84 |
|
|
85 |
node_uuids = self._GetNames(lu, lu.cfg.GetNodeList(), locking.LEVEL_NODE) |
|
86 |
|
|
87 |
result = [] |
|
88 |
for (node_uuid, nres) in lu.rpc.call_export_list(node_uuids).items(): |
|
89 |
node = lu.cfg.GetNodeInfo(node_uuid) |
|
90 |
if nres.fail_msg: |
|
91 |
result.append((node.name, None)) |
|
92 |
else: |
|
93 |
result.extend((node.name, expname) for expname in nres.payload) |
|
94 |
|
|
95 |
return result |
|
57 |
raise NotImplementedError |
|
96 | 58 |
|
97 | 59 |
|
98 | 60 |
class LUBackupQuery(NoHooksLU): |
... | ... | |
102 | 64 |
REQ_BGL = False |
103 | 65 |
|
104 | 66 |
def CheckArguments(self): |
105 |
self.expq = ExportQuery(qlang.MakeSimpleFilter("node", self.op.nodes), |
|
106 |
["node", "export"], self.op.use_locking) |
|
67 |
raise NotImplementedError |
|
107 | 68 |
|
108 | 69 |
def ExpandNames(self): |
109 |
self.expq.ExpandNames(self)
|
|
70 |
raise NotImplementedError
|
|
110 | 71 |
|
111 | 72 |
def DeclareLocks(self, level): |
112 |
self.expq.DeclareLocks(self, level)
|
|
73 |
raise NotImplementedError
|
|
113 | 74 |
|
114 | 75 |
def Exec(self, feedback_fn): |
115 |
result = {} |
|
116 |
|
|
117 |
for (node, expname) in self.expq.OldStyleQuery(self): |
|
118 |
if expname is None: |
|
119 |
result[node] = False |
|
120 |
else: |
|
121 |
result.setdefault(node, []).append(expname) |
|
122 |
|
|
123 |
return result |
|
76 |
raise NotImplementedError |
|
124 | 77 |
|
125 | 78 |
|
126 | 79 |
class LUBackupPrepare(NoHooksLU): |
b/lib/cmdlib/query.py | ||
---|---|---|
24 | 24 |
from ganeti import constants |
25 | 25 |
from ganeti import errors |
26 | 26 |
from ganeti import query |
27 |
from ganeti.cmdlib.backup import ExportQuery |
|
28 | 27 |
from ganeti.cmdlib.base import NoHooksLU |
29 | 28 |
from ganeti.cmdlib.cluster import ClusterQuery |
30 | 29 |
from ganeti.cmdlib.group import GroupQuery |
... | ... | |
40 | 39 |
constants.QR_GROUP: GroupQuery, |
41 | 40 |
constants.QR_OS: OsQuery, |
42 | 41 |
constants.QR_EXTSTORAGE: ExtStorageQuery, |
43 |
constants.QR_EXPORT: ExportQuery, |
|
44 | 42 |
} |
45 | 43 |
|
46 | 44 |
assert set(_QUERY_IMPL.keys()) == constants.QR_VIA_OP |
b/src/Ganeti/Constants.hs | ||
---|---|---|
3340 | 3340 |
qrInstance, |
3341 | 3341 |
qrGroup, |
3342 | 3342 |
qrOs, |
3343 |
qrExport, |
|
3344 | 3343 |
qrExtstorage] |
3345 | 3344 |
|
3346 | 3345 |
-- | List of resources which can be queried using Local UniX Interface |
3347 | 3346 |
qrViaLuxi :: FrozenSet String |
3348 |
qrViaLuxi = ConstantUtils.mkSet [qrLock, qrJob, qrNode, qrNetwork] |
|
3347 |
qrViaLuxi = ConstantUtils.mkSet [qrExport, |
|
3348 |
qrJob, |
|
3349 |
qrLock, |
|
3350 |
qrNetwork, |
|
3351 |
qrNode] |
|
3349 | 3352 |
|
3350 | 3353 |
-- | List of resources which can be queried using RAPI |
3351 | 3354 |
qrViaRapi :: FrozenSet String |
b/test/py/cmdlib/backup_unittest.py | ||
---|---|---|
31 | 31 |
import testutils |
32 | 32 |
|
33 | 33 |
|
34 |
class TestLUBackupQuery(CmdlibTestCase): |
|
35 |
def setUp(self): |
|
36 |
super(TestLUBackupQuery, self).setUp() |
|
37 |
|
|
38 |
self.fields = query._BuildExportFields().keys() |
|
39 |
|
|
40 |
def testFailingExportList(self): |
|
41 |
self.rpc.call_export_list.return_value = \ |
|
42 |
self.RpcResultsBuilder() \ |
|
43 |
.AddFailedNode(self.master) \ |
|
44 |
.Build() |
|
45 |
op = opcodes.OpBackupQuery(nodes=[self.master.name]) |
|
46 |
ret = self.ExecOpCode(op) |
|
47 |
self.assertEqual({self.master.name: False}, ret) |
|
48 |
|
|
49 |
def testQueryOneNode(self): |
|
50 |
self.rpc.call_export_list.return_value = \ |
|
51 |
self.RpcResultsBuilder() \ |
|
52 |
.AddSuccessfulNode(self.master, |
|
53 |
["mock_export1", "mock_export2"]) \ |
|
54 |
.Build() |
|
55 |
op = opcodes.OpBackupQuery(nodes=[self.master.name]) |
|
56 |
ret = self.ExecOpCode(op) |
|
57 |
self.assertEqual({self.master.name: ["mock_export1", "mock_export2"]}, ret) |
|
58 |
|
|
59 |
def testQueryAllNodes(self): |
|
60 |
node = self.cfg.AddNewNode() |
|
61 |
self.rpc.call_export_list.return_value = \ |
|
62 |
self.RpcResultsBuilder() \ |
|
63 |
.AddSuccessfulNode(self.master, ["mock_export1"]) \ |
|
64 |
.AddSuccessfulNode(node, ["mock_export2"]) \ |
|
65 |
.Build() |
|
66 |
op = opcodes.OpBackupQuery() |
|
67 |
ret = self.ExecOpCode(op) |
|
68 |
self.assertEqual({ |
|
69 |
self.master.name: ["mock_export1"], |
|
70 |
node.name: ["mock_export2"] |
|
71 |
}, ret) |
|
72 |
|
|
73 |
|
|
74 | 34 |
class TestLUBackupPrepare(CmdlibTestCase): |
75 | 35 |
@patchUtils("instance_utils") |
76 | 36 |
def testPrepareLocalExport(self, utils): |
Also available in: Unified diff