// Stop tries to start all associated VMs func Stop( buffer *bytes.Buffer, vmrun vmware.VmrunWrapper, config *util.LCMConfiguration) error { // Get all existing clones clones, err := getClones(vmrun, config) if err != nil { return err } util.TryWrite2Columns(buffer, 20, "Clones", fmt.Sprint(len(clones))) util.TryWriteln(buffer, "") for _, clone := range clones { if !clone.running { continue } err := vmrun.Stop(clone.path, true) if err != nil { return err } vmName := tryVMNameExtraction(clone.path) util.TryWrite2Columns(buffer, 20, " Stopped Clone", vmName) } util.TryWriteln(buffer, "") return nil }
// getRunningVMPaths returns the paths of running VMs func getTemplateSnapshots( vmrun vmware.VmrunWrapper, config *util.LCMConfiguration) ([]string, error) { list, err := vmrun.ListSnapshots(config.TemplatePath) if err != nil { return nil, err } lines := strings.Split(list, "\n") // Check if at least one line is there if len(lines) < 1 { return nil, fmt.Errorf("Failed to parse the listSnapshots command") } // Then remove the first line lines = lines[1:] var result []string // Now remove empty lines for _, line := range lines { if len(line) == 0 { continue } result = append(result, line) } return result, nil }
// cloneUpTo clones the template up to <<use>> times func cloneUpTo( vmrun vmware.VmrunWrapper, config *util.LCMConfiguration, clones []*virtualMachine, use int) ([]string, error) { // Assert use greater zero if use <= 0 { return []string{}, nil } // First get available mac addresses availableAddresses := getAvailableMacAddresses(clones, config) // calculate how many clones need to be created diff := math.Max(0, float64(use-len(clones))) toCreate := int(math.Min(float64(len(availableAddresses)), diff)) if toCreate <= 0 { return []string{}, nil } // Get snapshot for the clones snapshot, err := prepareTemplateSnapshot(vmrun, config) if err != nil { return nil, fmt.Errorf("Failed to prepare snapshot\n%s", err.Error()) } var created []string // Now fire the clone command for each of the addresses for i := 0; i < toCreate; i++ { address := availableAddresses[i] vmID := util.MacAddressToVMId(address) vmName := fmt.Sprintf("%s-%s", config.Prefix, vmID) vmxPath := fmt.Sprintf( "%s%s.vmwarevm/%s.vmx", config.ClonesDirectory, vmName, vmName) // First create the linked clone err := vmrun.CloneLinked( config.TemplatePath, config.ClonesDirectory, vmName, snapshot) if err != nil { return nil, fmt.Errorf("Failed to clone vm %s\n%s", vmName, err.Error()) } // Then configure that clone with the mac address err = util.UpdateVMX(vmxPath, vmxPath, address) if err != nil { return nil, fmt.Errorf("Failed to configure the linked clone %s\n%s", vmName, err.Error()) } created = append(created, vmName) } return created, nil }
// getRunningVMPaths returns the paths of running VMs func getRunningVMPaths( vmrun vmware.VmrunWrapper) ([]string, error) { list, err := vmrun.List() if err != nil { return nil, err } matches := listVMPaths.FindAllString(list, -1) return matches, nil }
// createTemplateSnapshot creates a prefixed snapshot of the template func createTemplateSnapshot( vmrun vmware.VmrunWrapper, config *util.LCMConfiguration) (string, error) { timestamp := int(time.Now().Unix()) // Create snapshot name snapshotName := fmt.Sprintf("%s-%d", config.Prefix, timestamp) err := vmrun.Snapshot(config.TemplatePath, snapshotName) if err != nil { return "", err } return snapshotName, nil }
// getVmrunVersion returns version information of the used vmrun executable func getVmrunVersion( vmrun vmware.VmrunWrapper) (*vmrunVersion, error) { help, err := vmrun.Help() if err != nil { return nil, err } matches := helpVmrunVersion.FindStringSubmatch(help) if len(matches) < 3 { return nil, fmt.Errorf("Could not parse vmrun version information") } result := new(vmrunVersion) // index 0 is the whole match itself result.version = matches[1] result.build = matches[2] return result, nil }
// getRunningVMNumber returns the number of running vms func getRunningVMNumber( vmrun vmware.VmrunWrapper) (int, error) { list, err := vmrun.List() if err != nil { return 0, err } matches := listVMNumber.FindStringSubmatch(list) if len(matches) < 2 { return 0, fmt.Errorf("Could not parse vm number information") } number, err := strconv.Atoi(matches[1]) if err != nil { return 0, fmt.Errorf("Could not parse regex match as integer") } return number, nil }
// Deletes up to <<use>> clones func deleteUpTo( vmrun vmware.VmrunWrapper, config *util.LCMConfiguration, clones []*virtualMachine, use int) ([]string, error) { // First order the clones by status clonesOrdered := orderClonesByRunning(clones) toDelete := int(math.Min( float64(len(clonesOrdered)), math.Abs(float64(len(clones)-use)))) var deletedClones []string // Then shutdown target clones for i := 0; i < toDelete; i++ { clone := clones[i] // First try to stop the clone if it is running if clone.running { // First try a soft stop err := vmrun.Stop(clone.path, false) if err != nil { // then try a hard stop err = vmrun.Stop(clone.path, true) if err != nil { return nil, err } } } // Run Vmrun delete err := vmrun.Delete(clone.path) if err != nil { return nil, err } // Try to find the vmName vmxMatch := vmxName.FindStringSubmatch(clone.path) if len(vmxMatch) != 2 { deletedClones = append(deletedClones, clone.path) } else { vmName := strings.TrimSuffix(vmxMatch[1], ".vmx") deletedClones = append(deletedClones, vmName) } } return deletedClones, nil }