forked from avocado-framework/avocado-vt
-
Notifications
You must be signed in to change notification settings - Fork 0
/
utils_libguestfs.py
4380 lines (3491 loc) · 144 KB
/
utils_libguestfs.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
"""
libguestfs tools test utility functions.
"""
import logging
import signal
import os
import re
import aexpect
from avocado.utils import path
from avocado.utils import process
from . import propcan
class LibguestfsCmdError(Exception):
"""
Error of libguestfs-tool command.
"""
def __init__(self, details=''):
self.details = details
Exception.__init__(self)
def __str__(self):
return str(self.details)
def lgf_cmd_check(cmd):
"""
To check whether the cmd is supported on this host.
:param cmd: the cmd to use a libguest tool.
:return: None if the cmd is not exist, otherwise return its path.
"""
libguestfs_cmds = ['libguestfs-test-tool', 'guestfish', 'guestmount',
'virt-alignment-scan', 'virt-cat', 'virt-copy-in',
'virt-copy-out', 'virt-df', 'virt-edit',
'virt-filesystems', 'virt-format', 'virt-inspector',
'virt-list-filesystems', 'virt-list-partitions',
'virt-ls', 'virt-make-fs', 'virt-rescue',
'virt-resize', 'virt-sparsify', 'virt-sysprep',
'virt-tar', 'virt-tar-in', 'virt-tar-out',
'virt-win-reg', 'virt-inspector2']
if cmd not in libguestfs_cmds:
raise LibguestfsCmdError(
"Command %s is not supported by libguestfs yet." % cmd)
try:
return path.find_command(cmd)
except path.CmdNotFoundError:
logging.warning("You have not installed %s on this host.", cmd)
return None
def lgf_command(cmd, ignore_status=True, debug=False, timeout=60):
"""
Interface of libguestfs tools' commands.
:param cmd: Command line to execute.
:return: CmdResult object.
:raise: LibguestfsCmdError if non-zero exit status
and ignore_status=False
"""
if debug:
logging.debug("Running command %s in debug mode.", cmd)
# Raise exception if ignore_status is False
try:
ret = process.run(cmd, ignore_status=ignore_status,
verbose=debug, timeout=timeout)
except process.CmdError as detail:
raise LibguestfsCmdError(detail)
if debug:
logging.debug("status: %s", ret.exit_status)
logging.debug("stdout: %s", ret.stdout.strip())
logging.debug("stderr: %s", ret.stderr.strip())
# Return CmdResult instance when ignore_status is True
return ret
class LibguestfsBase(propcan.PropCanBase):
"""
Base class of libguestfs tools.
"""
__slots__ = ['ignore_status', 'debug', 'timeout', 'uri', 'lgf_exec']
def __init__(self, lgf_exec="/bin/true", ignore_status=True,
debug=False, timeout=60, uri=None):
init_dict = {}
init_dict['ignore_status'] = ignore_status
init_dict['debug'] = debug
init_dict['timeout'] = timeout
init_dict['uri'] = uri
init_dict['lgf_exec'] = lgf_exec
super(LibguestfsBase, self).__init__(init_dict)
def set_ignore_status(self, ignore_status):
"""
Enforce setting ignore_status as a boolean.
"""
if bool(ignore_status):
self.__dict_set__('ignore_status', True)
else:
self.__dict_set__('ignore_status', False)
def set_debug(self, debug):
"""
Accessor method for 'debug' property that logs message on change
"""
if not self.INITIALIZED:
self.__dict_set__('debug', debug)
else:
current_setting = self.__dict_get__('debug')
desired_setting = bool(debug)
if not current_setting and desired_setting:
self.__dict_set__('debug', True)
logging.debug("Libguestfs debugging enabled")
# current and desired could both be True
if current_setting and not desired_setting:
self.__dict_set__('debug', False)
logging.debug("Libguestfs debugging disabled")
def set_timeout(self, timeout):
"""
Accessor method for 'timeout' property, timeout should be digit
"""
if type(timeout) is int:
self.__dict_set__('timeout', timeout)
else:
try:
timeout = int(str(timeout))
self.__dict_set__('timeout', timeout)
except ValueError:
logging.debug("Set timeout failed.")
def get_uri(self):
"""
Accessor method for 'uri' property that must exist
"""
# self.get() would call get_uri() recursivly
try:
return self.__dict_get__('uri')
except KeyError:
return None
# There are two ways to call guestfish:
# 1.Guestfish classies provided below(shell session)
# 2.guestfs module provided in system libguestfs package
class Guestfish(LibguestfsBase):
"""
Execute guestfish, using a new guestfish shell each time.
"""
__slots__ = []
def __init__(self, disk_img=None, ro_mode=False,
libvirt_domain=None, inspector=False,
uri=None, mount_options=None, run_mode="interactive"):
"""
Initialize guestfish command with options.
:param disk_img: if it is not None, use option '-a disk'.
:param ro_mode: only for disk_img. add option '--ro' if it is True.
:param libvirt_domain: if it is not None, use option '-d domain'.
:param inspector: guestfish mounts vm's disks automatically
:param uri: guestfish's connect uri
:param mount_options: Mount the named partition or logical volume
on the given mountpoint.
"""
guestfs_exec = "guestfish"
if lgf_cmd_check(guestfs_exec) is None:
raise LibguestfsCmdError
if run_mode not in ['remote', 'interactive']:
raise AssertionError("run_mode should be remote or interactive")
# unset GUESTFISH_XXX environment parameters
# to avoid color of guestfish shell session for testing
color_envs = ["GUESTFISH_PS1", "GUESTFISH_OUTPUT",
"GUESTFISH_RESTORE", "GUESTFISH_INIT"]
unset_cmd = ""
for env in color_envs:
unset_cmd += "unset %s;" % env
if run_mode == "interactive" and unset_cmd:
guestfs_exec = unset_cmd + " " + guestfs_exec
if run_mode == "remote":
guestfs_exec += " --listen"
else:
if uri:
guestfs_exec += " -c '%s'" % uri
if disk_img:
guestfs_exec += " -a '%s'" % disk_img
if libvirt_domain:
guestfs_exec += " -d '%s'" % libvirt_domain
if ro_mode:
guestfs_exec += " --ro"
if inspector:
guestfs_exec += " -i"
if mount_options is not None:
guestfs_exec += " --mount %s" % mount_options
super(Guestfish, self).__init__(guestfs_exec)
def complete_cmd(self, command):
"""
Execute built-in command in a complete guestfish command
(Not a guestfish session).
command: guestfish [--options] [commands]
"""
guestfs_exec = self.__dict_get__('lgf_exec')
ignore_status = self.__dict_get__('ignore_status')
debug = self.__dict_get__('debug')
timeout = self.__dict_get__('timeout')
if command:
guestfs_exec += " %s" % command
return lgf_command(guestfs_exec, ignore_status, debug, timeout)
else:
raise LibguestfsCmdError("No built-in command was passed.")
class GuestfishSession(aexpect.ShellSession):
"""
A shell session of guestfish.
"""
# Check output against list of known error-status strings
ERROR_REGEX_LIST = ['libguestfs: error:\s*']
def __init__(self, guestfs_exec=None, a_id=None, prompt=r"><fs>\s*"):
"""
Initialize guestfish session server, or client if id set.
:param guestfs_cmd: path to guestfish executable
:param id: ID of an already running server, if accessing a running
server, or None if starting a new one.
:param prompt: Regular expression describing the shell's prompt line.
"""
# aexpect tries to auto close session because no clients connected yet
super(GuestfishSession, self).__init__(guestfs_exec, a_id,
prompt=prompt,
auto_close=False)
def cmd_status_output(self, cmd, timeout=60, internal_timeout=None,
print_func=None):
"""
Send a guestfish command and return its exit status and output.
:param cmd: guestfish command to send
(must not contain newline characters)
:param timeout: The duration (in seconds) to wait for the prompt to
return
:param internal_timeout: The timeout to pass to read_nonblocking
:param print_func: A function to be used to print the data being read
(should take a string parameter)
:return: A tuple (status, output) where status is the exit status and
output is the output of cmd
:raise ShellTimeoutError: Raised if timeout expires
:raise ShellProcessTerminatedError: Raised if the shell process
terminates while waiting for output
:raise ShellStatusError: Raised if the exit status cannot be obtained
:raise ShellError: Raised if an unknown error occurs
"""
out = self.cmd_output(cmd, timeout, internal_timeout, print_func)
for line in out.splitlines():
if self.match_patterns(line, self.ERROR_REGEX_LIST) is not None:
return 1, out
return 0, out
def cmd_result(self, cmd, ignore_status=False):
"""Mimic process.run()"""
exit_status, stdout = self.cmd_status_output(cmd)
stderr = '' # no way to retrieve this separately
result = process.CmdResult(cmd, stdout, stderr, exit_status)
if not ignore_status and exit_status:
raise process.CmdError(cmd, result,
"Guestfish Command returned non-zero exit status")
return result
class GuestfishRemote(object):
"""
Remote control of guestfish.
"""
# Check output against list of known error-status strings
ERROR_REGEX_LIST = ['libguestfs: error:\s*']
def __init__(self, guestfs_exec=None, a_id=None):
"""
Initialize guestfish session server, or client if id set.
:param guestfs_cmd: path to guestfish executable
:param a_id: guestfish remote id
"""
if a_id is None:
try:
ret = process.run(guestfs_exec, ignore_status=False,
verbose=True, timeout=60)
except process.CmdError as detail:
raise LibguestfsCmdError(detail)
self.a_id = re.search("\d+", ret.stdout.strip()).group()
else:
self.a_id = a_id
def get_id(self):
return self.a_id
def cmd_status_output(self, cmd, ignore_status=None, verbose=None, timeout=60):
"""
Send a guestfish command and return its exit status and output.
:param cmd: guestfish command to send(must not contain newline characters)
:param timeout: The duration (in seconds) to wait for the prompt to return
:return: A tuple (status, output) where status is the exit status
and output is the output of cmd
:raise LibguestfsCmdError: Raised if commands execute failed
"""
guestfs_exec = "guestfish --remote=%s " % self.a_id
cmd = guestfs_exec + cmd
try:
ret = process.run(cmd, ignore_status=ignore_status,
verbose=verbose, timeout=timeout)
except process.CmdError as detail:
raise LibguestfsCmdError(detail)
for line in self.ERROR_REGEX_LIST:
if re.search(line, ret.stdout.strip()):
e_msg = ('Error pattern %s found on output of %s: %s' %
(line, cmd, ret.stdout.strip()))
raise LibguestfsCmdError(e_msg)
logging.debug("command: %s", cmd)
logging.debug("stdout: %s", ret.stdout.strip())
return 0, ret.stdout.strip()
def cmd(self, cmd, ignore_status=False):
"""Mimic process.run()"""
exit_status, stdout = self.cmd_status_output(cmd)
stderr = '' # no way to retrieve this separately
result = process.CmdResult(cmd, stdout, stderr, exit_status)
if not ignore_status and exit_status:
raise process.CmdError(cmd, result,
"Guestfish Command returned non-zero exit status")
return result
def cmd_result(self, cmd, ignore_status=False):
"""Mimic process.run()"""
exit_status, stdout = self.cmd_status_output(cmd)
stderr = '' # no way to retrieve this separately
result = process.CmdResult(cmd, stdout, stderr, exit_status)
if not ignore_status and exit_status:
raise process.CmdError(cmd, result,
"Guestfish Command returned non-zero exit status")
return result
class GuestfishPersistent(Guestfish):
"""
Execute operations using persistent guestfish session.
"""
__slots__ = ['session_id', 'run_mode']
# Help detect leftover sessions
SESSION_COUNTER = 0
def __init__(self, disk_img=None, ro_mode=False,
libvirt_domain=None, inspector=False,
uri=None, mount_options=None, run_mode="interactive"):
super(GuestfishPersistent, self).__init__(disk_img, ro_mode,
libvirt_domain, inspector,
uri, mount_options, run_mode)
self.__dict_set__('run_mode', run_mode)
if self.get('session_id') is None:
# set_uri does not call when INITIALIZED = False
# and no session_id passed to super __init__
self.new_session()
# Check whether guestfish session is prepared.
guestfs_session = self.open_session()
if run_mode != "remote":
status, output = guestfs_session.cmd_status_output(
'is-config', timeout=60)
if status != 0:
logging.debug(
"Persistent guestfish session is not responding.")
raise aexpect.ShellStatusError(self.lgf_exec, 'is-config')
def close_session(self):
"""
If a persistent session exists, close it down.
"""
try:
run_mode = self.get('run_mode')
existing = self.open_session()
# except clause exits function
# Try to end session with inner command 'quit'
try:
existing.cmd("quit")
# It should jump to exception followed normally
except aexpect.ShellProcessTerminatedError:
self.__class__.SESSION_COUNTER -= 1
self.__dict_del__('session_id')
return # guestfish session was closed normally
# Close with 'quit' did not respond
# So close with aexpect functions
if run_mode != "remote":
if existing.is_alive():
# try nicely first
existing.close()
if existing.is_alive():
# Be mean, incase it's hung
existing.close(sig=signal.SIGTERM)
# Keep count:
self.__class__.SESSION_COUNTER -= 1
self.__dict_del__('session_id')
except LibguestfsCmdError:
# Allow other exceptions to be raised
pass # session was closed already
def new_session(self):
"""
Open new session, closing any existing
"""
# Accessors may call this method, avoid recursion
# Must exist, can't be None
guestfs_exec = self.__dict_get__('lgf_exec')
self.close_session()
# Always create new session
run_mode = self.get('run_mode')
if run_mode == "remote":
new_session = GuestfishRemote(guestfs_exec)
else:
new_session = GuestfishSession(guestfs_exec)
# Keep count
self.__class__.SESSION_COUNTER += 1
session_id = new_session.get_id()
self.__dict_set__('session_id', session_id)
def open_session(self):
"""
Return session with session_id in this class.
"""
try:
session_id = self.__dict_get__('session_id')
run_mode = self.get('run_mode')
if session_id:
try:
if run_mode == "remote":
return GuestfishRemote(a_id=session_id)
else:
return GuestfishSession(a_id=session_id)
except aexpect.ShellStatusError:
# session was already closed
self.__dict_del__('session_id')
raise LibguestfsCmdError(
"Open session '%s' failed." % session_id)
except KeyError:
raise LibguestfsCmdError("No session id.")
# Inner command for guestfish should be executed in a guestfish session
def inner_cmd(self, command):
"""
Execute inner command of guestfish in a pesistent session.
:param command: inner command to be executed.
"""
session = self.open_session()
# Allow to raise error by default.
ignore_status = self.__dict_get__('ignore_status')
return session.cmd_result(command, ignore_status=ignore_status)
def add_drive(self, filename):
"""
add-drive - add an image to examine or modify
This function is the equivalent of calling "add_drive_opts" with no
optional parameters, so the disk is added writable, with the format
being detected automatically.
"""
return self.inner_cmd("add-drive %s" % filename)
def add_drive_opts(self, filename, readonly=False, format=None,
iface=None, name=None, label=None, protocol=None,
server=None, username=None, secret=None,
cachemode=None, discard=None, copyonread=False):
"""
add-drive-opts - add an image to examine or modify.
This function adds a disk image called "filename" to the handle.
"filename" may be a regular host file or a host device.
"""
cmd = "add-drive-opts %s" % filename
if readonly:
cmd += " readonly:true"
else:
cmd += " readonly:false"
if format:
cmd += " format:%s" % format
if iface:
cmd += " iface:%s" % iface
if name:
cmd += " name:%s" % name
if label:
cmd += " label:%s" % label
if protocol:
cmd += " protocol:%s" % protocol
if server:
cmd += " server:%s" % server
if username:
cmd += " username:%s" % username
if secret:
cmd += " secret:%s" % secret
if cachemode:
cmd += " cachemode:%s" % cachemode
if discard:
cmd += " discard:%s" % discard
if copyonread:
cmd += " copyonread:true"
else:
# The default is false for copyonread.
# If copyonread param is false,
# It's no need to set " copyonread:false" explicitly.
pass
return self.inner_cmd(cmd)
def add_drive_ro(self, filename):
"""
add-ro/add-drive-ro - add a drive in snapshot mode (read-only)
This function is the equivalent of calling "add_drive_opts" with the
optional parameter "GUESTFS_ADD_DRIVE_OPTS_READONLY" set to 1, so the
disk is added read-only, with the format being detected automatically.
"""
return self.inner_cmd("add-drive-ro %s" % filename)
def add_domain(self, domain, libvirturi=None, readonly=False, iface=None,
live=False, allowuuid=False, readonlydisk=None):
"""
domain/add-domain - add the disk(s) from a named libvirt domain
This function adds the disk(s) attached to the named libvirt domain
"dom". It works by connecting to libvirt, requesting the domain and
domain XML from libvirt, parsing it for disks, and calling
"add_drive_opts" on each one.
"""
cmd = "add-domain %s" % domain
if libvirturi:
cmd += " libvirturi:%s" % libvirturi
if readonly:
cmd += " readonly:true"
else:
cmd += " readonly:false"
if iface:
cmd += " iface:%s" % iface
if live:
cmd += " live:true"
if allowuuid:
cmd += " allowuuid:true"
if readonlydisk:
cmd += " readonlydisk:%s" % readonlydisk
return self.inner_cmd(cmd)
def run(self):
"""
run/launch - launch the qemu subprocess
Internally libguestfs is implemented by running a virtual machine
using qemu.
"""
return self.inner_cmd("launch")
def df(self):
"""
df - report file system disk space usage
This command runs the "df" command to report disk space used.
"""
return self.inner_cmd("df")
def df_h(self):
"""
df-h - report file system disk space usage (human readable)
This command runs the "df -h" command to report disk space used in
human-readable format.
"""
return self.inner_cmd("df-h")
def dd(self, src, dest):
"""
dd - copy from source to destination using dd
This command copies from one source device or file "src" to another
destination device or file "dest".Normally you would use this to copy
to or from a device or partition,for example to duplicate a filesystem
"""
return self.inner_cmd("dd %s %s" % (src, dest))
def copy_size(self, src, dest, size):
"""
copy-size - copy size bytes from source to destination using dd
This command copies exactly "size" bytes from one source device or file
"src" to another destination device or file "dest".
"""
return self.inner_cmd("copy-size %s %s %s" % (src, dest, size))
def list_partitions(self):
"""
list-partitions - list the partitions
List all the partitions detected on all block devices.
"""
return self.inner_cmd("list-partitions")
def mount(self, device, mountpoint):
"""
mount - mount a guest disk at a position in the filesystem
Mount a guest disk at a position in the filesystem.
"""
return self.inner_cmd("mount %s %s" % (device, mountpoint))
def mount_ro(self, device, mountpoint):
"""
mount-ro - mount a guest disk, read-only
This is the same as the "mount" command, but it mounts the
filesystem with the read-only (*-o ro*) flag.
"""
return self.inner_cmd("mount-ro %s %s" % (device, mountpoint))
def mount_options(self, options, device, mountpoint):
"""
mount - mount a guest disk at a position in the filesystem
Mount a guest disk at a position in the filesystem.
"""
return self.inner_cmd("mount-options %s %s %s" % (options, device, mountpoint))
def mounts(self):
"""
mounts - show mounted filesystems
This returns the list of currently mounted filesystems.
"""
return self.inner_cmd("mounts")
def mountpoints(self):
"""
mountpoints - show mountpoints
This call is similar to "mounts".
That call returns a list of devices.
"""
return self.inner_cmd("mountpoints")
def do_mount(self, mountpoint):
"""
do_mount - Automaticly mount
Mount a lvm or physical partation to '/'
"""
partition_type = self.params.get("partition_type")
if partition_type == "lvm":
vg_name = self.params.get("vg_name", "vol_test")
lv_name = self.params.get("lv_name", "vol_file")
device = "/dev/%s/%s" % (vg_name, lv_name)
logging.info("mount lvm partition...%s" % device)
elif partition_type == "physical":
pv_name = self.params.get("pv_name", "/dev/sdb")
device = pv_name + "1"
logging.info("mount physical partition...%s" % device)
self.mount(device, mountpoint)
def read_file(self, path):
"""
read-file - read a file
This calls returns the contents of the file "path" as a buffer.
"""
return self.inner_cmd("read-file %s" % path)
def cat(self, path):
"""
cat - list the contents of a file
Return the contents of the file named "path".
"""
return self.inner_cmd("cat %s" % path)
def write(self, path, content):
"""
write - create a new file
This call creates a file called "path". The content of the file
is the string "content" (which can contain any 8 bit data).
"""
return self.inner_cmd("write '%s' \"%s\"" % (path, content))
def write_append(self, path, content):
"""
write-append - append content to end of file
This call appends "content" to the end of file "path".
If "path" does not exist, then a new file is created.
"""
return self.inner_cmd("write-append '%s' \"%s\"" % (path, content))
def inspect_os(self):
"""
inspect-os - inspect disk and return list of operating systems found
This function uses other libguestfs functions and certain heuristics to
inspect the disk(s) (usually disks belonging to a virtual machine),
looking for operating systems.
"""
return self.inner_cmd("inspect-os")
def inspect_get_roots(self):
"""
inspect-get-roots - return list of operating systems found by
last inspection
This function is a convenient way to get the list of root devices
"""
return self.inner_cmd("inspect-get-roots")
def inspect_get_arch(self, root):
"""
inspect-get-arch - get architecture of inspected operating system
This returns the architecture of the inspected operating system.
"""
return self.inner_cmd("inspect-get-arch %s" % root)
def inspect_get_distro(self, root):
"""
inspect-get-distro - get distro of inspected operating system
This returns the distro (distribution) of the inspected
operating system.
"""
return self.inner_cmd("inspect-get-distro %s" % root)
def inspect_get_filesystems(self, root):
"""
inspect-get-filesystems - get filesystems associated with inspected
operating system
This returns a list of all the filesystems that we think are associated
with this operating system.
"""
return self.inner_cmd("inspect-get-filesystems %s" % root)
def inspect_get_hostname(self, root):
"""
inspect-get-hostname - get hostname of the operating system
This function returns the hostname of the operating system as found by
inspection of the guest's configuration files.
"""
return self.inner_cmd("inspect-get-hostname %s" % root)
def inspect_get_major_version(self, root):
"""
inspect-get-major-version - get major version of inspected operating
system
This returns the major version number of the inspected
operating system.
"""
return self.inner_cmd("inspect-get-major-version %s" % root)
def inspect_get_minor_version(self, root):
"""
inspect-get-minor-version - get minor version of inspected operating
system
This returns the minor version number of the inspected operating system
"""
return self.inner_cmd("inspect-get-minor-version %s" % root)
def inspect_get_mountpoints(self, root):
"""
inspect-get-mountpoints - get mountpoints of inspected operating system
This returns a hash of where we think the filesystems associated with
this operating system should be mounted.
"""
return self.inner_cmd("inspect-get-mountpoints %s" % root)
def list_filesystems(self):
"""
list-filesystems - list filesystems
This inspection command looks for filesystems on partitions, block
devices and logical volumes, returning a list of devices containing
filesystems and their type.
"""
return self.inner_cmd("list-filesystems")
def list_devices(self):
"""
list-devices - list the block devices
List all the block devices.
"""
return self.inner_cmd("list-devices")
def tar_out(self, directory, tarfile):
"""
tar-out - pack directory into tarfile
This command packs the contents of "directory" and downloads it
to local file "tarfile".
"""
return self.inner_cmd("tar-out %s %s" % (directory, tarfile))
def tar_in(self, tarfile, directory):
"""
tar-in - unpack tarfile to directory
This command uploads and unpacks local file "tarfile"
(an *uncompressed* tar file) into "directory".
"""
return self.inner_cmd("tar-in %s %s" % (tarfile, directory))
def tar_in_opts(self, tarfile, directory, compress=None):
"""
tar-in-opts - unpack tarfile to directory
This command uploads and unpacks local file "tarfile"
(an *compressed* tar file) into "directory".
"""
if compress:
return self.inner_cmd("tar-in-opts %s %s compress:%s" % (tarfile, directory, compress))
else:
return self.inner_cmd("tar-in-opts %s %s" % (tarfile, directory))
def file_architecture(self, filename):
"""
file-architecture - detect the architecture of a binary file
This detects the architecture of the binary "filename", and returns it
if known.
"""
return self.inner_cmd("file-architecture %s" % filename)
def filesize(self, file):
"""
filesize - return the size of the file in bytes
This command returns the size of "file" in bytes.
"""
return self.inner_cmd("filesize %s" % file)
def stat(self, path):
"""
stat - get file information
Returns file information for the given "path".
"""
return self.inner_cmd("stat %s" % path)
def lstat(self, path):
"""
lstat - get file information for a symbolic link
Returns file information for the given "path".
"""
return self.inner_cmd("lstat %s" % path)
def lstatlist(self, path, names):
"""
lstatlist - lstat on multiple files
This call allows you to perform the "lstat" operation on multiple files,
where all files are in the directory "path". "names" is the list of
files from this directory.
"""
return self.inner_cmd("lstatlist %s %s" % (path, names))
def umask(self, mask):
"""
umask - set file mode creation mask (umask)
This function sets the mask used for creating new files and device nodes
to "mask & 0777".
"""
return self.inner_cmd("umask %s" % mask)
def get_umask(self):
"""
get-umask - get the current umask
Return the current umask. By default the umask is 022 unless it has been
set by calling "umask".
"""
return self.inner_cmd("get-umask")
def mkdir(self, path):
"""
mkdir - create a directory
Create a directory named "path".
"""
return self.inner_cmd("mkdir %s" % path)
def mkdir_p(self, path):
"""
mkdir-p - create a directory and parents
Create a directory named "path", creating any parent directories as necessary.
This is like the "mkdir -p" shell command.
"""
return self.inner_cmd("mkdir-p %s" % path)
def mkdir_mode(self, path, mode):
"""
mkdir-mode - create a directory with a particular mode
This command creates a directory, setting the initial permissions of the
directory to "mode".
"""
return self.inner_cmd("mkdir-mode %s %s" % (path, mode))
def mknod(self, mode, devmajor, devminor, path):
"""
mknod - make block, character or FIFO devices
This call creates block or character special devices, or named pipes
(FIFOs).
"""
return self.inner_cmd("mknod %s %s %s %s" % (mode, devmajor, devminor, path))
def rm_rf(self, path):
"""
rm-rf - remove a file or directory recursively
Remove the file or directory "path", recursively removing the contents
if its a directory. This is like the "rm -rf" shell command.
"""
return self.inner_cmd("rm-rf %s" % path)
def copy_out(self, remote, localdir):
"""
copy-out - copy remote files or directories out of an image
"copy-out" copies remote files or directories recursively out of the
disk image, placing them on the host disk in a local directory called
"localdir" (which must exist).
"""
return self.inner_cmd("copy-out %s %s" % (remote, localdir))
def copy_in(self, local, remotedir):
"""
copy-in - copy local files or directories into an image
"copy-in" copies local files or directories recursively into the disk
image, placing them in the directory called "/remotedir" (which must
exist).
"""
return self.inner_cmd("copy-in %s /%s" % (local, remotedir))
def chmod(self, mode, path):
"""
chmod - change file mode
Change the mode (permissions) of "path" to "mode". Only numeric modes
are supported.
"""
return self.inner_cmd("chmod %s %s" % (mode, path))
def chown(self, owner, group, path):
"""
chown - change file owner and group