Package modules :: Package machinery :: Module xenserver
[hide private]
[frames] | no frames]

Source Code for Module modules.machinery.xenserver

  1  # Copyright (C) 2010-2015 Cuckoo Foundation. 
  2  # This file is part of Cuckoo Sandbox - http://www.cuckoosandbox.org 
  3  # See the file 'docs/LICENSE' for copying permission. 
  4   
  5  """ 
  6  XenServer machinery. 
  7  """ 
  8   
  9  import threading 
 10  import logging 
 11   
 12  from lib.cuckoo.common.abstracts import Machinery 
 13  from lib.cuckoo.common.exceptions import CuckooMachineError 
 14  from lib.cuckoo.common.exceptions import CuckooDependencyError 
 15   
 16  try: 
 17      import XenAPI 
 18      HAVE_XENAPI = True 
 19  except ImportError: 
 20      HAVE_XENAPI = False 
 21   
 22   
 23  log = logging.getLogger(__name__) 
24 25 26 -class XenServerMachinery(Machinery):
27 """Virtualization layer for XenServer using the XenAPI XML-RPC interface.""" 28 29 LABEL = "uuid" 30 31 # Power States. 32 RUNNING = "Running" 33 PAUSED = "Paused" 34 POWEROFF = "Halted" 35 ABORTED = "Suspended" 36
37 - def _initialize_check(self):
38 """Check XenServer configuration, initialize a Xen API connection, and 39 verify machine validity. 40 """ 41 42 self._sessions = {} 43 44 if not HAVE_XENAPI: 45 raise CuckooDependencyError("Unable to import XenAPI") 46 47 if not self.options.xenserver.user: 48 raise CuckooMachineError("XenServer username missing, please add " 49 "it to xenserver.conf.") 50 51 if not self.options.xenserver.password: 52 raise CuckooMachineError("XenServer password missing, please add " 53 "it to xenserver.conf") 54 55 if not self.options.xenserver.url: 56 raise CuckooMachineError("XenServer url missing, please add it to " 57 "xenserver.conf") 58 59 self._make_xenapi_session() 60 61 for machine in self.machines(): 62 uuid = machine.label 63 (ref, vm) = self._check_vm(uuid) 64 65 if machine.snapshot: 66 self._check_snapshot(uuid, machine.snapshot) 67 else: 68 self._check_disks_reset(vm) 69 70 super(XenServerMachinery, self)._initialize_check()
71 72 @property
73 - def session(self):
74 tid = threading.current_thread().ident 75 sess = self._sessions.get(tid, None) 76 if sess is None: 77 sess = self._make_xenapi_session(tid) 78 return sess
79
80 - def _make_xenapi_session(self, tid=None):
81 tid = tid or threading.current_thread().ident 82 try: 83 sess = XenAPI.Session(self.options.xenserver.url) 84 except: 85 raise CuckooMachineError("Could not connect to XenServer: invalid " 86 "or incorrect url, please ensure the url " 87 "is correct in xenserver.conf") 88 89 try: 90 sess.xenapi.login_with_password( 91 self.options.xenserver.user, self.options.xenserver.password 92 ) 93 except: 94 raise CuckooMachineError("Could not connect to XenServer: " 95 "incorrect credentials, please ensure " 96 "the user and password are correct in " 97 "xenserver.conf") 98 self._sessions[tid] = sess 99 return sess
100
101 - def _get_vm_ref(self, uuid):
102 """Get a virtual machine reference. 103 @param uuid: vm uuid 104 """ 105 106 return self.session.xenapi.VM.get_by_uuid(uuid.lower())
107
108 - def _get_vm_record(self, ref):
109 """Get the virtual machine record. 110 @param ref: vm reference 111 """ 112 113 return self.session.xenapi.VM.get_record(ref)
114
115 - def _get_vm_power_state(self, ref):
116 """Get the virtual machine power state. 117 @param ref: vm reference 118 """ 119 120 return self.session.xenapi.VM.get_power_state(ref)
121
122 - def _check_vm(self, uuid):
123 """Check vm existence and validity. 124 @param uuid: vm uuid 125 """ 126 127 try: 128 ref = self._get_vm_ref(uuid) 129 vm = self._get_vm_record(ref) 130 except XenAPI.Failure as e: 131 raise CuckooMachineError("Vm not found: %s: %s" 132 % (uuid, e.details[0])) 133 134 if vm["is_a_snapshot"]: 135 raise CuckooMachineError("Vm is a snapshot: %s" % uuid) 136 137 if vm["is_a_template"]: 138 raise CuckooMachineError("Vm is a template: %s" % uuid) 139 140 if vm["is_control_domain"]: 141 raise CuckooMachineError("Vm is a control domain: %s" % uuid) 142 143 return (ref, vm)
144
145 - def _check_snapshot(self, vm_uuid, snapshot_uuid):
146 """Check snapshot existence and that the snapshot is of the specified 147 vm uuid. 148 @param vm_uuid: vm uuid 149 @param snapshot_uuid: snapshot uuid 150 """ 151 152 try: 153 snapshot_ref = self._get_vm_ref(snapshot_uuid) 154 snapshot = self._get_vm_record(snapshot_ref) 155 except: 156 raise CuckooMachineError("Snapshot not found: %s" % snapshot_uuid) 157 158 if not snapshot["is_a_snapshot"]: 159 raise CuckooMachineError("Invalid snapshot: %s" % snapshot_uuid) 160 161 try: 162 parent = self._get_vm_record(snapshot["snapshot_of"]) 163 except: 164 raise CuckooMachineError("Invalid snapshot: %s" % snapshot_uuid) 165 166 parent_uuid = parent["uuid"] 167 if parent_uuid != vm_uuid: 168 raise CuckooMachineError("Snapshot does not belong to specified " 169 "vm: %s" % snapshot_uuid)
170
171 - def _check_disks_reset(self, vm):
172 """Check whether each attached disk is set to reset on boot. 173 @param vm: vm record 174 """ 175 176 for ref in vm["VBDs"]: 177 try: 178 vbd = self.session.xenapi.VBD.get_record(ref) 179 except: 180 log.warning("Invalid VBD for vm %s: %s", vm["uuid"], ref) 181 continue 182 183 if vbd["type"] == "Disk": 184 vdi_ref = vbd["VDI"] 185 try: 186 vdi = self.session.xenapi.VDI.get_record(vdi_ref) 187 except: 188 log.warning("Invalid VDI for vm %s: %s", vm["uuid"], 189 vdi_ref) 190 continue 191 192 if vdi["on_boot"] != "reset" and vdi["read_only"] is False: 193 raise CuckooMachineError( 194 "Vm %s contains invalid VDI %s: disk is not reset on " 195 "boot. Please set the on-boot parameter to 'reset'." 196 % (vm["uuid"], vdi["uuid"]))
197
198 - def _snapshot_from_vm_uuid(self, uuid):
199 """Get the snapshot uuid from a virtual machine. 200 @param uuid: vm uuid 201 """ 202 203 machine = self.db.view_machine_by_label(uuid) 204 return machine.snapshot
205
206 - def _is_halted(self, vm):
207 """Checks if the virtual machine is running. 208 @param uuid: vm uuid 209 """ 210 211 return vm["power_state"] == "Halted"
212
213 - def start(self, label):
214 """Start a virtual machine. 215 @param label: vm uuid 216 """ 217 218 vm_ref = self._get_vm_ref(label) 219 vm = self._get_vm_record(vm_ref) 220 221 if not self._is_halted(vm): 222 raise CuckooMachineError("Vm is already running: %s", label) 223 224 snapshot = self._snapshot_from_vm_uuid(label) 225 if snapshot: 226 snapshot_ref = self._get_vm_ref(snapshot) 227 try: 228 log.debug("Reverting vm %s to snapshot %s", label, snapshot) 229 self.session.xenapi.VM.revert(snapshot_ref) 230 log.debug("Revert completed for vm %s", label) 231 except XenAPI.Failure as e: 232 raise CuckooMachineError("Unable to revert vm %s: %s" 233 % (label, e.details[0])) 234 235 try: 236 log.debug("Resuming reverted vm %s", label) 237 self.session.xenapi.VM.resume(vm_ref, False, False) 238 except XenAPI.Failure as e: 239 raise CuckooMachineError("Unable to resume vm %s: %s" 240 % (label, e.details[0])) 241 else: 242 log.debug("No snapshot found for vm, booting: %s", label) 243 try: 244 self.session.xenapi.VM.start(vm_ref, False, False) 245 except XenAPI.Failure as e: 246 raise CuckooMachineError("Unable to start vm %s: %s" 247 % (label, e.details[0])) 248 249 log.debug("Started vm: %s", label)
250
251 - def stop(self, label=None):
252 """Stop a virtual machine. 253 @param label: vm uuid 254 """ 255 256 ref = self._get_vm_ref(label) 257 vm = self._get_vm_record(ref) 258 if self._is_halted(vm): 259 log.warning("Trying to stop an already stopped machine: %s", label) 260 else: 261 try: 262 self.session.xenapi.VM.hard_shutdown(ref) 263 except XenAPI.Failure as e: 264 raise CuckooMachineError("Error shutting down virtual machine:" 265 " %s: %s" % (label, e.details[0]))
266
267 - def _list(self):
268 """List available virtual machines. 269 @raise CuckooMachineError: if unable to list virtual machines. 270 """ 271 272 try: 273 vm_list = [] 274 for ref in self.session.xenapi.VM.get_all(): 275 vm = self._get_vm_record(ref) 276 vm_list.append(vm['uuid']) 277 except: 278 raise CuckooMachineError("Cannot list domains") 279 else: 280 return vm_list
281
282 - def _status(self, label):
283 """Gets current status of a vm. 284 @param label: virtual machine uuid 285 @return: status string. 286 """ 287 288 ref = self._get_vm_ref(label) 289 state = self._get_vm_power_state(ref) 290 291 return state
292