예제 #1
0
// Upload stemcell to an IAAS. It does the following steps:
// 1) uploads the stemcell to the cloud (if needed),
// 2) saves a record of the uploaded stemcell in the repo
func (m *manager) Upload(extractedStemcell ExtractedStemcell, uploadStage biui.Stage) (cloudStemcell CloudStemcell, err error) {
	manifest := extractedStemcell.Manifest()
	stageName := fmt.Sprintf("Uploading stemcell '%s/%s'", manifest.Name, manifest.Version)
	err = uploadStage.Perform(stageName, func() error {
		foundStemcellRecord, found, err := m.repo.Find(manifest.Name, manifest.Version)
		if err != nil {
			return bosherr.WrapError(err, "Finding existing stemcell record in repo")
		}

		if found {
			cloudStemcell = NewCloudStemcell(foundStemcellRecord, m.repo, m.cloud)
			return biui.NewSkipStageError(bosherr.Errorf("Found stemcell: %#v", foundStemcellRecord), "Stemcell already uploaded")
		}

		cid, err := m.cloud.CreateStemcell(manifest.ImagePath, manifest.CloudProperties)
		if err != nil {
			return bosherr.WrapErrorf(err, "creating stemcell (%s %s)", manifest.Name, manifest.Version)
		}

		stemcellRecord, err := m.repo.Save(manifest.Name, manifest.Version, cid)
		if err != nil {
			//TODO: delete stemcell from cloud when saving fails
			return bosherr.WrapErrorf(err, "saving stemcell record in repo (cid=%s, stemcell=%s)", cid, extractedStemcell)
		}

		cloudStemcell = NewCloudStemcell(stemcellRecord, m.repo, m.cloud)
		return nil
	})
	if err != nil {
		return cloudStemcell, err
	}

	return cloudStemcell, nil
}
func (vm SoftLayerVM) getAllowedHostCredential(virtualGuest datatypes.SoftLayer_Virtual_Guest) (AllowedHostCredential, error) {
	virtualGuestService, err := vm.softLayerClient.GetSoftLayer_Virtual_Guest_Service()
	if err != nil {
		return AllowedHostCredential{}, bosherr.WrapError(err, "Cannot get softlayer virtual guest service.")
	}

	allowedHost, err := virtualGuestService.GetAllowedHost(virtualGuest.Id)
	if err != nil {
		return AllowedHostCredential{}, bosherr.WrapErrorf(err, "Cannot get allowed host with instance id: %d", virtualGuest.Id)
	}
	if allowedHost.Id == 0 {
		return AllowedHostCredential{}, bosherr.Errorf("Cannot get allowed host with instance id: %d", virtualGuest.Id)
	}

	allowedHostService, err := vm.softLayerClient.GetSoftLayer_Network_Storage_Allowed_Host_Service()
	if err != nil {
		return AllowedHostCredential{}, bosherr.WrapError(err, "Cannot get network storage allowed host service.")
	}

	credential, err := allowedHostService.GetCredential(allowedHost.Id)
	if err != nil {
		return AllowedHostCredential{}, bosherr.WrapErrorf(err, "Cannot get credential with allowed host id: %d", allowedHost.Id)
	}

	return AllowedHostCredential{
		Iqn:      allowedHost.Name,
		Username: credential.Username,
		Password: credential.Password,
	}, nil
}
예제 #3
0
func (p partedPartitioner) GetDeviceSizeInBytes(devicePath string) (uint64, error) {
	p.logger.Debug(p.logTag, "Getting size of disk remaining after first partition")

	stdout, _, _, err := p.cmdRunner.RunCommand("parted", "-m", devicePath, "unit", "B", "print")
	if err != nil {
		return 0, bosherr.WrapErrorf(err, "Getting remaining size of `%s'", devicePath)
	}

	allLines := strings.Split(stdout, "\n")
	if len(allLines) < 3 {
		return 0, bosherr.Errorf("Getting remaining size of `%s'", devicePath)
	}

	partitionInfoLines := allLines[1:3]
	deviceInfo := strings.Split(partitionInfoLines[0], ":")
	deviceFullSizeInBytes, err := strconv.ParseUint(strings.TrimRight(deviceInfo[1], "B"), 10, 64)
	if err != nil {
		return 0, bosherr.WrapErrorf(err, "Getting remaining size of `%s'", devicePath)
	}

	firstPartitionInfo := strings.Split(partitionInfoLines[1], ":")
	firstPartitionEndInBytes, err := strconv.ParseUint(strings.TrimRight(firstPartitionInfo[2], "B"), 10, 64)
	if err != nil {
		return 0, bosherr.WrapErrorf(err, "Getting remaining size of `%s'", devicePath)
	}

	remainingSizeInBytes := deviceFullSizeInBytes - firstPartitionEndInBytes - 1

	return remainingSizeInBytes, nil
}
func (s *systemInterfaceAddrs) Get() ([]InterfaceAddress, error) {
	ifaces, err := net.Interfaces()
	if err != nil {
		return []InterfaceAddress{}, bosherr.WrapError(err, "Getting network interfaces")
	}

	interfaceAddrs := []InterfaceAddress{}

	for _, iface := range ifaces {
		addrs, err := iface.Addrs()
		if err != nil {
			return []InterfaceAddress{}, bosherr.WrapErrorf(err, "Getting addresses of interface '%s'", iface.Name)
		}

		for _, addr := range addrs {
			ip, _, err := net.ParseCIDR(addr.String())
			if err != nil {
				return []InterfaceAddress{}, bosherr.WrapErrorf(err, "Parsing addresses of interface '%s'", iface.Name)
			}

			if ipv4 := ip.To4(); ipv4 != nil {
				interfaceAddrs = append(interfaceAddrs, NewSimpleInterfaceAddress(iface.Name, ipv4.String()))
			}
		}

	}

	return interfaceAddrs, nil
}
예제 #5
0
func (fs *osFileSystem) Symlink(oldPath, newPath string) error {
	fs.logger.Debug(fs.logTag, "Symlinking oldPath %s with newPath %s", oldPath, newPath)

	if fi, err := os.Lstat(newPath); err == nil {
		if fi.Mode()&os.ModeSymlink != 0 {
			// Symlink
			new, err := os.Readlink(newPath)
			if err != nil {
				return bosherr.WrapErrorf(err, "Reading link for %s", newPath)
			}
			if filepath.Clean(oldPath) == filepath.Clean(new) {
				return nil
			}
		}
		if err := os.Remove(newPath); err != nil {
			return bosherr.WrapErrorf(err, "Removing new path at %s", newPath)
		}
	}

	containingDir := filepath.Dir(newPath)
	if !fs.FileExists(containingDir) {
		fs.MkdirAll(containingDir, os.FileMode(0700))
	}

	return symlink(oldPath, newPath)
}
func (tc ConcreteTemplatesCompiler) buildJobReaders(job bpdep.Job) ([]jobReader, error) {
	var readers []jobReader

	for _, template := range job.Templates {
		rec, found, err := tc.tplToJobRepo.FindByTemplate(template)
		if err != nil {
			return readers, bosherr.WrapErrorf(err, "Finding dep-template -> release-job record %s", template.Name)
		} else if !found {
			return readers, bosherr.Errorf("Expected to find dep-template -> release-job record %s", template.Name)
		}

		jobRec, found, err := tc.jobsRepo.FindByReleaseJob(rec)
		if err != nil {
			return readers, bosherr.WrapErrorf(err, "Finding job source blob %s", template.Name)
		} else if !found {
			return readers, bosherr.Errorf("Expected to find job source blob %s -- %s", template.Name, rec)
		}

		jobURL := fmt.Sprintf("blobstore:///%s?fingerprint=%s", jobRec.BlobID, jobRec.SHA1)

		reader := jobReader{
			rec:       rec,
			tarReader: tc.jobReaderFactory.NewReader(jobURL),
		}

		readers = append(readers, reader)
	}

	return readers, nil
}
예제 #7
0
func (p linux) setupRunDir(sysDir string) error {
	runDir := path.Join(sysDir, "run")

	_, runDirIsMounted, err := p.IsMountPoint(runDir)
	if err != nil {
		return bosherr.WrapErrorf(err, "Checking for mount point %s", runDir)
	}

	if !runDirIsMounted {
		err = p.fs.MkdirAll(runDir, runDirPermissions)
		if err != nil {
			return bosherr.WrapErrorf(err, "Making %s dir", runDir)
		}

		err = p.diskManager.GetMounter().Mount("tmpfs", runDir, "-t", "tmpfs", "-o", "size=1m")
		if err != nil {
			return bosherr.WrapErrorf(err, "Mounting tmpfs to %s", runDir)
		}

		_, _, _, err = p.cmdRunner.RunCommand("chown", "root:vcap", runDir)
		if err != nil {
			return bosherr.WrapErrorf(err, "chown %s", runDir)
		}
	}

	return nil
}
예제 #8
0
파일: parser.go 프로젝트: mattcui/bosh-init
func (p *parser) Parse(path string) (Manifest, error) {
	contents, err := p.fs.ReadFile(path)
	if err != nil {
		return Manifest{}, bosherr.WrapErrorf(err, "Reading file %s", path)
	}

	comboManifest := manifest{}
	err = yaml.Unmarshal(contents, &comboManifest)
	if err != nil {
		return Manifest{}, bosherr.WrapError(err, "Unmarshalling release set manifest")
	}
	p.logger.Debug(p.logTag, "Parsed release set manifest: %#v", comboManifest)

	for i, releaseRef := range comboManifest.Releases {
		comboManifest.Releases[i].URL, err = biutil.AbsolutifyPath(path, releaseRef.URL, p.fs)
		if err != nil {
			return Manifest{}, bosherr.WrapErrorf(err, "Resolving release path '%s", releaseRef.URL)
		}
	}

	releaseSetManifest := Manifest{
		Releases: comboManifest.Releases,
	}

	err = p.validator.Validate(releaseSetManifest)
	if err != nil {
		return Manifest{}, bosherr.WrapError(err, "Validating release set manifest")
	}

	return releaseSetManifest, nil
}
func (s registryAgentEnvService) Update(agentEnv AgentEnv) error {
	settingsJSON, err := json.Marshal(agentEnv)
	if err != nil {
		return bosherr.WrapError(err, "Marshalling agent env")
	}

	s.logger.Debug(s.logTag, "Updating registry endpoint '%s' with agent env: '%s'", s.endpoint, settingsJSON)

	putPayload := bytes.NewReader(settingsJSON)
	request, err := http.NewRequest("PUT", s.endpoint, putPayload)
	if err != nil {
		return bosherr.WrapErrorf(err, "Creating PUT request to update registry at '%s' with settings '%s'", s.endpoint, settingsJSON)
	}

	httpClient := http.Client{}
	httpResponse, err := httpClient.Do(request)
	if err != nil {
		return bosherr.WrapErrorf(err, "Updating registry endpoint '%s' with settings: '%s'", s.endpoint, settingsJSON)
	}

	defer httpResponse.Body.Close()

	if httpResponse.StatusCode != http.StatusOK && httpResponse.StatusCode != http.StatusCreated {
		return bosherr.Errorf("Received non-2xx status code when contacting registry: '%d'", httpResponse.StatusCode)
	}

	return nil
}
예제 #10
0
func (a SyncDNS) Run(blobID, sha1 string) (string, error) {
	fileName, err := a.blobstore.Get(blobID, sha1)
	if err != nil {
		return "", bosherr.WrapErrorf(err, "Getting %s from blobstore", blobID)
	}

	fs := a.platform.GetFs()

	contents, err := fs.ReadFile(fileName)
	if err != nil {
		return "", bosherr.WrapErrorf(err, "Reading fileName %s from blobstore", fileName)
	}

	err = fs.RemoveAll(fileName)
	if err != nil {
		a.logger.Info(a.logTag, fmt.Sprintf("Failed to remove dns blob file at path '%s'", fileName))
	}

	dnsRecords := boshsettings.DNSRecords{}
	err = json.Unmarshal(contents, &dnsRecords)
	if err != nil {
		return "", bosherr.WrapError(err, "Unmarshalling DNS records")
	}

	err = a.platform.SaveDNSRecords(dnsRecords, a.settingsService.GetSettings().AgentID)
	if err != nil {
		return "", bosherr.WrapError(err, "Saving DNS records in platform")
	}

	return "synced", nil
}
func (s *fileSystemDeploymentStateService) Load() (DeploymentState, error) {
	if s.configPath == "" {
		panic("configPath not yet set!")
	}

	s.logger.Debug(s.logTag, "Loading deployment state: %s", s.configPath)

	deploymentState := &DeploymentState{}

	if s.fs.FileExists(s.configPath) {
		deploymentStateFileContents, err := s.fs.ReadFile(s.configPath)
		if err != nil {
			return DeploymentState{}, bosherr.WrapErrorf(err, "Reading deployment state file '%s'", s.configPath)
		}
		s.logger.Debug(s.logTag, "Deployment File Contents %#s", deploymentStateFileContents)

		err = json.Unmarshal(deploymentStateFileContents, deploymentState)
		if err != nil {
			return DeploymentState{}, bosherr.WrapErrorf(err, "Unmarshalling deployment state file '%s'", s.configPath)
		}
	}

	err := s.initDefaults(deploymentState)
	if err != nil {
		return DeploymentState{}, bosherr.WrapErrorf(err, "Initializing deployment state defaults")
	}

	return *deploymentState, nil
}
예제 #12
0
func (fs *osFileSystem) Symlink(oldPath, newPath string) error {
	fs.logger.Debug(fs.logTag, "Symlinking oldPath %s with newPath %s", oldPath, newPath)

	actualOldPath, err := filepath.EvalSymlinks(oldPath)
	if err != nil {
		return bosherr.WrapErrorf(err, "Evaluating symlinks for %s", oldPath)
	}

	existingTargetedPath, err := filepath.EvalSymlinks(newPath)
	if err == nil {
		if existingTargetedPath == actualOldPath {
			return nil
		}

		err = os.Remove(newPath)
		if err != nil {
			return bosherr.WrapErrorf(err, "Failed to delete symlimk at %s", newPath)
		}
	}

	containingDir := filepath.Dir(newPath)
	if !fs.FileExists(containingDir) {
		fs.MkdirAll(containingDir, os.FileMode(0700))
	}

	return os.Symlink(oldPath, newPath)
}
예제 #13
0
func (e *extractor) Extract(blobID string, blobSHA1 string, targetDir string) error {
	// Retrieve a temp copy of blob
	filePath, err := e.blobstore.Get(blobID, blobSHA1)
	if err != nil {
		return bosherr.WrapErrorf(err, "Getting object from blobstore: %s", blobID)
	}
	// Clean up temp copy of blob
	defer e.cleanUpBlob(filePath)

	existed := e.fs.FileExists(targetDir)
	if !existed {
		err = e.fs.MkdirAll(targetDir, os.ModePerm)
		if err != nil {
			return bosherr.WrapErrorf(err, "Creating target dir: %s", targetDir)
		}
	}

	err = e.compressor.DecompressFileToDir(filePath, targetDir, boshcmd.CompressorOptions{})
	if err != nil {
		if !existed {
			// Clean up extracted contents of blob
			e.cleanUpFile(targetDir)
		}
		return bosherr.WrapErrorf(err, "Decompressing compiled package: BlobID: '%s', BlobSHA1: '%s'", blobID, blobSHA1)
	}
	return nil
}
예제 #14
0
func NewWatchTime(timeRange string) (WatchTime, error) {
	parts := strings.Split(timeRange, "-")
	if len(parts) != 2 {
		return WatchTime{}, bosherr.Errorf("Invalid watch time range '%s'", timeRange)
	}

	start, err := strconv.Atoi(strings.Trim(parts[0], " "))
	if err != nil {
		return WatchTime{}, bosherr.WrapErrorf(
			err, "Non-positive number as watch time minimum %s", parts[0])
	}

	end, err := strconv.Atoi(strings.Trim(parts[1], " "))
	if err != nil {
		return WatchTime{}, bosherr.WrapErrorf(
			err, "Non-positive number as watch time maximum %s", parts[1])
	}

	if end < start {
		return WatchTime{}, bosherr.Errorf(
			"Watch time must have maximum greater than or equal minimum %s", timeRange)
	}

	return WatchTime{
		Start: start,
		End:   end,
	}, nil
}
예제 #15
0
func (p sfdiskPartitioner) diskMatchesPartitions(devicePath string, partitionsToMatch []Partition) (result bool) {
	existingPartitions, err := p.getPartitions(devicePath)
	if err != nil {
		err = bosherr.WrapErrorf(err, "Getting partitions for %s", devicePath)
		return
	}

	if len(existingPartitions) < len(partitionsToMatch) {
		return
	}

	remainingDiskSpace, err := p.GetDeviceSizeInBytes(devicePath)
	if err != nil {
		err = bosherr.WrapErrorf(err, "Getting device size for %s", devicePath)
		return
	}

	for index, partitionToMatch := range partitionsToMatch {
		if index == len(partitionsToMatch)-1 {
			partitionToMatch.SizeInBytes = remainingDiskSpace
		}

		existingPartition := existingPartitions[index]
		switch {
		case existingPartition.Type != partitionToMatch.Type:
			return
		case !withinDelta(existingPartition.SizeInBytes, partitionToMatch.SizeInBytes, p.convertFromMbToBytes(20)):
			return
		}

		remainingDiskSpace = remainingDiskSpace - partitionToMatch.SizeInBytes
	}

	return true
}
예제 #16
0
func (ms httpMetadataService) getUserData() (UserDataContentsType, error) {
	var userData UserDataContentsType

	err := ms.ensureMinimalNetworkSetup()
	if err != nil {
		return userData, err
	}

	userDataURL := fmt.Sprintf("%s%s", ms.metadataHost, ms.userdataPath)
	userDataResp, err := ms.doGet(userDataURL)
	if err != nil {
		return userData, bosherr.WrapErrorf(err, "Getting user data from url %s", userDataURL)
	}

	defer func() {
		if err := userDataResp.Body.Close(); err != nil {
			ms.logger.Warn(ms.logTag, "Failed to close response body when getting user data: %s", err.Error())
		}
	}()

	userDataBytes, err := ioutil.ReadAll(userDataResp.Body)
	if err != nil {
		return userData, bosherr.WrapError(err, "Reading user data response body")
	}

	err = json.Unmarshal(userDataBytes, &userData)
	if err != nil {
		return userData, bosherr.WrapErrorf(err, "Unmarshalling user data '%s'", string(userDataBytes))
	}

	return userData, nil
}
예제 #17
0
func (net centosNetManager) writeDHCPConfiguration(dnsServers []string, dhcpInterfaceConfigurations []DHCPInterfaceConfiguration) (bool, error) {
	buffer := bytes.NewBuffer([]byte{})
	t := template.Must(template.New("dhcp-config").Parse(centosDHCPConfigTemplate))

	// Keep DNS servers in the order specified by the network
	// because they are added by a *single* DHCP's prepend command
	dnsServersList := strings.Join(dnsServers, ", ")
	err := t.Execute(buffer, dnsServersList)
	if err != nil {
		return false, bosherr.WrapError(err, "Generating config from template")
	}
	dhclientConfigFile := "/etc/dhcp/dhclient.conf"
	changed, err := net.fs.ConvergeFileContents(dhclientConfigFile, buffer.Bytes())

	if err != nil {
		return changed, bosherr.WrapErrorf(err, "Writing to %s", dhclientConfigFile)
	}

	for i := range dhcpInterfaceConfigurations {
		name := dhcpInterfaceConfigurations[i].Name
		interfaceDhclientConfigFile := filepath.Join("/etc/dhcp/", "dhclient-"+name+".conf")
		err = net.fs.Symlink(dhclientConfigFile, interfaceDhclientConfigFile)
		if err != nil {
			return changed, bosherr.WrapErrorf(err, "Symlinking '%s' to '%s'", interfaceDhclientConfigFile, dhclientConfigFile)
		}
	}

	return changed, nil
}
예제 #18
0
func (fs *osFileSystem) Symlink(oldPath, newPath string) error {
	fs.logger.Debug(fs.logTag, "Symlinking oldPath %s with newPath %s", oldPath, newPath)

	source, target, err := fs.symlinkPaths(oldPath, newPath)
	if err != nil {
		bosherr.WrapErrorf(err, "Getting absolute paths for target and path links: %s %s", oldPath, newPath)
	}
	if fi, err := fs.Lstat(target); err == nil {
		if fi.Mode()&os.ModeSymlink != 0 {
			// Symlink
			new, err := fs.Readlink(target)
			if err != nil {
				return bosherr.WrapErrorf(err, "Reading link for %s", target)
			}
			if filepath.Clean(source) == filepath.Clean(new) {
				return nil
			}
		}
		if err := fs.RemoveAll(target); err != nil {
			return bosherr.WrapErrorf(err, "Removing new path at %s", target)
		}
	}

	containingDir := filepath.Dir(target)
	if !fs.FileExists(containingDir) {
		fs.MkdirAll(containingDir, os.FileMode(0700))
	}

	return fsWrapper.Symlink(source, target)
}
예제 #19
0
func (p linux) SetupDataDir() error {
	dataDir := p.dirProvider.DataDir()

	sysDataDir := path.Join(dataDir, "sys")

	logDir := path.Join(sysDataDir, "log")
	err := p.fs.MkdirAll(logDir, logDirPermissions)
	if err != nil {
		return bosherr.WrapErrorf(err, "Making %s dir", logDir)
	}

	_, _, _, err = p.cmdRunner.RunCommand("chown", "root:vcap", sysDataDir)
	if err != nil {
		return bosherr.WrapErrorf(err, "chown %s", sysDataDir)
	}

	_, _, _, err = p.cmdRunner.RunCommand("chown", "root:vcap", logDir)
	if err != nil {
		return bosherr.WrapErrorf(err, "chown %s", logDir)
	}

	err = p.setupRunDir(sysDataDir)
	if err != nil {
		return err
	}

	sysDir := path.Join(path.Dir(dataDir), "sys")
	err = p.fs.Symlink(sysDataDir, sysDir)
	if err != nil {
		return bosherr.WrapErrorf(err, "Symlinking '%s' to '%s'", sysDir, sysDataDir)
	}

	return nil
}
예제 #20
0
func NewWatchTimeFromString(str string) (WatchTime, error) {
	var watchTime WatchTime

	parts := strings.Split(str, "-")
	if len(parts) != 2 {
		return watchTime, bosherr.Errorf("Invalid watch time range %s", str)
	}

	min, err := strconv.Atoi(strings.Trim(parts[0], " "))
	if err != nil {
		return watchTime, bosherr.WrapErrorf(
			err, "Non-positive number as watch time minimum %s", parts[0])
	}

	max, err := strconv.Atoi(strings.Trim(parts[1], " "))
	if err != nil {
		return watchTime, bosherr.WrapErrorf(
			err, "Non-positive number as watch time maximum %s", parts[1])
	}

	if max < min {
		return watchTime, bosherr.Errorf(
			"Watch time must have maximum greater than or equal minimum %s", str)
	}

	watchTime[0], watchTime[1] = min, max

	return watchTime, nil
}
func (v SyntaxValidator) Validate() error {
	if v.release.Name == "" {
		return bosherr.Error("Missing release name")
	}

	if v.release.Version == "" {
		return bosherr.Error("Missing release version")
	}

	if v.release.CommitHash == "" {
		return bosherr.Error("Missing release commit_hash")
	}

	for i, job := range v.release.Jobs {
		err := v.validateJob(&v.release.Jobs[i])
		if err != nil {
			return bosherr.WrapErrorf(err, "Job %s (%d)", job.Name, i)
		}
	}

	for i, pkg := range v.release.Packages {
		err := v.validatePkg(&v.release.Packages[i])
		if err != nil {
			return bosherr.WrapErrorf(err, "Package %s (%d)", pkg.Name, i)
		}
	}

	return nil
}
func (g *renderer) Render(input bftinput.Input, manifestPath string, cloudConfigPath string) error {
	deploymentTemplate := template.Must(template.New("deployment").Parse(DeploymentTemplate))

	buffer := bytes.NewBuffer([]byte{})
	err := deploymentTemplate.Execute(buffer, input)
	if err != nil {
		return bosherr.WrapErrorf(err, "Generating deployment manifest")
	}

	err = g.fs.WriteFile(manifestPath, buffer.Bytes())
	if err != nil {
		return bosherr.WrapErrorf(err, "Saving generated manifest")
	}

	cloudTemplate := template.Must(template.New("cloud-config").Parse(CloudTemplate))

	buffer = bytes.NewBuffer([]byte{})

	err = cloudTemplate.Execute(buffer, input)
	if err != nil {
		return bosherr.WrapErrorf(err, "Generating cloud config")
	}

	err = g.fs.WriteFile(cloudConfigPath, buffer.Bytes())
	if err != nil {
		return bosherr.WrapErrorf(err, "Saving generated cloud config")
	}

	return nil
}
예제 #23
0
func (fs *osFileSystem) ConvergeFileContents(path string, content []byte) (bool, error) {
	if fs.filesAreIdentical(content, path) {
		fs.logger.Debug(fs.logTag, "Skipping writing %s because contents are identical", path)
		return false, nil
	}

	fs.logger.Debug(fs.logTag, "File %s will be overwritten", path)

	err := fs.MkdirAll(filepath.Dir(path), os.ModePerm)
	if err != nil {
		return true, bosherr.WrapErrorf(err, "Making dir for file %s", path)
	}

	file, err := os.Create(path)
	if err != nil {
		return true, bosherr.WrapErrorf(err, "Creating file %s", path)
	}

	defer file.Close()

	_, err = file.Write(content)
	if err != nil {
		return true, bosherr.WrapErrorf(err, "Writing content to file %s", path)
	}

	return true, nil
}
예제 #24
0
func (a AttachDisk) Run(vmCID VMCID, diskCID DiskCID) (interface{}, error) {
	vm, found, err := a.vmFinder.Find(vmCID.Int())
	if err != nil {
		return nil, bosherr.WrapErrorf(err, "Finding VM '%s'", vmCID)
	}

	if !found {
		return nil, bosherr.Errorf("Expected to find VM '%s'", vmCID)
	}

	disk, found, err := a.diskFinder.Find(diskCID.Int())
	if err != nil {
		return nil, bosherr.WrapErrorf(err, "Finding disk '%s'", diskCID)
	}

	if !found {
		return nil, bosherr.Errorf("Expected to find disk '%s'", diskCID)
	}

	err = vm.AttachDisk(disk)
	if err != nil {
		return nil, bosherr.WrapErrorf(err, "Attaching disk '%s' to VM '%s'", diskCID, vmCID)
	}

	return nil, nil
}
예제 #25
0
func (fs *osFileSystem) Chown(path, username string) error {
	fs.logger.Debug(fs.logTag, "Chown %s to user %s", path, username)

	uid, err := fs.runCommand(fmt.Sprintf("id -u %s", username))
	if err != nil {
		return bosherr.WrapErrorf(err, "Getting user id for '%s'", username)
	}

	uidAsInt, err := strconv.Atoi(uid)
	if err != nil {
		return bosherr.WrapError(err, "Converting UID to integer")
	}

	gid, err := fs.runCommand(fmt.Sprintf("id -g %s", username))
	if err != nil {
		return bosherr.WrapErrorf(err, "Getting group id for '%s'", username)
	}

	gidAsInt, err := strconv.Atoi(gid)
	if err != nil {
		return bosherr.WrapError(err, "Converting GID to integer")
	}

	err = os.Chown(path, uidAsInt, gidAsInt)
	if err != nil {
		return bosherr.WrapError(err, "Doing Chown")
	}

	return nil
}
예제 #26
0
// Extract decompresses a release tarball into a temp directory (release.extractedPath),
// parses the release manifest, decompresses the packages and jobs, and validates the release.
// Use release.Delete() to clean up the temp directory.
func (e *extractor) Extract(releaseTarballPath string) (Release, error) {
	extractedReleasePath, err := e.fs.TempDir("bosh-init-release")
	if err != nil {
		return nil, bosherr.WrapErrorf(err, "Creating temp directory to extract release '%s'", releaseTarballPath)
	}

	e.logger.Info(e.logTag, "Extracting release tarball '%s' to '%s'", releaseTarballPath, extractedReleasePath)

	releaseReader := NewReader(releaseTarballPath, extractedReleasePath, e.fs, e.compressor)
	release, err := releaseReader.Read()
	if err != nil {
		if removeErr := e.fs.RemoveAll(extractedReleasePath); removeErr != nil {
			e.logger.Warn(e.logTag, "Failed to remove extracted release: %s", removeErr.Error())
		}
		return nil, bosherr.WrapErrorf(err, "Reading release from '%s'", releaseTarballPath)
	}

	err = e.validator.Validate(release)
	if err != nil {
		if removeErr := e.fs.RemoveAll(extractedReleasePath); removeErr != nil {
			e.logger.Warn(e.logTag, "Failed to remove extracted release: %s", removeErr.Error())
		}
		return nil, bosherr.WrapErrorf(err, "Validating release '%s-%s'", release.Name(), release.Version())
	}

	e.logger.Info(e.logTag, "Extracted release %s version %s", release.Name(), release.Version())

	return release, nil
}
예제 #27
0
func (vm SoftLayerVM) SetMetadata(vmMetadata VMMetadata) error {
	tags, err := vm.extractTagsFromVMMetadata(vmMetadata)
	if err != nil {
		return err
	}

	if len(tags) == 0 {
		return nil
	}

	//Check below needed since Golang strings.Split return [""] on strings.Split("", ",")
	if len(tags) == 1 && tags[0] == "" {
		return nil
	}

	virtualGuestService, err := vm.softLayerClient.GetSoftLayer_Virtual_Guest_Service()
	if err != nil {
		return bosherr.WrapError(err, "Creating SoftLayer VirtualGuestService from client")
	}

	success, err := virtualGuestService.SetTags(vm.ID(), tags)
	if !success {
		return bosherr.WrapErrorf(err, "Settings tags on SoftLayer VirtualGuest `%d`", vm.ID())
	}

	if err != nil {
		return bosherr.WrapErrorf(err, "Settings tags on SoftLayer VirtualGuest `%d`", vm.ID())
	}

	return nil
}
예제 #28
0
func (p rootDevicePartitioner) Partition(devicePath string, partitions []Partition) error {
	existingPartitions, deviceFullSizeInBytes, err := p.getPartitions(devicePath)
	if err != nil {
		return bosherr.WrapErrorf(err, "Getting existing partitions of `%s'", devicePath)
	}
	p.logger.Debug(p.logTag, "Current partitions: %#v", existingPartitions)

	if len(existingPartitions) == 0 {
		return bosherr.Errorf("Missing first partition on `%s'", devicePath)
	}

	if p.partitionsMatch(existingPartitions[1:], partitions) {
		p.logger.Info(p.logTag, "Partitions already match, skipping partitioning")
		return nil
	}

	if len(existingPartitions) > 1 {
		p.logger.Error(p.logTag,
			"Failed to create ephemeral partitions on root device `%s'. Expected 1 partition, found %d: %s",
			devicePath,
			len(existingPartitions),
			existingPartitions,
		)
		return bosherr.Errorf("Found %d unexpected partitions on `%s'", len(existingPartitions)-1, devicePath)
	}

	// To support optimal reads on HDDs and optimal erasure on SSD: use 1MiB partition alignments.
	alignmentInBytes := uint64(1048576)

	partitionStart := p.roundUp(existingPartitions[0].EndInBytes+1, alignmentInBytes)

	for index, partition := range partitions {
		partitionEnd := partitionStart + partition.SizeInBytes - 1
		if partitionEnd >= deviceFullSizeInBytes {
			partitionEnd = deviceFullSizeInBytes - 1
			p.logger.Info(p.logTag, "Partition %d would be larger than remaining space. Reducing size to %dB", index, partitionEnd-partitionStart)
		}

		p.logger.Info(p.logTag, "Creating partition %d with start %dB and end %dB", index, partitionStart, partitionEnd)

		_, _, _, err := p.cmdRunner.RunCommand(
			"parted",
			"-s",
			devicePath,
			"unit",
			"B",
			"mkpart",
			"primary",
			fmt.Sprintf("%d", partitionStart),
			fmt.Sprintf("%d", partitionEnd),
		)

		if err != nil {
			return bosherr.WrapErrorf(err, "Partitioning disk `%s'", devicePath)
		}

		partitionStart = p.roundUp(partitionEnd+1, alignmentInBytes)
	}
	return nil
}
예제 #29
0
func (s JobState) buildPackageSpecs() (map[string]boshas.PackageSpec, error) {
	specs := map[string]boshas.PackageSpec{}

	for _, template := range s.depJob.Templates {
		pkgs, err := s.templatesCompiler.FindPackages(template)
		if err != nil {
			return specs, bosherr.WrapErrorf(err, "Finding packages for template %s", template.Name)
		}

		for _, pkg := range pkgs {
			rec, err := s.packagesCompiler.FindCompiledPackage(pkg)
			if err != nil {
				return specs, bosherr.WrapErrorf(err, "Finding compiled package %s", pkg.Name)
			}

			specs[pkg.Name] = boshas.PackageSpec{
				Name:    pkg.Name,
				Version: pkg.Version,

				Sha1:        rec.SHA1,
				BlobstoreID: rec.BlobID,
			}
		}
	}

	return specs, nil
}
예제 #30
0
파일: parser.go 프로젝트: mattcui/bosh-init
func (p *parser) parseResourcePoolManifests(rawResourcePools []resourcePool, path string) ([]ResourcePool, error) {
	resourcePools := make([]ResourcePool, len(rawResourcePools), len(rawResourcePools))
	for i, rawResourcePool := range rawResourcePools {
		resourcePool := ResourcePool{
			Name:     rawResourcePool.Name,
			Network:  rawResourcePool.Network,
			Stemcell: StemcellRef(rawResourcePool.Stemcell),
		}

		cloudProperties, err := biproperty.BuildMap(rawResourcePool.CloudProperties)
		if err != nil {
			return resourcePools, bosherr.WrapErrorf(err, "Parsing resource_pool '%s' cloud_properties: %#v", rawResourcePool.Name, rawResourcePool.CloudProperties)
		}
		resourcePool.CloudProperties = cloudProperties

		env, err := biproperty.BuildMap(rawResourcePool.Env)
		if err != nil {
			return resourcePools, bosherr.WrapErrorf(err, "Parsing resource_pool '%s' env: %#v", rawResourcePool.Name, rawResourcePool.Env)
		}
		resourcePool.Env = env

		resourcePool.Stemcell.URL, err = biutil.AbsolutifyPath(path, resourcePool.Stemcell.URL, p.fs)
		if err != nil {
			return resourcePools, bosherr.WrapErrorf(err, "Resolving stemcell path '%s", resourcePool.Stemcell.URL)
		}

		resourcePools[i] = resourcePool
	}

	return resourcePools, nil
}