def check_keyword(keyword_name): try: STREAM.debug(" -> Check for keyword:") keyword = importlib.import_module("vmaker.keywords.%s" % keyword_name) STREAM.debug(" %s" % keyword) STREAM.debug(" -> Check for a class <Keyword>:") cls = getattr(keyword, "Keyword") STREAM.debug(" %s" % cls) STREAM.debug(" -> Check for entrypoint <main>:") entry = getattr(cls, "main") STREAM.debug(" %s" % entry) STREAM.debug(" -> Check for REQUIRED_CONFIG_ATTRS:") entry = getattr(cls, "REQUIRED_CONFIG_ATTRS") STREAM.debug(" %s" % entry) STREAM.success(_aligner(" -> Checking and loading keyword <%s>" % keyword_name, "OK")) except ImportError as err: STREAM.warning(_aligner(" -> Checking and loading keyword <%s>" % keyword_name, "FAILED")) STREAM.critical(" -> %s" % err) sys.exit() except AttributeError as err: STREAM.warning(_aligner(" -> Checking and loading keyword <%s>" % keyword_name, "FAILED")) STREAM.critical(" -> %s" % err) sys.exit() finally: sleep(0.1)
def run_playbook(self, playbook, inventory): options = self.parse_options() STREAM.info("==> Execute Ansible playbook: %s" % playbook) # initialize needed objects loader = DataLoader() passwords = {} inventory = InventoryManager(loader=loader, sources=inventory) variable_manager = VariableManager(loader=loader, inventory=inventory) # create the playbook executor, which manages running the plays via a task queue manager pbex = PlaybookExecutor(playbooks=[playbook], inventory=inventory, variable_manager=variable_manager, loader=loader, options=options, passwords=passwords) # run playbook and return exit_code results = pbex.run() if results == 0: STREAM.success(" -> Successfully executed.") else: raise Exception( " -> Ansible playbook(%s) exited with error_code: %s" % (playbook, results)) # Clean ansible temp files shutil.rmtree(C.DEFAULT_LOCAL_TMP, True)
def start_cache(self): pool = Pool(self.WORKERS) for status in pool.map(self.parallel_cache, self.nodes): if "ERROR" in status: STREAM.error(status) else: STREAM.success(status)
def mount_vbox_guestadditions(self, ssh): """ Method to mount VirtualBoxGuestAdditions.iso to VirtualMachine """ Popen( 'vboxmanage storageattach %s --storagectl "IDE" --port 1 --device 0' ' --type dvddrive --medium %s --forceunmount' % (self.vm_name, "emptydrive"), shell=True, stdout=PIPE, stderr=PIPE).communicate() last_realese = self.get_vboxga_latest_realese() iso = self.get_vbox_guestadditions_iso(last_realese) if self.check_vbox_guestadditions_version(ssh) == last_realese: STREAM.success( " -> VboxGuestAdditions have a latest version (%s)." % last_realese) return False Popen('vboxmanage storageattach %s --storagectl "IDE"' ' --port 1 --device 0 --type dvddrive --medium %s' % (self.vm_name, iso), shell=True, stdout=PIPE, stderr=PIPE).communicate() sleep(1) ssh.exec_command("mkdir /mnt/dvd") ssh.exec_command("mount -t iso9660 -o ro /dev/cdrom /mnt/dvd") sleep(1) return True
def try_connect(ssh): """ Recursive function to enable multiple connection attempts """ try: ssh.connect(self.ssh_server, port=int(self.ssh_port), username=self.ssh_user, password=self.ssh_password) STREAM.success(" -> Connection established") except Exception as err: STREAM.warning(" -> Fail (%s)" % err) if "ecdsakey" in str(err): STREAM.warning("ECDSAKey error, try to fix.") Popen('ssh-keygen -f %s -R "[%s]:%s"' % (os.path.join( os.path.expanduser("~"), ".ssh/known_hosts"), self.ssh_server, self.ssh_port), shell=True, stdout=PIPE, stderr=PIPE).communicate() if self.connect_tries > 20: raise paramiko.ssh_exception.SSHException( "Connection retries limit exceed!") self.connect_tries += 1 STREAM.info(" -> Connection retry %s:" % self.connect_tries) sleep(15) try_connect(ssh)
def main(self): # - Attributes taken from config self.vm_name = self.vm_name self.vagrant_catalog = self.vagrant_catalog # ---------------------------- if self.vagrant_catalog.endswith("/"): self.vagrant_catalog = self.vagrant_catalog[:-1] self.vagrant_server_url = LoadSettings.VAGRANT_SERVER_URL if self.vagrant_server_url == "": raise Exception( "Parameter 'vagrant_server_url' not specified, you must specify it in vmaker.ini" ) if self.vagrant_server_url.endswith("/"): self.vagrant_server_url = self.vagrant_server_url[:-1] self.vagrant_server_url = LoadSettings.VAGRANT_SERVER_URL.replace( "//", "\/\/") self.provider = "virtualbox" self.version = datetime.now().strftime("%Y%m%d%H%M") self.boxname = "%s_%s_%s.box.prep" % (self.vm_name, self.version, self.provider) result = self.export_vm_configuration() if result: self.create_vagrant_template() self.create_box() self.create_metadata_file() self.renew_vm() STREAM.success( "==> Exporting into vagrant successfully completed.")
def generate_from_path(path): """ Generating config based on path to Virtual box """ cfg = os.path.join(LoadSettings.WORK_DIR, "generated.ini") config = ConfigParser() config.read(cfg) for vm in os.listdir(path): if os.path.isdir(os.path.join(path, vm)): config.add_section(vm) config.set(vm, "type", "vm") config.set(vm, "vm_name", vm) with open(cfg, "w") as conf: config.write(conf) STREAM.success("Generated %s" % cfg)
def vbox_guestadditions_update(self, ssh): """ Method to update Virtual Box Guest Additions in VirtualMachine """ STREAM.info("==> Updating VboxGuestAdditions.") if not self.mount_vbox_guestadditions(ssh): return STREAM.debug(" -> Execute update GuestAdditions.") ssh_stdin, ssh_stdout, ssh_stderr = ssh.exec_command( "/mnt/dvd/VBoxLinuxAdditions.run 2>&1", environment={"LC_ALL": "C"}) ssh_stdin.write("y\n") ssh_stdin.flush() stdout = ssh_stdout.read() if "Running kernel modules will not be replaced" in stdout: STREAM.success(" -> VboxGuestAdditions updated") else: STREAM.error(stdout)
def command_exec(self, ssh, command, stdin=""): """ Method to execute remote command via ssh connection """ STREAM.info(" -> Executing command: %s" % command) ssh_stdin, ssh_stdout, ssh_stderr = ssh.exec_command(command) ssh_stdin.write(stdin) ssh_stdin.flush() stdout = ssh_stdout.read() stderr = ssh_stderr.read() STREAM.debug(self.get_decoded(stdout)) if len(stderr) > 0: STREAM.debug(self.get_decoded(stderr)) exit_code = ssh_stdout.channel.recv_exit_status() STREAM.debug(" -> Command exitcode: %s" % exit_code) if exit_code == 0: STREAM.success(" -> Command executed successfully") else: raise Exception("Executed command exit status not 0")
def get_vbox_guestadditions_iso(self, version): """ Method to download VirtualBoxGuestAdditions.iso from Virtual Box server """ filename = "VBoxGuestAdditions_%s.iso" % version download_path = os.path.join(LoadSettings.WORK_DIR, filename) if os.path.exists(download_path): return download_path Popen('rm -rf %s' % os.path.join(LoadSettings.WORK_DIR, "*.iso"), shell=True, stdout=PIPE, stderr=PIPE).communicate() download_link = self.vbox_url + version + "/" + filename STREAM.debug(" -> download link: %s" % download_link) iso = requests.get(download_link).content STREAM.info(" -> Downloading VboxGuestAdditions...") with open(download_path, "wb") as ga: ga.write(iso) STREAM.success(" -> Downloaded: %s" % download_path) return download_path
def restore_from_snapshot(self): STREAM.info("==> Restore VirtualMachine state from snapshot: '%s'" % self.snapshot_name) result = Popen('VBoxManage snapshot %s restore %s' % (self.vm_name, self.snapshot_name), shell=True, stdout=PIPE, stderr=PIPE).communicate() if len(result[1]) > 0: if "0%...10%...20%...30%...40%...50%...60%...70%...80%...90%...100%" not in result[ 1]: if "VBOX_E_OBJECT_NOT_FOUND" in result[1]: raise Exception( "Snapshot with name '%s' not found for this VirtualMachine" % self.snapshot_name) else: raise Exception(result[1]) STREAM.debug(result) STREAM.success(" -> Restore complete.")
def cache_image(self, nova, depth=3): """ Method to cache image on one random node. """ server = self.create_instance(nova) STREAM.debug(" -> Created instance: %s" % server) # if recursion will not breaked, whatever keyword will be terminated by vmaker timeout. while True: sleep(2) status = self.get_instance_status(nova, server.id) STREAM.debug(" -> Creation status: %s" % status) if status == "ACTIVE": self.delete_instance(nova, server) STREAM.success(" -> Image has been cached.") break elif status == "ERROR": self.delete_instance(nova, server) STREAM.warning(" -> Unexpected error while launch instance") if depth == 0: break STREAM.warning(" -> Trying to cache image again.") self.cache_image(nova, depth=depth - 1) break
def upload_image(self, connection): """ Method to upload image to the openstack cluster """ args = self.get_image_properties() args["name"] = self.openstack_image_name STREAM.info("==> Uploading image...") STREAM.debug(" -> Image properties: %s" % args) # Find where vm files are located vm_dir = self.find_vm_files() if vm_dir is None: return # Find specified disk format in vm directory. disk = None for fil in os.listdir(vm_dir): if fil.endswith(args["disk_format"]): disk = os.path.join(vm_dir, fil) if disk is None: STREAM.error("%s disk not found in %s\nMake sure that you are specify a right disk_format " "in parameter(openstack_image_properties) or the disk exists." % (args["disk_format"], vm_dir)) STREAM.error("Export in openstack canceled.") return STREAM.debug(" -> VirtualMachine's virtual hard drive location: %s" % disk) # Get image id, if image with specified name already exists old_image_id = self.image_exists(connection, args["name"]) # Create image object with specified properties. image = connection.images.create(**args) # create file with created image id image_id_file = os.path.join(LoadSettings.WORK_DIR, ".openstack_export.tmp") with open(image_id_file, "w") as tmp: tmp.write(image.id) # Uploading image. connection.images.upload(image.id, open(disk, 'rb')) STREAM.success(" -> Uploading complete.") # if all ok remove tmp file os.remove(image_id_file) if old_image_id is not None: STREAM.info(" -> Remove old image.") self.delete_image(connection, old_image_id) STREAM.debug(" -> Removed image with id: %s" % old_image_id) STREAM.success(" -> Removed.")
def command_exec(self, ssh, command, stdin="", get_pty=False): """ Method to execute remote command via ssh connection """ def line_buffered(f): """ Iterator object to get output in realtime from stdout buffer """ while not f.channel.exit_status_ready(): yield self.get_decoded(f.readline().strip()) STREAM.info(" -> Executing command: %s" % command) ssh_stdin, ssh_stdout, ssh_stderr = ssh.exec_command(command, get_pty=get_pty) ssh_stdout._set_mode("rb") ssh_stdin.write(stdin) ssh_stdin.flush() for l in line_buffered(ssh_stdout): STREAM.debug(l) stderr = ssh_stderr.read() if len(stderr) > 0: try: raise Exception(stderr) except UnicodeDecodeError: raise Exception(self.get_decoded(stderr)) STREAM.success(" -> Command executed successfully")
def main(self): # - Attributes taken from config self.vm_name = self.vm_name self.forwarding_ports = self.forwarding_ports self.credentials = self.credentials self.management_type = self.management_type # ------------------------------------------- # Setting attributes to invoked keywords vbox_stop.vm_name = self.vm_name vbox_start.vm_name = self.vm_name STREAM.info("==> Updating VirtualMachine.") self.get_connection_settings() if self.management_type == "ssh": ssh = self.ssh_connect_to_vm() else: raise Exception( "Don't know how to connect to vm! (parameter 'management_type' has unknown value)" ) self.detected_os = self.get_vm_platform(ssh) # Invoke update method update_method = getattr(self, "update_%s" % self.detected_os) update_method(ssh) STREAM.success(" -> VirtualMachine has been updated.")
def upload_script_and_execute(self, ssh, parameter): Platform = self.get_platform(ssh) if parameter.strip().startswith("script:"): parameter = parameter[7:] try: shell, filepath = parameter.strip().split(":") except ValueError: shell = None filepath = parameter.strip() STREAM.info(" -> Executing script: %s" % filepath) if Platform == "win-like": STREAM.debug(" -> Remote system probably is windows type") temppath = os.path.join("C:\Windows\Temp", os.path.basename(filepath)) default_shell = r"C:\Windows\System32\cmd.exe /c start" else: STREAM.debug(" -> Remote system probably is unix type") temppath = os.path.join("/tmp", os.path.basename(filepath)) default_shell = "bash" if shell is None: STREAM.debug(" -> Shell is not specified, using default: %s" % default_shell) shell = default_shell scp = SCPClient(ssh.get_transport()) scp.put(filepath, temppath) scp.close() ssh_stdin, ssh_stdout, ssh_stderr = ssh.exec_command("%s %s" % (shell, temppath)) stdout = ssh_stdout.read() stderr = ssh_stderr.read() STREAM.debug(self.get_decoded(stdout)) if len(stderr) > 0: STREAM.debug(self.get_decoded(stderr)) exit_code = ssh_stdout.channel.recv_exit_status() STREAM.debug(" -> Script exitcode: %s" % exit_code) if exit_code == 0: STREAM.success(" -> Script executed successfully") else: raise Exception("Executed script exit status not 0")
def load_config(self): STREAM.info("==> Loading user configuration file...") config = ConfigParser() config.read(self.CONFIG_FILE) aliases, groups, vms, cmds = {}, {}, {}, {} # - Generating aliases objects STREAM.debug("==> Generating alias objects...") for sec in config.sections(): STREAM.debug(" -> Loading section '%s'" % sec) try: if config[sec]["type"] == "aliases": STREAM.debug(" [%s] Section seems like alias object" % sec) args = { key: [val.strip() for val in value.split(",")] for key, value in config.items(sec) if key != "type" } STREAM.debug(" [%s] -> Section attributes: %s" % (sec, args)) if config.has_option(sec, "group"): STREAM.debug( " [%s] -> Section have <group> attribute: assigned to group %s" % (sec, str(config[sec]["group"]))) aliases[str(config[sec]["group"])] = type( str(config[sec]["group"]), (object, ), {"aliases": args}) STREAM.debug( " [%s] -> Object attributes: %s" % (sec, dir(aliases[str(config[sec]["group"])]))) else: STREAM.debug( " [%s] -> Section don't have <group> attribute: assigned to global context" % sec) aliases["global"] = type("global", (object, ), {"aliases": args}) STREAM.debug(" [%s] -> Object attributes: %s" % (sec, dir(aliases["global"]))) else: STREAM.debug( " [%s] Section doesn't seem like alias object. Passed..." % sec) except KeyError as wrong_key: STREAM.error( " -> Config Error: Wrong section '%s' Key %s not specified" % (sec, wrong_key)) sys.exit() STREAM.debug("[*] ==> Generated alias objects: %s\n" % aliases) # - Generating group objects STREAM.debug("==> Generating group objects...") for sec in config.sections(): STREAM.debug(" -> Loading section '%s'" % sec) try: if config[sec]["type"] == "group": STREAM.debug(" [%s] Section seems like group object" % sec) args = { key: value for key, value in config.items(sec) if key != "type" } STREAM.debug(" [%s] -> Section attributes: %s" % (sec, args)) if aliases != {}: STREAM.debug( " [%s] -> Alias objects detected: object will generated with alias inheritance" % sec) if aliases.get(sec) is None and aliases.get( "global") is None: # => alias null STREAM.debug( " [%s] -> Group alias: False, Global alias: False -> object will generated without alias inheritance" % sec) groups[sec] = type(str(sec), (object, ), args) STREAM.debug(" [%s] -> Object attrs: %s" % (sec, groups[sec].aliases)) elif aliases.get(sec) is not None and aliases.get( "global") is not None: # => alias group + global STREAM.debug( " [%s] -> Group alias: True, Global alias: True -> alias group + global alias inheritance" % sec) complex_alias = dict( aliases.get(sec).aliases, **aliases.get("global").aliases) aliases.get(sec).aliases = complex_alias groups[sec] = type(str(sec), (aliases.get(sec), ), args) STREAM.debug(" [%s] -> Object aliases: %s" % (sec, groups[sec].aliases)) elif aliases.get(sec) is not None: # => alias group STREAM.debug( " [%s] -> Group alias: True, Global alias: False -> alias group inheritance" % sec) groups[sec] = type(str(sec), (aliases.get(sec), ), args) STREAM.debug(" [%s] -> Object attrs: %s" % (sec, groups[sec].aliases)) elif aliases.get("global") is not None: # => alias global STREAM.debug( " [%s] -> Group alias: False, Global alias: True -> global alias inheritance" % sec) groups[sec] = type(str(sec), (aliases.get("global"), ), args) STREAM.debug(" [%s] -> Object attrs: %s" % (sec, groups[sec].aliases)) else: STREAM.debug( " [%s] -> Alias objects not detected: object will generated without alias inheritance" % sec) # => alias null groups[sec] = type(str(sec), (object, ), args) else: STREAM.debug( " [%s] Section doesn't seem like group object. Passed..." % sec) except KeyError as wrong_key: STREAM.error( " -> Config Error: Wrong section '%s' Key '%s' not specified" % (sec, wrong_key)) sys.exit() STREAM.debug("[*] ==> Generated group objects: %s\n" % groups) # - Generating VM objects STREAM.debug("==> Generating vm objects...") vms_work_sequence = [] for sec in config.sections(): STREAM.debug(" -> Loading section '%s'" % sec) try: if config[sec]["type"] == "vm": STREAM.debug(" [%s] Section seems like vm object" % sec) args = { key: value for key, value in config.items(sec) if key != "type" and key != "group" and key != "actions" } STREAM.debug(" [%s] -> Section attributes: %s" % (sec, args)) # firstly check if vm section exists action attr # then below check maybe it inherit from group try: act = config[sec]["actions"] args["actions"] = act except KeyError: pass # alias inheritance added in group generation step if config.has_option(sec, "group") and groups.get( config[sec]["group"]) is not None: STREAM.debug( " [%s] Assigned group detected: inherit attributes " "from group '%s'" % (sec, config[sec]["group"])) vms[sec] = type(str(sec), (groups.get(config[sec]["group"]), ), args) else: # if group doesn't exist or no group, adding alias inheritance STREAM.debug( " [%s] Assigned group not detected: assign aliases" % sec) if aliases.get("global") is None: STREAM.debug( " [%s] Aliases not assigned: no aliases" % sec) # => alias null vms[sec] = type(str(sec), (), args) else: STREAM.debug(" [%s] Aliases assigned: global" % sec) # => alias global vms[sec] = type(str(sec), (aliases.get("global"), ), args) # Check if 'action' attr was inherited from group try: acts = getattr(vms[sec], "actions") setattr(vms[sec], "actions", [action.strip() for action in acts.split(",")]) retro = " [%s] Section inheritance retrospective:" final_attrs = { attr for attr in dir(vms[sec]) if not attr.startswith('__') } for attr in final_attrs: val = getattr(vms[sec], attr) retro += "\n\t\t\t\t\t\t%s = %s" % (attr, val) STREAM.debug(retro % sec) vms_work_sequence.append(sec) except AttributeError as wrong_key: STREAM.error(" -> Config Error: Wrong section '%s'" " Key %s not specified" % (sec, str(wrong_key).split(" ")[-1])) del vms[sec] sys.exit() else: STREAM.debug( " [%s] Section doesn't seem like vm object. Passed..." % sec) except KeyError as wrong_key: STREAM.error( " -> Config Error: Wrong section '%s' Key '%s' not specified" % (sec, wrong_key)) sys.exit() STREAM.debug("[*] ==> Generated vm objects: %s" % vms) STREAM.debug("[*] ==> Generated vm objects work sequence: %s" % vms_work_sequence) STREAM.debug("==> Finding sections with executions...") for sec in config.sections(): try: if config[sec]["type"] == "executions": STREAM.debug(" -> Found section '%s'" % sec) args = { key: value for key, value in config.items(sec) if key != "type" } cmds = dict(cmds, **args) except KeyError as wrong_key: STREAM.error( " -> Config Error: Wrong section '%s' Key '%s' not specified" % (sec, wrong_key)) sys.exit() STREAM.debug("[*] ==> Found executions aliases: %s" % cmds) STREAM.success(" -> User configuration file loaded") return vms, vms_work_sequence, cmds
def check_attributes_dependencies(self): STREAM.info("==> Checking for keywords required attributes.") for vm in self.config_sequence: # Set of required attributes for all Keywords used in the VirtualMachine req_args = set() STREAM.debug("==> VirtualMachine: %s" % vm) for action in self.config[vm].actions: try: # List of required attributes for the Keyword to work req_attr = self.loaded_keywords[ action].REQUIRED_CONFIG_ATTRS # Add required attributes of current action to summary set req_args = set(req_args) | set(req_attr) except KeyError: # If action not in executions section, check for aliases if action not in self.executions.keys(): # Check aliases actions for required attributes try: aliases = self.config[vm].aliases[action] # Intercept if VirtualMachine have no aliases except KeyError as key: STREAM.error( "The keyword (%s) you use in the configuration file does not exist or is not enabled." % key) STREAM.warning( "You can't use this keyword until you turn it on in .vmaker.ini" ) sys.exit(1) # Intercept if VirtualMachine have no aliases except AttributeError: STREAM.error( "The keyword (u'%s') you use in the configuration file does not exist or is not enabled." % action) STREAM.warning( "You can't use this keyword until you turn it on in .vmaker.ini" ) sys.exit(1) for act in aliases: req_attr = self.loaded_keywords[ act].REQUIRED_CONFIG_ATTRS req_args = set(req_args) | set(req_attr) vm_attrs = [ name for name in dir(self.config[vm]) if not name.startswith('__') ] req_args = set(req_args) vm_attrs = set(vm_attrs) STREAM.debug(" -> [%s] Required attributes for actions: %s" % (vm, req_args)) STREAM.debug(" -> [%s] VirtualMachines attributes: %s" % (vm, vm_attrs)) # Attributes comparison result = req_args - vm_attrs if len(result) > 0: STREAM.error( " -> Section <%s> missed required attributes %s." % (vm, list(result))) STREAM.error( " -> This causes problems in the operation of some keywords. Check your user configuration file." ) sys.exit() STREAM.success(" -> All attributes are present.")
def forward(self): self.forwarding_ports = [ ports.strip() for ports in self.forwarding_ports.split(",") ] for item in self.forwarding_ports: ports_rule = item.split(":") if len(ports_rule) == 3: name, guest, host = ports_rule name, guest, host = name.strip(), guest.strip(), host.strip() name = "vmaker_" + name elif len(ports_rule) == 2: name, auto = ports_rule name, auto = name.strip(), auto.strip() if name == "manage" and auto == "auto": name, guest, host = self.generate_auto() else: continue else: continue STREAM.debug("%s, %s, %s" % (name, guest, host)) check_name = Popen("vboxmanage showvminfo %s |grep -i %s" % (self.vm_name, name), shell=True, stdout=PIPE, stderr=PIPE).communicate() if check_name[0] != "": STREAM.debug( " -> Detecting previosly set up rule with the same name.") Popen("vboxmanage modifyvm %s --natpf1 delete %s" % (self.vm_name, name), shell=True, stdout=PIPE, stderr=PIPE).communicate() STREAM.debug(" -> Deleted rule: %s" % name) STREAM.debug(" -> Set up new rule: %s" % name) result = Popen( "vboxmanage modifyvm %s --natpf1 %s,tcp,127.0.0.1,%s,,%s" % (self.vm_name, name, host, guest), shell=True, stdout=PIPE, stderr=PIPE).communicate() if len(result[1]) > 0: raise Exception(result[1]) else: check_port = Popen( "vboxmanage showvminfo %s |grep -i 'host port = %s'" % (self.vm_name, host), shell=True, stdout=PIPE, stderr=PIPE).communicate() if check_port[0] != "": raise Exception( " -> Host port(%s) already in use! Check your VirtualMachine settings." % host) result = Popen( "vboxmanage modifyvm %s --natpf1 %s,tcp,127.0.0.1,%s,,%s" % (self.vm_name, name, host, guest), shell=True, stdout=PIPE, stderr=PIPE).communicate() if len(result[1]) > 0: raise Exception(result[1]) STREAM.debug(result) STREAM.success(" -> Forwarded ports %s(guest) => %s(host)" % (guest, host))
def create_snapshot(self): STREAM.info("==> Create a snapshot with name: '%s'" % self.snapshot_name) result = Popen('VBoxManage snapshot %s take %s' % (self.vm_name, self.snapshot_name), shell=True, stdout=PIPE, stderr=PIPE).communicate() STREAM.debug(result) STREAM.success(" -> Snapshot created")
def generate_default_config(config_file): template = """; You can create vm objects and assign them any actions. ; Specify preffered section name. [debian9-x86-template] ; Mandatory keys. ; Key specifies, which type of object will be created (vm, group, alias). type = vm ; Key specifies Keywords which will be performed for this VirtualMachine actions = port_forwarding, vbox_start, execute_command, vbox_stop ; Variable keys ; Key specifies to which group this object belongs. group = linux ; You may specify email to receive notifications about Keyword's errors. ;alert = [email protected] ; That description will be shown in subject of the email ;alert_description = install curl in vm ; Attributes needed for the correct work of a Keyword's ; name of the virtual machine in VirtualBox. vm_name = debian9-x86-template ; Command which will be executed in VirtualMachine by Keyword "execute_command" execute_command = apt-get install -y clamav [fedora27-amd64] type = vm ; actions will be inherited from group group = linux vm_name = fedora27-amd64 execute_command = dnf install -y clamav [freebsd10-amd64] type = vm group = linux vm_name = freebsd10-amd64 execute_command = pkg install -y clamav ; You can create groups and combine it with other objects. ; Groups support attribute inheritance (groups attributes have a lower priority than vm attributes). ; Specify name of the group. [linux] ; Mandatory key. type = group ; Key specifies keywords which will be performed for the group of VirtualMachines. actions = port_forwarding, vbox_start, execute_command, vbox_stop ; You can specify a timeout for each Keyword after which the process will be terminated (ex: <Keyword_name>_timeout) execute_command_timeout = 10 ; You can combine some Keywords in one action, named alias. [linux_aliases] type = alias ; By default aliases extends to all objects, but you can assign aliases at specific group ;group = linux reboot = vbox_stop, vbox_start """ STREAM.info("==> Generating default configuration file...") if os.path.exists(config_file): STREAM.warning(" -> File %s already exists!" % config_file) STREAM.warning(" -> Do you want to overwrite it? (y/n): ") answers = ["y", "n"] while 1: choice = raw_input().lower() if choice in answers: break STREAM.error("Choose y or n! : ") if choice == answers[0]: with open(config_file, "w") as config: config.write(template) STREAM.success(" -> Generated %s" % config_file) else: STREAM.notice(" -> Cancelled by user.") sys.exit() else: with open(config_file, "w") as config: config.write(template) STREAM.success(" -> Generated %s" % config_file)
def export_vm_configuration(self): """ Method to export VirtualMachine configuration from Virtual Vox """ STREAM.info("==> Checking if vm exists...") vms = Popen("vboxmanage list vms |awk '{print $1}'", shell=True, stdout=PIPE, stderr=PIPE).communicate() vms = vms[0] if not self.vm_name in vms: STREAM.error( " -> VirtualMachine doesn't exist!\nMake sure that the VirtualMachine" " you specified in the parameter(vm_name) are exists.") return False STREAM.success(" -> Exists: True") STREAM.info("==> Exporting configuration...") STREAM.debug(" -> vagrant catalog directory: %s" % self.vagrant_catalog) if not os.path.exists(self.vagrant_catalog): STREAM.error( " -> Vagrant catalog (%s) does not exist!\nMake sure that the catalog" " you specified in the parameter(vagrant_catalog) are exists." % self.vagrant_catalog) STREAM.warning(" -> Export in vagrant, passed.") return False self.work_dir = os.path.join(self.vagrant_catalog, self.vm_name) self.tmp_dir = os.path.join(self.vagrant_catalog, self.vm_name, "tmp") try: os.makedirs(self.tmp_dir) except OSError as errno: if "Errno 17" in str(errno): STREAM.debug( "==> Temporary directory detected, cleaning before start..." ) shutil.rmtree(self.tmp_dir) STREAM.debug(" -> Removed: %s" % self.tmp_dir) os.makedirs(self.tmp_dir) else: STREAM.error(errno) return False result = Popen( 'VBoxManage export %s --output %s' % (self.vm_name, os.path.join(self.tmp_dir, self.vm_name + ".ovf")), shell=True, stdout=PIPE, stderr=PIPE).communicate() if len(result[1]) > 0: if "0%...10%...20%...30%...40%...50%...60%...70%...80%...90%...100%" not in result[ 1]: raise Exception(result[1]) diskname = "" for fil in os.listdir(self.tmp_dir): if fil.endswith(".vmdk"): diskname = fil os.rename(os.path.join(self.tmp_dir, fil), os.path.join(self.tmp_dir, "box-disk.vmdk")) elif fil.endswith(".ovf"): os.rename(os.path.join(self.tmp_dir, fil), os.path.join(self.tmp_dir, "box.ovf")) with open(os.path.join(self.tmp_dir, "box.ovf"), "r") as ovf: ovf_file = ovf.read() with open(os.path.join(self.tmp_dir, "box.ovf"), "w") as ovf: ovf.write(ovf_file.replace(diskname, "box-disk.vmdk")) return True