def _handle_configure(self, id_, image): """Configure the image (spin it up, let the user muck around in it, commit all changes back into the original image) """ child_snapshots = master.models.Image.objects(base_image=image.id) if len(child_snapshots) > 0: self._log.warn("ERROR! ILLEGAL OPERATION! I WILL NOT MODIFY AN IMAGE WITH {} DEPENDENT SNAPSHOTS!".format( len(child_snapshots) )) image.status = {"name": "ready"} return vagrantfile = image.status.setdefault("vagrantfile", None) user_interaction = image.status.setdefault("user_interaction", False) vnc_info = self._vm_manager.configure_image( str(image.id), vagrantfile = vagrantfile, user_interaction = user_interaction, on_success = self._set_image_ready, kvm = image.status["kvm"] ) self._log.debug("got vnc info from configure image: {!r}".format(vnc_info)) from master import Master Master.instance().update_status(vms=self._get_running_vms()) image = master.models.Image.objects(id=image.id)[0] if user_interaction: image.status = { "name": "configuring", "vnc": vnc_info } image.save()
def _handle_create(self, id_, image): """Handle creating a new VM based on an existing VM """ self._log.info("creating an image") base = image.base_image dest_name = image.name vagrantfile = image.status.setdefault("vagrantfile", None) user_interaction = image.status.setdefault("user_interaction", False) vnc_info = self._vm_manager.create_image( vagrantfile, base_name = str(base.id), dest_name = str(image.id), user_interaction = user_interaction, on_success = self._set_image_ready ) from master import Master Master.instance().update_status(vms=self._get_running_vms()) image = master.models.Image.objects(id=image.id)[0] if user_interaction: image.status = { "name": "configuring", "vnc": vnc_info } image.save()
def stop_job(self, job): """This is intended to be called once a job has been completed (not cancelled, but completed) """ self._log.info("stopping job: {}".format(job.id)) if str(job.id) in self._job_handlers: with self._job_queue_lock: handler = self._job_handlers[str(job.id)] queue = self._job_amqp_queues[handler.queue_name] new_queue = [] for priority, handler in queue.queue: if handler.job.id == job.id: continue new_queue.append((priority, handler)) queue.queue = new_queue Master.instance().update_status(queues=self._get_queues()) AmqpManager.instance().queue_msg(json.dumps( dict(type="cancel", job=str(job.id))), "", exchange=Master.AMQP_BROADCAST_XCHG) job.reload() job.status = {"name": "finished"} job.timestamps["finished"] = time.time() job.save() self._log.info("stopped job: {}".format(job.id)) self._cleanup_job(job)
def run_job(self, job): """TODO: Docstring for run_job. :job: TODO :returns: TODO """ self._log.info("running job: {}".format(job.id)) job.priority = self._safe_priority(job.priority) job.save() queue = job.queue if queue is None or queue == "": queue = self.AMQP_JOB_QUEUE handler = JobHandler(job, queue, self) self._job_handlers[str(job.id)] = handler with self._job_queue_lock: job_priority_queue = self._job_amqp_queues.setdefault(queue, PQ()) # items are fetched by lowest priority value first, so we need to # invert the priorities job_priority_queue.put(((1000-job.priority), handler)) Master.instance().update_status(queues=self._get_queues())
def run_job(self, job): """TODO: Docstring for run_job. :job: TODO :returns: TODO """ self._log.info("running job: {}".format(job.id)) job.priority = self._safe_priority(job.priority) job.save() queue = job.queue if queue is None or queue == "": queue = self.AMQP_JOB_QUEUE handler = JobHandler(job, queue, self) self._job_handlers[str(job.id)] = handler with self._job_queue_lock: job_priority_queue = self._job_amqp_queues.setdefault(queue, PQ()) # items are fetched by lowest priority value first, so we need to # invert the priorities job_priority_queue.put(((1000 - job.priority), handler)) Master.instance().update_status(queues=self._get_queues())
def _handle_configure(self, id_, image): """Configure the image (spin it up, let the user muck around in it, commit all changes back into the original image) """ vagrantfile = image.status.setdefault("vagrantfile", None) user_interaction = image.status.setdefault("user_interaction", False) vnc_info = self._vm_manager.configure_image( str(image.id), vagrantfile = vagrantfile, user_interaction = user_interaction, on_success = self._set_image_ready, kvm = image.status["kvm"] ) self._log.debug("got vnc info from configure image: {!r}".format(vnc_info)) from master import Master Master.instance().update_status(vms=self._get_running_vms()) image = master.models.Image.objects(id=image.id)[0] if user_interaction: image.status = { "name": "configuring", "vnc": vnc_info } image.save()
def _handle_iso_create(self, id_, image): """Handle creating a new VM from scratch using the iso provided in the state object. """ self._log.info("creating new image using iso") iso_id = bson.ObjectId(image.status["iso"]) iso_file = master.models.TmpFile.objects(id=iso_id)[0] if iso_file.path.startswith("/"): iso_file.path = iso_file.path[1:] iso_path = os.path.join("/tmp/talus", iso_file.path) if not os.path.exists(iso_path): self._log.warn("cannot locate iso {!r} for image {!r} creation".format( iso_file.path, image.name, )) iso_file.delete() image.status = { "name": "iso-create error", } image.save() return vnc_info = self._vm_manager.create_from_iso( iso_path = iso_path, #vagrantfile = image.status.setdefault("vagrantfile", None), image_name = str(image.id), username = image.username, password = image.password, on_success = self._set_image_ready, ) from master import Master Master.instance().update_status(vms=self._get_running_vms()) if os.path.exists(iso_file.path): os.remove(iso_file.path) iso_file.delete() image.status = { "name": "configuring", "vnc": vnc_info, } image.save() self._log.info("new VM is starting up with iso {!r}, ready for initial configuration\n {!r}".format( os.path.basename(iso_path), vnc_info, ))
def cancel_job(self, job): """Cancel the job ``job`` :job: The job object to cancel :returns: None """ # TODO forcefully cancel the job (notify all slaves via amqp that # this job.id needs to be forcefully cancelled self._log.info("cancelling job: {}".format(job.id)) if str(job.id) in self._job_handlers: with self._job_queue_lock: handler = self._job_handlers[str(job.id)] queue = self._job_amqp_queues[handler.queue_name] new_queue = [] while queue.qsize() > 0: priority,handler = queue.get() # leave this one out (the one we're cancelling) if handler.job.id == job.id: continue new_queue.append((priority, handler)) for item in new_queue: queue.put(item) Master.instance().update_status(queues=self._get_queues()) else: self._log.debug("job to cancel ({}) not in job handlers, sending cancel message to amqp anyways".format(job.id)) AmqpManager.instance().queue_msg( json.dumps(dict( type = "cancel", job = str(job.id) )), "", exchange=Master.AMQP_BROADCAST_XCHG ) job.reload() job.status = { "name": "cancelled" } job.timestamps["cancelled"] = time.time() job.save() self._log.info("cancelled job: {}".format(job.id)) self._cleanup_job(job)
def _handle_import(self, id_, image): """This is the initial step when importing an image from the API. The API will insert a new Image document into the database with status["name"] set to "importing" """ self._log.info("importing an image") image_to_import = bson.ObjectId(image.status["tmpfile"]) tmp_file = master.models.TmpFile.objects(id=image_to_import)[0] if tmp_file.path.startswith("/"): tmp_file.path = tmp_file.path[1:] image_path = os.path.join("/tmp/talus", tmp_file.path) if not os.path.exists(image_path): self._log.warn("Cannot import image: {!r}, image to import not found ({})".format( image.name, tmp_file.path )) tmp_file.delete() image.status = { "name": "import_error" } image.save() return vnc_info = self._vm_manager.import_image( image_path, str(image.id), # image name user_interaction = True, username = image.username, password = image.password, on_success = self._set_image_ready ) from master import Master Master.instance().update_status(vms=self._get_running_vms()) if os.path.exists(tmp_file.path): os.remove(tmp_file.path) tmp_file.delete() image.status = { "name": "configuring", "vnc": vnc_info } image.save() self._log.info("image is imported and running, ready for initial configuration:\n\t{!r}".format(vnc_info))
def stop_job(self, job): """This is intended to be called once a job has been completed (not cancelled, but completed) """ self._log.info("stopping job: {}".format(job.id)) if str(job.id) in self._job_handlers: with self._job_queue_lock: handler = self._job_handlers[str(job.id)] queue = self._job_amqp_queues[handler.queue_name] new_queue = [] for priority,handler in queue.queue: if handler.job.id == job.id: continue new_queue.append((priority, handler)) queue.queue = new_queue Master.instance().update_status(queues=self._get_queues()) AmqpManager.instance().queue_msg( json.dumps(dict( type = "cancel", job = str(job.id) )), "", exchange=Master.AMQP_BROADCAST_XCHG ) job.reload() job.status = { "name": "finished" } job.timestamps["finished"] = time.time() job.save() self._log.info("stopped job: {}".format(job.id)) self._cleanup_job(job)
def _handle_configure(self, id_, image): """Configure the image (spin it up, let the user muck around in it, commit all changes back into the original image) """ vagrantfile = image.status.setdefault("vagrantfile", None) user_interaction = image.status.setdefault("user_interaction", False) vnc_info = self._vm_manager.configure_image( str(image.id), vagrantfile=vagrantfile, user_interaction=user_interaction, on_success=self._set_image_ready, kvm=image.status["kvm"]) self._log.debug( "got vnc info from configure image: {!r}".format(vnc_info)) from master import Master Master.instance().update_status(vms=self._get_running_vms()) image = master.models.Image.objects(id=image.id)[0] if user_interaction: image.status = {"name": "configuring", "vnc": vnc_info} image.save()
def _on_worker_exited(self): from master import Master Master.instance().update_status(vms=self._get_running_vms())