2 * Copyright (C) 2014 Red Hat, Inc.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library. If not, see
16 * <http://www.gnu.org/licenses/>.
21 #include "testutils.h"
30 # define LIBVIRT_VIRCOMMANDPRIV_H_ALLOW
31 # include "vircommandpriv.h"
32 # include "viriscsi.h"
34 # define VIR_FROM_THIS VIR_FROM_NONE
36 static const char *iscsiadmSessionOutput
=
37 "tcp: [1] 10.20.30.40:3260,1 iqn.2004-06.example:example1:iscsi.test\n"
38 "tcp: [2] 10.20.30.41:3260,1 iqn.2005-05.example:example1:iscsi.hello\n"
39 "tcp: [3] 10.20.30.42:3260,1 iqn.2006-04.example:example1:iscsi.world\n"
40 "tcp: [5] 10.20.30.43:3260,1 iqn.2007-04.example:example1:iscsi.foo\n"
41 "tcp: [6] 10.20.30.44:3260,1 iqn.2008-04.example:example1:iscsi.bar\n"
42 "tcp: [7] 10.20.30.45:3260,1 iqn.2009-04.example:example1:iscsi.seven\n";
44 static const char *iscsiadmSessionOutputNonFlash
=
45 "tcp: [1] 10.20.30.40:3260,1 iqn.2004-06.example:example1:iscsi.test (non-flash)\n"
46 "tcp: [2] 10.20.30.41:3260,1 iqn.2005-05.example:example1:iscsi.hello (non-flash)\n"
47 "tcp: [3] 10.20.30.42:3260,1 iqn.2006-04.example:example1:iscsi.world (non-flash)\n"
48 "tcp: [5] 10.20.30.43:3260,1 iqn.2007-04.example:example1:iscsi.foo (non-flash)\n"
49 "tcp: [6] 10.20.30.44:3260,1 iqn.2008-04.example:example1:iscsi.bar (non-flash)\n"
50 "tcp: [7] 10.20.30.45:3260,1 iqn.2009-04.example:example1:iscsi.seven (non-flash)\n";
52 const char *iscsiadmSendtargetsOutput
=
53 "10.20.30.40:3260,1 iqn.2004-06.example:example1:iscsi.test\n"
54 "10.20.30.40:3260,1 iqn.2005-05.example:example1:iscsi.hello\n"
55 "10.20.30.40:3260,1 iqn.2006-04.example:example1:iscsi.world\n"
56 "10.20.30.40:3260,1 iqn.2007-04.example:example1:iscsi.foo\n"
57 "10.20.30.40:3260,1 iqn.2008-04.example:example1:iscsi.bar\n"
58 "10.20.30.40:3260,1 iqn.2009-04.example:example1:iscsi.seven\n";
60 const char *iscsiadmIfaceDefaultOutput
=
61 "default tcp,<empty>,<empty>,<empty>,<empty>\n"
62 "iser iser,<empty>,<empty>,<empty>,<empty>\n";
64 const char *iscsiadmIfaceIfaceOutput
=
65 "default tcp,<empty>,<empty>,<empty>,<empty>\n"
66 "iser iser,<empty>,<empty>,<empty>,<empty>\n"
67 "libvirt-iface-03020100 tcp,<empty>,<empty>,<empty>,iqn.2004-06.example:example1:initiator\n";
70 struct testIscsiadmCbData
{
75 static void testIscsiadmCb(const char *const*args
,
76 const char *const*env ATTRIBUTE_UNUSED
,
77 const char *input ATTRIBUTE_UNUSED
,
79 char **error ATTRIBUTE_UNUSED
,
83 struct testIscsiadmCbData
*data
= opaque
;
85 if (args
[0] && STREQ(args
[0], ISCSIADM
) &&
86 args
[1] && STREQ(args
[1], "--mode") &&
87 args
[2] && STREQ(args
[2], "session") &&
89 if (data
->output_version
)
90 ignore_value(VIR_STRDUP(*output
, iscsiadmSessionOutputNonFlash
));
92 ignore_value(VIR_STRDUP(*output
, iscsiadmSessionOutput
));
93 } else if (args
[0] && STREQ(args
[0], ISCSIADM
) &&
94 args
[1] && STREQ(args
[1], "--mode") &&
95 args
[2] && STREQ(args
[2], "discovery") &&
96 args
[3] && STREQ(args
[3], "--type") &&
97 args
[4] && STREQ(args
[4], "sendtargets") &&
98 args
[5] && STREQ(args
[5], "--portal") &&
99 args
[6] && STREQ(args
[6], "10.20.30.40:3260,1") &&
100 args
[7] && STREQ(args
[7], "--op") &&
101 args
[8] && STREQ(args
[8], "nonpersistent") &&
103 ignore_value(VIR_STRDUP(*output
, iscsiadmSendtargetsOutput
));
104 } else if (args
[0] && STREQ(args
[0], ISCSIADM
) &&
105 args
[1] && STREQ(args
[1], "--mode") &&
106 args
[2] && STREQ(args
[2], "node") &&
107 args
[3] && STREQ(args
[3], "--portal") &&
108 args
[4] && STREQ(args
[4], "10.20.30.40:3260,1") &&
109 args
[5] && STREQ(args
[5], "--targetname") &&
110 args
[6] && STREQ(args
[6], "iqn.2004-06.example:example1:iscsi.test") &&
111 args
[7] && STREQ(args
[7], "--login") &&
113 /* Mocking real environment output is not needed for now.
114 * Example output from real environment:
116 * Logging in to [iface: default, \
117 * target: iqn.2004-06.example:example1:iscsi.test, \
118 * portal: 10.20.30.40:3260,1] (multiple)
119 * Login to [iface: default, \
120 * target: iqn.2004-06.example:example1:iscsi.test, \
121 * portal: 10.20.30.40:3260,1] successful.
123 } else if (args
[0] && STREQ(args
[0], ISCSIADM
) &&
124 args
[1] && STREQ(args
[1], "--mode") &&
125 args
[2] && STREQ(args
[2], "iface") &&
127 if (data
->iface_created
)
128 ignore_value(VIR_STRDUP(*output
, iscsiadmIfaceIfaceOutput
));
130 ignore_value(VIR_STRDUP(*output
, iscsiadmIfaceDefaultOutput
));
131 } else if (args
[0] && STREQ(args
[0], ISCSIADM
) &&
132 args
[1] && STREQ(args
[1], "--mode") &&
133 args
[2] && STREQ(args
[2], "iface") &&
134 args
[3] && STREQ(args
[3], "--interface") &&
135 args
[4] && STREQ(args
[4], "libvirt-iface-03020100") &&
136 args
[5] && STREQ(args
[5], "--op") &&
137 args
[6] && STREQ(args
[6], "new") &&
139 /* Mocking real environment output is not needed for now.
140 * Example output from real environment:
142 * New interface libvirt-iface-03020100 added
144 data
->iface_created
= true;
145 } else if (args
[0] && STREQ(args
[0], ISCSIADM
) &&
146 args
[1] && STREQ(args
[1], "--mode") &&
147 args
[2] && STREQ(args
[2], "iface") &&
148 args
[3] && STREQ(args
[3], "--interface") &&
149 args
[4] && STREQ(args
[4], "libvirt-iface-03020100") &&
150 args
[5] && STREQ(args
[5], "--op") &&
151 args
[6] && STREQ(args
[6], "update") &&
152 args
[7] && STREQ(args
[7], "--name") &&
153 args
[8] && STREQ(args
[8], "iface.initiatorname") &&
154 args
[9] && STREQ(args
[9], "--value") &&
155 args
[10] && STREQ(args
[10], "iqn.2004-06.example:example1:initiator") &&
157 data
->iface_created
) {
158 /* Mocking real environment output is not needed for now.
159 * Example output from real environment:
161 * libvirt-iface-03020100 updated.
163 } else if (args
[0] && STREQ(args
[0], ISCSIADM
) &&
164 args
[1] && STREQ(args
[1], "--mode") &&
165 args
[2] && STREQ(args
[2], "discovery") &&
166 args
[3] && STREQ(args
[3], "--type") &&
167 args
[4] && STREQ(args
[4], "sendtargets") &&
168 args
[5] && STREQ(args
[5], "--portal") &&
169 args
[6] && STREQ(args
[6], "10.20.30.40:3260,1") &&
170 args
[7] && STREQ(args
[7], "--interface") &&
171 args
[8] && STREQ(args
[8], "libvirt-iface-03020100") &&
173 data
->iface_created
) {
174 ignore_value(VIR_STRDUP(*output
, iscsiadmSendtargetsOutput
));
175 } else if (args
[0] && STREQ(args
[0], ISCSIADM
) &&
176 args
[1] && STREQ(args
[1], "--mode") &&
177 args
[2] && STREQ(args
[2], "node") &&
178 args
[3] && STREQ(args
[3], "--portal") &&
179 args
[4] && STREQ(args
[4], "10.20.30.40:3260,1") &&
180 args
[5] && STREQ(args
[5], "--targetname") &&
181 args
[6] && STREQ(args
[6], "iqn.2004-06.example:example1:iscsi.test") &&
182 args
[7] && STREQ(args
[7], "--login") &&
183 args
[8] && STREQ(args
[8], "--interface") &&
184 args
[9] && STREQ(args
[9], "libvirt-iface-03020100") &&
186 data
->iface_created
) {
187 /* Mocking real environment output is not needed for now.
188 * Example output from real environment:
190 * Logging in to [iface: libvirt-iface-03020100, \
191 * target: iqn.2004-06.example:example1:iscsi.test, \
192 * portal: 10.20.30.40:3260,1] (multiple)
193 * Login to [iface: libvirt-iface-03020100, \
194 * target: iqn.2004-06.example:example1:iscsi.test, \
195 * portal: 10.20.30.40:3260,1] successful.
202 struct testSessionInfo
{
203 const char *device_path
;
205 const char *expected_session
;
209 testISCSIGetSession(const void *data
)
211 const struct testSessionInfo
*info
= data
;
212 struct testIscsiadmCbData cbData
= { 0 };
213 char *actual_session
= NULL
;
216 cbData
.output_version
= info
->output_version
;
218 virCommandSetDryRun(NULL
, testIscsiadmCb
, &cbData
);
220 actual_session
= virISCSIGetSession(info
->device_path
, true);
222 if (STRNEQ_NULLABLE(actual_session
, info
->expected_session
)) {
223 virReportError(VIR_ERR_INTERNAL_ERROR
,
224 "Expected session: '%s' got: '%s'",
225 NULLSTR(info
->expected_session
),
226 NULLSTR(actual_session
));
233 virCommandSetDryRun(NULL
, NULL
, NULL
);
234 VIR_FREE(actual_session
);
238 struct testScanTargetsInfo
{
239 const char *fake_cmd_output
;
241 const char **expected_targets
;
246 testISCSIScanTargets(const void *data
)
248 const struct testScanTargetsInfo
*info
= data
;
250 char **targets
= NULL
;
254 virCommandSetDryRun(NULL
, testIscsiadmCb
, NULL
);
256 if (virISCSIScanTargets(info
->portal
, NULL
,
257 false, &ntargets
, &targets
) < 0)
260 if (info
->nexpected
!= ntargets
) {
261 virReportError(VIR_ERR_INTERNAL_ERROR
,
262 "Expected %zu targets, got %zu",
263 info
->nexpected
, ntargets
);
267 for (i
= 0; i
< ntargets
; i
++) {
268 if (STRNEQ(info
->expected_targets
[i
], targets
[i
])) {
269 virReportError(VIR_ERR_INTERNAL_ERROR
,
270 "Expected target '%s', got '%s'",
271 info
->expected_targets
[i
], targets
[i
]);
279 virCommandSetDryRun(NULL
, NULL
, NULL
);
280 for (i
= 0; i
< ntargets
; i
++)
281 VIR_FREE(targets
[i
]);
287 struct testConnectionInfoLogin
{
289 const char *initiatoriqn
;
295 testISCSIConnectionLogin(const void *data
)
297 const struct testConnectionInfoLogin
*info
= data
;
298 struct testIscsiadmCbData cbData
= { 0 };
301 virCommandSetDryRun(NULL
, testIscsiadmCb
, &cbData
);
303 if (virISCSIConnectionLogin(info
->portal
, info
->initiatoriqn
, info
->target
) < 0)
308 virCommandSetDryRun(NULL
, NULL
, NULL
);
318 # define DO_SESSION_TEST(name, session) \
320 struct testSessionInfo info = {name, false, session}; \
321 if (virTestRun("ISCSI get session test" name, \
322 testISCSIGetSession, &info) < 0) \
324 info.output_version = true; \
325 if (virTestRun("ISCSI get (non-flash) session test" name, \
326 testISCSIGetSession, &info) < 0) \
330 DO_SESSION_TEST("iqn.2004-06.example:example1:iscsi.test", "1");
331 DO_SESSION_TEST("iqn.2009-04.example:example1:iscsi.seven", "7");
332 DO_SESSION_TEST("iqn.2009-04.example:example1:iscsi.eight", NULL
);
334 const char *targets
[] = {
335 "iqn.2004-06.example:example1:iscsi.test",
336 "iqn.2005-05.example:example1:iscsi.hello",
337 "iqn.2006-04.example:example1:iscsi.world",
338 "iqn.2007-04.example:example1:iscsi.foo",
339 "iqn.2008-04.example:example1:iscsi.bar",
340 "iqn.2009-04.example:example1:iscsi.seven"
342 struct testScanTargetsInfo infoTargets
= {
343 .fake_cmd_output
= "iscsiadm_sendtargets",
344 .portal
= "10.20.30.40:3260,1",
345 .expected_targets
= targets
,
346 .nexpected
= ARRAY_CARDINALITY(targets
),
348 if (virTestRun("ISCSI scan targets", testISCSIScanTargets
, &infoTargets
) < 0)
351 # define DO_LOGIN_TEST(portal, iqn, target) \
353 struct testConnectionInfoLogin info = {portal, iqn, target }; \
354 if (virTestRun("ISCSI login " portal, \
355 testISCSIConnectionLogin, &info) < 0) \
359 DO_LOGIN_TEST("10.20.30.40:3260,1", NULL
, "iqn.2004-06.example:example1:iscsi.test");
360 DO_LOGIN_TEST("10.20.30.40:3260,1", "iqn.2004-06.example:example1:initiator",
361 "iqn.2004-06.example:example1:iscsi.test");
368 VIR_TEST_MAIN_PRELOAD(mymain
,
369 abs_builddir
"/.libs/virrandommock.so")