1
2
3
4
5
6 import logging
7 import subprocess
8 import os.path
9 import time
10
11 from lib.cuckoo.common.abstracts import Machinery
12 from lib.cuckoo.common.exceptions import CuckooMachineError
13
14 log = logging.getLogger(__name__)
15
17 """Virtualization layer for VMware Workstation using vmrun utility."""
18
37
39 """Checks a vmx file
40 @param host: file path
41 @raise CuckooMachineError: if file not found or not ending with .vmx
42 """
43 if not host.endswith(".vmx"):
44 raise CuckooMachineError("Wrong configuration: vm path not "
45 "ending with .vmx: %s)" % host)
46 if not os.path.exists(self.options.vmware.path):
47 raise CuckooMachineError("Vm file %s not found" % host)
48
50 """Checks snapshot existance.
51 @param host: file path
52 @param snapshot: snapshot name
53 @raise CuckooMachineError: if snapshot not found
54 """
55 try:
56 p = subprocess.Popen([self.options.vmware.path,
57 "listSnapshots", host],
58 stdout=subprocess.PIPE,
59 stderr=subprocess.PIPE)
60 output, error = p.communicate()
61 if output:
62 if snapshot in output:
63 return True
64 else:
65 return False
66 else:
67 raise CuckooMachineError("Unable to get snapshot list for %s. "
68 "No output from "
69 "`vmrun listSnapshots`" % host)
70 except OSError as e:
71 raise CuckooMachineError("Unable to get snapshot list for %s. "
72 "Reason: %s" % (host, e))
73
75 """Start a virtual machine.
76 @param label: virtual machine identifier: path to vmx file.
77 @raise CuckooMachineError: if unable to start.
78 """
79 host, snapshot = self._get_host_and_snapshot(label)
80
81
82 if self._is_running(host):
83 raise CuckooMachineError("Machine %s is already running" % host)
84
85 self._revert(host, snapshot)
86
87 time.sleep(3)
88
89 log.debug("Starting vm %s" % host)
90 try:
91 p = subprocess.Popen([self.options.vmware.path,
92 "start", host, self.options.vmware.mode],
93 stdout=subprocess.PIPE,
94 stderr=subprocess.PIPE)
95 if self.options.vmware.mode.lower() == "gui":
96 output, error = p.communicate()
97 if output:
98 raise CuckooMachineError("Unable to start machine "
99 "%s: %s" % (host, output))
100 except OSError as e:
101 mode = self.options.vmware.mode.upper()
102 raise CuckooMachineError("Unable to start machine %s in %s "
103 "mode: %s" % (host, mode, e))
104
105 - def stop(self, label):
106 """Stops a virtual machine.
107 @param label: virtual machine identifier: path to vmx file
108 (in older configurations it also includes current snapshot name).
109 @raise CuckooMachineError: if unable to stop.
110 """
111 host, snapshot = self._get_host_and_snapshot(label)
112
113 log.debug("Stopping vm %s" % host)
114 if self._is_running(host):
115 try:
116 if subprocess.call([self.options.vmware.path,
117 "stop",
118 host,
119 "hard"],
120 stdout=subprocess.PIPE,
121 stderr=subprocess.PIPE):
122 raise CuckooMachineError("Error shutting down "
123 "machine %s" % host)
124 except OSError as e:
125 raise CuckooMachineError("Error shutting down machine "
126 "%s: %s" % (host, e))
127 else:
128 log.warning("Trying to stop an already stopped machine: %s" % host)
129
130 - def _revert(self, host, snapshot):
131 """Revets machine to snapshot.
132 @param host: file path
133 @param snapshot: snapshot name
134 @raise CuckooMachineError: if unable to revert
135 """
136 log.debug("Revert snapshot for vm %s" % host)
137 try:
138 if subprocess.call([self.options.vmware.path,
139 "revertToSnapshot",
140 host,
141 snapshot],
142 stdout=subprocess.PIPE,
143 stderr=subprocess.PIPE):
144 raise CuckooMachineError("Unable to revert snapshot for "
145 "machine %s: vmrun exited with "
146 "error" % host)
147 except OSError as e:
148 raise CuckooMachineError("Unable to revert snapshot for "
149 "machine %s: %s" % (host, e))
150
152 """Checks if host is running.
153 @param host: file path
154 @return: running status
155 """
156 try:
157 p = subprocess.Popen([self.options.vmware.path, "list"],
158 stdout=subprocess.PIPE,
159 stderr=subprocess.PIPE)
160 output, error = p.communicate()
161 if output:
162 if host in output:
163 return True
164 else:
165 return False
166 else:
167 raise CuckooMachineError("Unable to check running status "
168 "for %s. No output from "
169 "`vmrun list`" % host)
170 except OSError as e:
171 raise CuckooMachineError("Unable to check running status for %s. "
172 "Reason: %s" % (host, e))
173
175 """Parse configuration file label.
176 @param label: configuration option from config file
177 @return: tuple of host file path and snapshot name
178 """
179 opts = label.strip().split(",")
180 if len(opts) != 2:
181 raise CuckooMachineError("Wrong label syntax for %s in "
182 "vmware.conf: %s" % label)
183 label = opts[0].strip()
184 snapshot = opts[1].strip()
185 return label, snapshot
186
188 """Get host and snapshot for a given label
189 New configuration files have a specific 'snapshot' option, while
190 older configuration files have a label in the format:
191 'file.vmx,Snapshot'.
192 @param label: configuration option from config file
193 """
194 vm_info = self.db.view_machine_by_label(label)
195
196 if vm_info.snapshot:
197 host = label.split(',')[0]
198
199
200 snapshot = vm_info.snapshot
201 else:
202
203 host, snapshot = self._parse_label(label)
204 log.warning("Deprecation warning: your vmware configuartion "
205 "file is using old snaphost syntax, please use the "
206 "option 'snapshot' instead.")
207
208 return host, snapshot
209