root / test / py / cmdlib / backup_unittest.py @ 560ef132
History | View | Annotate | Download (6.3 kB)
1 | a80e802a | Thomas Thrainer | #!/usr/bin/python
|
---|---|---|---|
2 | a80e802a | Thomas Thrainer | #
|
3 | a80e802a | Thomas Thrainer | |
4 | a80e802a | Thomas Thrainer | # Copyright (C) 2013 Google Inc.
|
5 | a80e802a | Thomas Thrainer | #
|
6 | a80e802a | Thomas Thrainer | # This program is free software; you can redistribute it and/or modify
|
7 | a80e802a | Thomas Thrainer | # it under the terms of the GNU General Public License as published by
|
8 | a80e802a | Thomas Thrainer | # the Free Software Foundation; either version 2 of the License, or
|
9 | a80e802a | Thomas Thrainer | # (at your option) any later version.
|
10 | a80e802a | Thomas Thrainer | #
|
11 | a80e802a | Thomas Thrainer | # This program is distributed in the hope that it will be useful, but
|
12 | a80e802a | Thomas Thrainer | # WITHOUT ANY WARRANTY; without even the implied warranty of
|
13 | a80e802a | Thomas Thrainer | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
14 | a80e802a | Thomas Thrainer | # General Public License for more details.
|
15 | a80e802a | Thomas Thrainer | #
|
16 | a80e802a | Thomas Thrainer | # You should have received a copy of the GNU General Public License
|
17 | a80e802a | Thomas Thrainer | # along with this program; if not, write to the Free Software
|
18 | a80e802a | Thomas Thrainer | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
19 | a80e802a | Thomas Thrainer | # 02110-1301, USA.
|
20 | a80e802a | Thomas Thrainer | |
21 | a80e802a | Thomas Thrainer | |
22 | a80e802a | Thomas Thrainer | """Tests for LUBackup*"""
|
23 | a80e802a | Thomas Thrainer | |
24 | a80e802a | Thomas Thrainer | from ganeti import constants |
25 | 70b634e6 | Thomas Thrainer | from ganeti import objects |
26 | a80e802a | Thomas Thrainer | from ganeti import opcodes |
27 | a80e802a | Thomas Thrainer | from ganeti import query |
28 | a80e802a | Thomas Thrainer | |
29 | a80e802a | Thomas Thrainer | from testsupport import * |
30 | a80e802a | Thomas Thrainer | |
31 | a80e802a | Thomas Thrainer | import testutils |
32 | a80e802a | Thomas Thrainer | |
33 | a80e802a | Thomas Thrainer | |
34 | 3388debb | Thomas Thrainer | class TestLUBackupPrepare(CmdlibTestCase): |
35 | 3388debb | Thomas Thrainer | @patchUtils("instance_utils") |
36 | 3388debb | Thomas Thrainer | def testPrepareLocalExport(self, utils): |
37 | 3388debb | Thomas Thrainer | utils.ReadOneLineFile.return_value = "cluster_secret"
|
38 | 3388debb | Thomas Thrainer | inst = self.cfg.AddNewInstance()
|
39 | 3388debb | Thomas Thrainer | op = opcodes.OpBackupPrepare(instance_name=inst.name, |
40 | 3388debb | Thomas Thrainer | mode=constants.EXPORT_MODE_LOCAL) |
41 | 3388debb | Thomas Thrainer | self.ExecOpCode(op)
|
42 | 3388debb | Thomas Thrainer | |
43 | 3388debb | Thomas Thrainer | @patchUtils("instance_utils") |
44 | 3388debb | Thomas Thrainer | def testPrepareRemoteExport(self, utils): |
45 | 3388debb | Thomas Thrainer | utils.ReadOneLineFile.return_value = "cluster_secret"
|
46 | 3388debb | Thomas Thrainer | inst = self.cfg.AddNewInstance()
|
47 | 3388debb | Thomas Thrainer | self.rpc.call_x509_cert_create.return_value = \
|
48 | 3388debb | Thomas Thrainer | self.RpcResultsBuilder() \
|
49 | 3388debb | Thomas Thrainer | .CreateSuccessfulNodeResult(inst.primary_node, |
50 | 3388debb | Thomas Thrainer | ("key_name",
|
51 | 3388debb | Thomas Thrainer | testutils.ReadTestData("cert1.pem")))
|
52 | 3388debb | Thomas Thrainer | op = opcodes.OpBackupPrepare(instance_name=inst.name, |
53 | 3388debb | Thomas Thrainer | mode=constants.EXPORT_MODE_REMOTE) |
54 | 3388debb | Thomas Thrainer | self.ExecOpCode(op)
|
55 | 3388debb | Thomas Thrainer | |
56 | 3388debb | Thomas Thrainer | |
57 | 70b634e6 | Thomas Thrainer | class TestLUBackupExportBase(CmdlibTestCase): |
58 | 70b634e6 | Thomas Thrainer | def setUp(self): |
59 | 70b634e6 | Thomas Thrainer | super(TestLUBackupExportBase, self).setUp() |
60 | 70b634e6 | Thomas Thrainer | |
61 | 70b634e6 | Thomas Thrainer | self.rpc.call_instance_start.return_value = \
|
62 | 70b634e6 | Thomas Thrainer | self.RpcResultsBuilder() \
|
63 | 70b634e6 | Thomas Thrainer | .CreateSuccessfulNodeResult(self.master, True) |
64 | 70b634e6 | Thomas Thrainer | |
65 | 70b634e6 | Thomas Thrainer | self.rpc.call_blockdev_assemble.return_value = \
|
66 | 70b634e6 | Thomas Thrainer | self.RpcResultsBuilder() \
|
67 | ba924970 | Dimitris Aragiorgis | .CreateSuccessfulNodeResult(self.master, ("/dev/mock_path", |
68 | ba924970 | Dimitris Aragiorgis | "/dev/mock_link_name"))
|
69 | 70b634e6 | Thomas Thrainer | |
70 | 70b634e6 | Thomas Thrainer | self.rpc.call_blockdev_shutdown.return_value = \
|
71 | 70b634e6 | Thomas Thrainer | self.RpcResultsBuilder() \
|
72 | 70b634e6 | Thomas Thrainer | .CreateSuccessfulNodeResult(self.master, None) |
73 | 70b634e6 | Thomas Thrainer | |
74 | 70b634e6 | Thomas Thrainer | self.rpc.call_blockdev_snapshot.return_value = \
|
75 | 70b634e6 | Thomas Thrainer | self.RpcResultsBuilder() \
|
76 | 70b634e6 | Thomas Thrainer | .CreateSuccessfulNodeResult(self.master, ("mock_vg", "mock_id")) |
77 | 70b634e6 | Thomas Thrainer | |
78 | 70b634e6 | Thomas Thrainer | self.rpc.call_blockdev_remove.return_value = \
|
79 | 70b634e6 | Thomas Thrainer | self.RpcResultsBuilder() \
|
80 | 70b634e6 | Thomas Thrainer | .CreateSuccessfulNodeResult(self.master, None) |
81 | 70b634e6 | Thomas Thrainer | |
82 | 70b634e6 | Thomas Thrainer | self.rpc.call_export_start.return_value = \
|
83 | 70b634e6 | Thomas Thrainer | self.RpcResultsBuilder() \
|
84 | 70b634e6 | Thomas Thrainer | .CreateSuccessfulNodeResult(self.master, "export_daemon") |
85 | 70b634e6 | Thomas Thrainer | |
86 | 70b634e6 | Thomas Thrainer | def ImpExpStatus(node_uuid, name): |
87 | 70b634e6 | Thomas Thrainer | return self.RpcResultsBuilder() \ |
88 | 70b634e6 | Thomas Thrainer | .CreateSuccessfulNodeResult(node_uuid, |
89 | 70b634e6 | Thomas Thrainer | [objects.ImportExportStatus( |
90 | 70b634e6 | Thomas Thrainer | exit_status=0
|
91 | 70b634e6 | Thomas Thrainer | )]) |
92 | 70b634e6 | Thomas Thrainer | self.rpc.call_impexp_status.side_effect = ImpExpStatus
|
93 | 70b634e6 | Thomas Thrainer | |
94 | 70b634e6 | Thomas Thrainer | def ImpExpCleanup(node_uuid, name): |
95 | 70b634e6 | Thomas Thrainer | return self.RpcResultsBuilder() \ |
96 | 70b634e6 | Thomas Thrainer | .CreateSuccessfulNodeResult(node_uuid) |
97 | 70b634e6 | Thomas Thrainer | self.rpc.call_impexp_cleanup.side_effect = ImpExpCleanup
|
98 | 70b634e6 | Thomas Thrainer | |
99 | 70b634e6 | Thomas Thrainer | self.rpc.call_finalize_export.return_value = \
|
100 | 70b634e6 | Thomas Thrainer | self.RpcResultsBuilder() \
|
101 | 70b634e6 | Thomas Thrainer | .CreateSuccessfulNodeResult(self.master, None) |
102 | 70b634e6 | Thomas Thrainer | |
103 | 70b634e6 | Thomas Thrainer | def testRemoveRunningInstanceWithoutShutdown(self): |
104 | 70b634e6 | Thomas Thrainer | inst = self.cfg.AddNewInstance(admin_state=constants.ADMINST_UP)
|
105 | 70b634e6 | Thomas Thrainer | op = opcodes.OpBackupExport(instance_name=inst.name, |
106 | 70b634e6 | Thomas Thrainer | target_node=self.master.name,
|
107 | 70b634e6 | Thomas Thrainer | shutdown=False,
|
108 | 70b634e6 | Thomas Thrainer | remove_instance=True)
|
109 | 70b634e6 | Thomas Thrainer | self.ExecOpCodeExpectOpPrereqError(
|
110 | 70b634e6 | Thomas Thrainer | op, "Can not remove instance without shutting it down before")
|
111 | 70b634e6 | Thomas Thrainer | |
112 | 70b634e6 | Thomas Thrainer | def testUnsupportedDiskTemplate(self): |
113 | 70b634e6 | Thomas Thrainer | inst = self.cfg.AddNewInstance(disk_template=constants.DT_FILE)
|
114 | 70b634e6 | Thomas Thrainer | op = opcodes.OpBackupExport(instance_name=inst.name, |
115 | 70b634e6 | Thomas Thrainer | target_node=self.master.name)
|
116 | 70b634e6 | Thomas Thrainer | self.ExecOpCodeExpectOpPrereqError(
|
117 | 70b634e6 | Thomas Thrainer | op, "Export not supported for instances with file-based disks")
|
118 | 70b634e6 | Thomas Thrainer | |
119 | 70b634e6 | Thomas Thrainer | |
120 | 70b634e6 | Thomas Thrainer | class TestLUBackupExportLocalExport(TestLUBackupExportBase): |
121 | 70b634e6 | Thomas Thrainer | def setUp(self): |
122 | 70b634e6 | Thomas Thrainer | super(TestLUBackupExportLocalExport, self).setUp() |
123 | 70b634e6 | Thomas Thrainer | |
124 | 70b634e6 | Thomas Thrainer | self.inst = self.cfg.AddNewInstance() |
125 | 70b634e6 | Thomas Thrainer | self.target_node = self.cfg.AddNewNode() |
126 | 70b634e6 | Thomas Thrainer | self.op = opcodes.OpBackupExport(mode=constants.EXPORT_MODE_LOCAL,
|
127 | 70b634e6 | Thomas Thrainer | instance_name=self.inst.name,
|
128 | 70b634e6 | Thomas Thrainer | target_node=self.target_node.name)
|
129 | 70b634e6 | Thomas Thrainer | |
130 | 70b634e6 | Thomas Thrainer | self.rpc.call_import_start.return_value = \
|
131 | 70b634e6 | Thomas Thrainer | self.RpcResultsBuilder() \
|
132 | 70b634e6 | Thomas Thrainer | .CreateSuccessfulNodeResult(self.target_node, "import_daemon") |
133 | 70b634e6 | Thomas Thrainer | |
134 | 70b634e6 | Thomas Thrainer | def testExportWithShutdown(self): |
135 | 70b634e6 | Thomas Thrainer | inst = self.cfg.AddNewInstance(admin_state=constants.ADMINST_UP)
|
136 | 70b634e6 | Thomas Thrainer | op = self.CopyOpCode(self.op, instance_name=inst.name, shutdown=True) |
137 | 70b634e6 | Thomas Thrainer | self.ExecOpCode(op)
|
138 | 70b634e6 | Thomas Thrainer | |
139 | 70b634e6 | Thomas Thrainer | def testExportDeactivatedDisks(self): |
140 | 70b634e6 | Thomas Thrainer | self.ExecOpCode(self.op) |
141 | 70b634e6 | Thomas Thrainer | |
142 | 70b634e6 | Thomas Thrainer | def testExportRemoveInstance(self): |
143 | 70b634e6 | Thomas Thrainer | op = self.CopyOpCode(self.op, remove_instance=True) |
144 | 70b634e6 | Thomas Thrainer | self.ExecOpCode(op)
|
145 | 70b634e6 | Thomas Thrainer | |
146 | 70b634e6 | Thomas Thrainer | |
147 | 70b634e6 | Thomas Thrainer | class TestLUBackupExportRemoteExport(TestLUBackupExportBase): |
148 | 70b634e6 | Thomas Thrainer | def setUp(self): |
149 | 70b634e6 | Thomas Thrainer | super(TestLUBackupExportRemoteExport, self).setUp() |
150 | 70b634e6 | Thomas Thrainer | |
151 | 70b634e6 | Thomas Thrainer | self.inst = self.cfg.AddNewInstance() |
152 | 70b634e6 | Thomas Thrainer | self.op = opcodes.OpBackupExport(mode=constants.EXPORT_MODE_REMOTE,
|
153 | 70b634e6 | Thomas Thrainer | instance_name=self.inst.name,
|
154 | 70b634e6 | Thomas Thrainer | target_node=[], |
155 | 70b634e6 | Thomas Thrainer | x509_key_name=["mock_key_name"],
|
156 | 70b634e6 | Thomas Thrainer | destination_x509_ca="mock_dest_ca")
|
157 | 70b634e6 | Thomas Thrainer | |
158 | 70b634e6 | Thomas Thrainer | def testRemoteExportWithoutX509KeyName(self): |
159 | 70b634e6 | Thomas Thrainer | op = self.CopyOpCode(self.op, x509_key_name=self.REMOVE) |
160 | 70b634e6 | Thomas Thrainer | self.ExecOpCodeExpectOpPrereqError(op,
|
161 | 70b634e6 | Thomas Thrainer | "Missing X509 key name for encryption")
|
162 | 70b634e6 | Thomas Thrainer | |
163 | 70b634e6 | Thomas Thrainer | def testRemoteExportWithoutX509DestCa(self): |
164 | 70b634e6 | Thomas Thrainer | op = self.CopyOpCode(self.op, destination_x509_ca=self.REMOVE) |
165 | 70b634e6 | Thomas Thrainer | self.ExecOpCodeExpectOpPrereqError(op,
|
166 | 70b634e6 | Thomas Thrainer | "Missing destination X509 CA")
|
167 | 70b634e6 | Thomas Thrainer | |
168 | 70b634e6 | Thomas Thrainer | |
169 | a80e802a | Thomas Thrainer | if __name__ == "__main__": |
170 | a80e802a | Thomas Thrainer | testutils.GanetiTestProgram() |