Ejemplo n.º 1
0
// Build creates a generic property that may be a Map, List or primitive.
// If it is a Map or List it will be built using the appropriate builder and constraints.
func Build(val interface{}) (Property, error) {
	if val == nil {
		return nil, nil
	}

	switch reflect.TypeOf(val).Kind() {
	case reflect.Map:
		valMap, ok := val.(map[interface{}]interface{})
		if !ok {
			return nil, bosherr.Errorf("Converting map %#v", val)
		}

		return BuildMap(valMap)

	case reflect.Slice:
		valSlice, ok := val.([]interface{})
		if !ok {
			return nil, bosherr.Errorf("Converting slice %#v", val)
		}

		return BuildList(valSlice)

	default:
		return val, nil
	}
}
Ejemplo n.º 2
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
}
func (creator interfaceConfigurationCreator) createMultipleInterfaceConfigurations(networks boshsettings.Networks, interfacesByMAC map[string]string) ([]StaticInterfaceConfiguration, []DHCPInterfaceConfiguration, error) {
	if len(interfacesByMAC) < len(networks) {
		return nil, nil, bosherr.Errorf("Number of network settings '%d' is greater than the number of network devices '%d'", len(networks), len(interfacesByMAC))
	}

	for name := range networks {
		if mac := networks[name].Mac; mac != "" {
			if _, ok := interfacesByMAC[mac]; !ok {
				return nil, nil, bosherr.Errorf("No device found for network '%s' with MAC address '%s'", name, mac)
			}
		}
	}

	// Configure interfaces with network settings matching MAC address.
	// If we cannot find a network setting with a matching MAC address, configure that interface as DHCP
	var networkSettings boshsettings.Network
	var err error
	staticConfigs := []StaticInterfaceConfiguration{}
	dhcpConfigs := []DHCPInterfaceConfiguration{}

	for mac, ifaceName := range interfacesByMAC {
		networkSettings, _ = networks.NetworkForMac(mac)
		staticConfigs, dhcpConfigs, err = creator.createInterfaceConfiguration(staticConfigs, dhcpConfigs, ifaceName, networkSettings)
		if err != nil {
			return nil, nil, bosherr.WrapError(err, "Creating interface configuration")
		}
	}

	return staticConfigs, dhcpConfigs, nil
}
Ejemplo n.º 4
0
func (r ipResolver) GetPrimaryIPv4(interfaceName string) (*gonet.IPNet, error) {
	addrs, err := r.ifaceToAddrsFunc(interfaceName)
	if err != nil {
		return nil, bosherr.WrapErrorf(err, "Looking up addresses for interface '%s'", interfaceName)
	}

	if len(addrs) == 0 {
		return nil, bosherr.Errorf("No addresses found for interface '%s'", interfaceName)
	}

	for _, addr := range addrs {
		ip, ok := addr.(*gonet.IPNet)
		if !ok {
			continue
		}

		// ignore ipv6
		if ip.IP.To4() == nil {
			continue
		}

		return ip, nil
	}

	return nil, bosherr.Errorf("Failed to find primary IPv4 address for interface '%s'", interfaceName)
}
Ejemplo n.º 5
0
func (c *agentClient) CompilePackage(packageSource agentclient.BlobRef, compiledPackageDependencies []agentclient.BlobRef) (compiledPackageRef agentclient.BlobRef, err error) {
	dependencies := make(map[string]BlobRef, len(compiledPackageDependencies))
	for _, dependency := range compiledPackageDependencies {
		dependencies[dependency.Name] = BlobRef{
			Name:        dependency.Name,
			Version:     dependency.Version,
			SHA1:        dependency.SHA1,
			BlobstoreID: dependency.BlobstoreID,
		}
	}

	args := []interface{}{
		packageSource.BlobstoreID,
		packageSource.SHA1,
		packageSource.Name,
		packageSource.Version,
		dependencies,
	}

	responseValue, err := c.sendAsyncTaskMessage("compile_package", args)
	if err != nil {
		return agentclient.BlobRef{}, bosherr.WrapError(err, "Sending 'compile_package' to the agent")
	}

	result, ok := responseValue["result"].(map[string]interface{})
	if !ok {
		return agentclient.BlobRef{}, bosherr.Errorf("Unable to parse 'compile_package' response from the agent: %#v", responseValue)
	}

	sha1, ok := result["sha1"].(string)
	if !ok {
		return agentclient.BlobRef{}, bosherr.Errorf("Unable to parse 'compile_package' response from the agent: %#v", responseValue)
	}

	blobstoreID, ok := result["blobstore_id"].(string)
	if !ok {
		return agentclient.BlobRef{}, bosherr.Errorf("Unable to parse 'compile_package' response from the agent: %#v", responseValue)
	}

	compiledPackageRef = agentclient.BlobRef{
		Name:        packageSource.Name,
		Version:     packageSource.Version,
		SHA1:        sha1,
		BlobstoreID: blobstoreID,
	}

	return compiledPackageRef, nil
}
Ejemplo n.º 6
0
func (p HandlerProvider) Get(
	platform boshplatform.Platform,
	dirProvider boshdir.Provider,
) (handler boshhandler.Handler, err error) {
	if p.handler != nil {
		handler = p.handler
		return
	}

	mbusURL, err := url.Parse(p.settingsService.GetSettings().Mbus)
	if err != nil {
		err = bosherr.WrapError(err, "Parsing handler URL")
		return
	}

	switch mbusURL.Scheme {
	case "nats":
		handler = NewNatsHandler(p.settingsService, yagnats.NewClient(), p.logger)
	case "https":
		handler = boshmicro.NewHTTPSHandler(mbusURL, p.logger, platform.GetFs(), dirProvider)
	default:
		err = bosherr.Errorf("Message Bus Handler with scheme %s could not be found", mbusURL.Scheme)
	}

	p.handler = handler

	return
}
Ejemplo n.º 7
0
func (a MountDiskAction) Run(diskCid string) (interface{}, error) {
	err := a.settingsService.LoadSettings()
	if err != nil {
		return nil, bosherr.WrapError(err, "Refreshing the settings")
	}

	settings := a.settingsService.GetSettings()

	diskSettings, found := settings.PersistentDiskSettings(diskCid)
	if !found {
		return nil, bosherr.Errorf("Persistent disk with volume id '%s' could not be found", diskCid)
	}

	mountPoint := a.dirProvider.StoreDir()

	isMountPoint, err := a.mountPoints.IsMountPoint(mountPoint)
	if err != nil {
		return nil, bosherr.WrapError(err, "Checking mount point")
	}
	if isMountPoint {
		mountPoint = a.dirProvider.StoreMigrationDir()
	}

	err = a.diskMounter.MountPersistentDisk(diskSettings, mountPoint)
	if err != nil {
		return nil, bosherr.WrapError(err, "Mounting persistent disk")
	}

	return map[string]string{}, nil
}
Ejemplo n.º 8
0
func (p provider) Get(name string) (Platform, error) {
	plat, found := p.platforms[name]
	if !found {
		return nil, bosherror.Errorf("Platform %s could not be found", name)
	}
	return plat, nil
}
Ejemplo n.º 9
0
func (b externalBlobstore) Validate() error {
	if !b.runner.CommandExists(b.executable()) {
		return bosherr.Errorf("executable %s not found in PATH", b.executable())
	}

	return b.writeConfigFile()
}
Ejemplo n.º 10
0
func (s concreteV1Service) PopulateDHCPNetworks(spec V1ApplySpec, settings boshsettings.Settings) (V1ApplySpec, error) {
	for networkName, networkSpec := range spec.NetworkSpecs {
		// Skip 'local' network since for vsphere/vcloud networks
		// are generated incorrectly by the bosh_cli_plugin_micro/bosh-release;
		// can be removed with new bosh micro CLI
		if networkName == "local" && networkSpec.Fields["ip"] == "127.0.0.1" {
			continue
		}

		network, ok := settings.Networks[networkName]
		if !ok {
			return V1ApplySpec{}, bosherr.Errorf("Network '%s' is not found in settings", networkName)
		}

		if !network.IsDHCP() {
			continue
		}

		spec.NetworkSpecs[networkName] = networkSpec.PopulateIPInfo(
			network.IP,
			network.Netmask,
			network.Gateway,
		)
	}

	return spec, nil
}
Ejemplo n.º 11
0
func (p rootDevicePartitioner) 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
}
Ejemplo n.º 12
0
func (p Provider) Get(name string) (supervisor JobSupervisor, err error) {
	supervisor, found := p.supervisors[name]
	if !found {
		err = bosherr.Errorf("JobSupervisor %s could not be found", name)
	}
	return
}
Ejemplo n.º 13
0
func (a UnmountDiskAction) Run(diskID string) (value interface{}, err error) {
	settings := a.settingsService.GetSettings()

	diskSettings, found := settings.PersistentDiskSettings(diskID)
	if !found {
		err = bosherr.Errorf("Persistent disk with volume id '%s' could not be found", diskID)
		return
	}

	didUnmount, err := a.platform.UnmountPersistentDisk(diskSettings)
	if err != nil {
		err = bosherr.WrapError(err, "Unmounting persistent disk")
		return
	}

	msg := fmt.Sprintf("Partition of %s is not mounted", diskSettings.Path)

	if didUnmount {
		msg = fmt.Sprintf("Unmounted partition of %s", diskSettings.Path)
	}

	type valueType struct {
		Message string `json:"message"`
	}

	value = valueType{Message: msg}
	return
}
Ejemplo n.º 14
0
func (idpr idDevicePathResolver) GetRealDevicePath(diskSettings boshsettings.DiskSettings) (string, bool, error) {
	if diskSettings.ID == "" {
		return "", false, bosherr.Errorf("Disk ID is not set")
	}

	if len(diskSettings.ID) < 20 {
		return "", false, bosherr.Errorf("Disk ID is not the correct format")
	}

	err := idpr.udev.Trigger()
	if err != nil {
		return "", false, bosherr.WrapError(err, "Running udevadm trigger")
	}

	err = idpr.udev.Settle()
	if err != nil {
		return "", false, bosherr.WrapError(err, "Running udevadm settle")
	}

	stopAfter := time.Now().Add(idpr.diskWaitTimeout)
	found := false

	var realPath string

	diskID := diskSettings.ID[0:20]

	for !found {
		if time.Now().After(stopAfter) {
			return "", true, bosherr.Errorf("Timed out getting real device path for '%s'", diskID)
		}

		time.Sleep(100 * time.Millisecond)

		deviceIDPath := filepath.Join(string(os.PathSeparator), "dev", "disk", "by-id", fmt.Sprintf("virtio-%s", diskID))

		realPath, err = idpr.fs.ReadLink(deviceIDPath)
		if err != nil {
			continue
		}

		if idpr.fs.FileExists(realPath) {
			found = true
		}
	}

	return realPath, false, nil
}
Ejemplo n.º 15
0
func (a CancelTaskAction) Run(taskID string) (string, error) {
	task, found := a.taskService.FindTaskWithID(taskID)
	if !found {
		return "", bosherr.Errorf("Task with id %s could not be found", taskID)
	}

	return "canceled", task.Cancel()
}
Ejemplo n.º 16
0
func (f concreteFactory) Create(method string) (Action, error) {
	action, found := f.availableActions[method]
	if !found {
		return nil, bosherr.Errorf("Could not create action with method %s", method)
	}

	return action, nil
}
Ejemplo n.º 17
0
func (r *getStateRetryable) Attempt() (bool, error) {
	stateResponse, err := r.agentClient.GetState()
	if err != nil {
		return false, err
	}

	if stateResponse.JobState == "running" {
		return true, nil
	}

	return true, bosherr.Errorf("Received non-running job state: '%s'", stateResponse.JobState)
}
Ejemplo n.º 18
0
func (m linuxMounter) shouldMount(partitionPath, mountPoint string) (bool, error) {
	mounts, err := m.mountsSearcher.SearchMounts()
	if err != nil {
		return false, bosherr.WrapError(err, "Searching mounts")
	}

	for _, mount := range mounts {
		switch {
		case mount.PartitionPath == partitionPath && mount.MountPoint == mountPoint:
			return false, nil
		case mount.PartitionPath == partitionPath && mount.MountPoint != mountPoint && partitionPath != "tmpfs":
			return false, bosherr.Errorf("Device %s is already mounted to %s, can't mount to %s",
				mount.PartitionPath, mount.MountPoint, mountPoint)
		case mount.MountPoint == mountPoint:
			return false, bosherr.Errorf("Device %s is already mounted to %s, can't mount %s",
				mount.PartitionPath, mount.MountPoint, partitionPath)
		}
	}

	return true, nil
}
Ejemplo n.º 19
0
func (a RunScriptAction) Run(scriptName string, options map[string]interface{}) (map[string]string, error) {
	result := map[string]string{}

	currentSpec, err := a.specService.Get()
	if err != nil {
		return result, bosherr.WrapError(err, "Getting current spec")
	}

	a.logger.Info("run-script-action", "Attempting to run '%s' scripts in %d jobs", scriptName, len(currentSpec.JobSpec.JobTemplateSpecs))

	scriptCount := 0

	resultChannel := make(chan scriptrunner.RunScriptResult)

	for _, jobTemplate := range currentSpec.JobSpec.JobTemplateSpecs {
		script := a.scriptProvider.Get(jobTemplate.Name, scriptName)
		if script.Exists() {
			scriptCount++
			go func() {
				resultChannel <- script.Run()
			}()
		}
	}

	var failedScripts []string
	var passedScripts []string

	for i := 0; i < scriptCount; i++ {
		select {
		case resultScript := <-resultChannel:
			jobName := resultScript.Tag
			if resultScript.Error == nil {
				passedScripts = append(passedScripts, jobName)
				result[jobName] = "executed"
				a.logger.Info("run-script-action", "'%s' script has successfully executed", resultScript.ScriptPath)
			} else {
				failedScripts = append(failedScripts, jobName)
				result[jobName] = "failed"
				a.logger.Error("run-script-action", "'%s' script has failed with error %s", resultScript.ScriptPath, resultScript.Error)
			}
		}
	}

	if len(failedScripts) > 0 {
		msg := "Failed Jobs: " + strings.Join(failedScripts, ", ")
		if len(passedScripts) > 0 {
			msg += ". Successful Jobs: " + strings.Join(passedScripts, ", ")
		}
		return result, bosherr.Errorf("%d of %d %s scripts failed. %s.", len(failedScripts), scriptCount, scriptName, msg)
	}
	return result, nil
}
Ejemplo n.º 20
0
func (c *agentClient) Start() error {
	var response SimpleTaskResponse
	err := c.agentRequest.Send("start", []interface{}{}, &response)
	if err != nil {
		return bosherr.WrapError(err, "Starting agent services")
	}

	if response.Value != "started" {
		return bosherr.Errorf("Failed to start agent services with response: '%s'", response)
	}

	return nil
}
Ejemplo n.º 21
0
func (dispatcher concreteActionDispatcher) Dispatch(req boshhandler.Request) boshhandler.Response {
	action, err := dispatcher.actionFactory.Create(req.Method)
	if err != nil {
		dispatcher.logger.Error(actionDispatcherLogTag, "Unknown action %s", req.Method)
		return boshhandler.NewExceptionResponse(bosherr.Errorf("unknown message %s", req.Method))
	}

	if action.IsAsynchronous() {
		return dispatcher.dispatchAsynchronousAction(action, req)
	}

	return dispatcher.dispatchSynchronousAction(action, req)
}
Ejemplo n.º 22
0
func (c *agentClient) sendAsyncTaskMessage(method string, arguments []interface{}) (value map[string]interface{}, err error) {
	var response TaskResponse
	err = c.agentRequest.Send(method, arguments, &response)
	if err != nil {
		return value, bosherr.WrapErrorf(err, "Sending '%s' to the agent", method)
	}

	agentTaskID, err := response.TaskID()
	if err != nil {
		return value, bosherr.WrapError(err, "Getting agent task id")
	}

	sendErrors := 0
	getTaskRetryable := boshretry.NewRetryable(func() (bool, error) {
		var response TaskResponse
		err = c.agentRequest.Send("get_task", []interface{}{agentTaskID}, &response)
		if err != nil {
			sendErrors++
			shouldRetry := sendErrors <= c.toleratedErrorCount
			err = bosherr.WrapError(err, "Sending 'get_task' to the agent")
			msg := fmt.Sprintf("Error occured sending get_task. Error retry %d of %d", sendErrors, c.toleratedErrorCount)
			c.logger.Debug(c.logTag, msg, err)
			return shouldRetry, err
		}
		sendErrors = 0

		c.logger.Debug(c.logTag, "get_task response value: %#v", response.Value)

		taskState, err := response.TaskState()
		if err != nil {
			return false, bosherr.WrapError(err, "Getting task state")
		}

		if taskState != "running" {
			var ok bool
			value, ok = response.Value.(map[string]interface{})
			if !ok {
				c.logger.Warn(c.logTag, "Unable to parse get_task response value: %#v", response.Value)
			}
			return true, nil
		}

		return true, bosherr.Errorf("Task %s is still running", method)
	})

	getTaskRetryStrategy := boshretry.NewUnlimitedRetryStrategy(c.getTaskDelay, getTaskRetryable, c.logger)
	// cannot call getTaskRetryStrategy.Try in the return statement due to gccgo
	// execution order issues: https://code.google.com/p/go/issues/detail?id=8698&thanks=8698&ts=1410376474
	err = getTaskRetryStrategy.Try()
	return value, err
}
// TerminateNicely can be called multiple times simultaneously from different goroutines
func (p *execProcess) TerminateNicely(killGracePeriod time.Duration) error {
	// Make sure process is being waited on for process state reaping to occur
	// as to avoid forcibly killing the process after killGracePeriod
	if p.waitCh == nil {
		panic("TerminateNicely() must be called after Wait()")
	}

	err := p.signalGroup(syscall.SIGTERM)
	if err != nil {
		return bosherr.WrapErrorf(err, "Sending SIGTERM to process group %d", p.pid)
	}

	terminatedCh := make(chan struct{})
	stopCheckingTerminatedCh := make(chan struct{})

	go func() {
		for p.groupExists() {
			select {
			case <-time.After(500 * time.Millisecond):
				// nothing to do
			case <-stopCheckingTerminatedCh:
				return
			}
		}

		close(terminatedCh)
	}()

	select {
	case <-terminatedCh:
		// nothing to do

	case <-time.After(killGracePeriod):
		close(stopCheckingTerminatedCh)

		err = p.signalGroup(syscall.SIGKILL)
		if err != nil {
			return bosherr.WrapErrorf(err, "Sending SIGKILL to process group %d", p.pid)
		}
	}

	// It takes some time for the process to disappear
	for i := 0; i < 20; i++ {
		if !p.groupExists() {
			return nil
		}
		time.Sleep(500 * time.Millisecond)
	}

	return bosherr.Errorf("Failed to kill process after grace timeout (PID %d)", p.pid)
}
Ejemplo n.º 24
0
func (fs *osFileSystem) HomeDir(username string) (string, error) {
	fs.logger.Debug(fs.logTag, "Getting HomeDir for %s", username)

	homeDir, err := fs.runCommand(fmt.Sprintf("echo ~%s", username))
	if err != nil {
		return "", bosherr.WrapErrorf(err, "Shelling out to get user '%s' home directory", username)
	}

	if strings.HasPrefix(homeDir, "~") {
		return "", bosherr.Errorf("Failed to get user '%s' home directory", username)
	}

	fs.logger.Debug(fs.logTag, "HomeDir is %s", homeDir)
	return homeDir, nil
}
Ejemplo n.º 25
0
func (fs *FakeFileSystem) ReadFile(path string) ([]byte, error) {
	stats := fs.GetFileTestStat(path)
	if stats != nil {
		if fs.ReadFileError != nil {
			return nil, fs.ReadFileError
		}

		if fs.readFileErrorByPath[path] != nil {
			return nil, fs.readFileErrorByPath[path]
		}

		return stats.Content, nil
	}
	return nil, bosherr.Errorf("File not found: '%s'", path)
}
func (s ParallelScript) summarizeErrs(passedScripts, failedScripts []string) error {
	if len(failedScripts) > 0 {
		errMsg := "Failed Jobs: " + strings.Join(failedScripts, ", ")

		if len(passedScripts) > 0 {
			errMsg += ". Successful Jobs: " + strings.Join(passedScripts, ", ")
		}

		totalRan := len(passedScripts) + len(failedScripts)

		return bosherr.Errorf("%d of %d %s scripts failed. %s.", len(failedScripts), totalRan, s.name, errMsg)
	}

	return nil
}
Ejemplo n.º 27
0
func (p *CertificateVerifier) Verify(peerCertificates []*x509.Certificate) error {
	if len(peerCertificates) < 1 {
		return errors.Error("No peer certificates provided by client")
	}
	subject := peerCertificates[0].Subject
	for _, pattern := range p.AllowedNames {
		matched, err := matchName(&pattern, &subject)
		if err != nil {
			return err
		}
		if matched {
			return nil
		}
	}
	return errors.Errorf("Subject (%#v) didn't match allowed distinguished names", subject)
}
Ejemplo n.º 28
0
func (m monitJobSupervisor) Reload() error {
	var currentIncarnation int

	oldIncarnation, err := m.getIncarnation()
	if err != nil {
		return bosherr.WrapError(err, "Getting monit incarnation")
	}

	// Monit process could be started in the same second as `monit reload` runs
	// so it's ideal for MaxCheckTries * DelayBetweenCheckTries to be greater than 1 sec
	// because monit incarnation id is just a timestamp with 1 sec resolution.
	for reloadI := 0; reloadI < m.reloadOptions.MaxTries; reloadI++ {
		// Exit code or output cannot be trusted
		_, _, _, err := m.runner.RunCommand("monit", "reload")
		if err != nil {
			m.logger.Error(monitJobSupervisorLogTag, "Failed to reload monit %s", err.Error())
		}

		for checkI := 0; checkI < m.reloadOptions.MaxCheckTries; checkI++ {
			currentIncarnation, err = m.getIncarnation()
			if err != nil {
				return bosherr.WrapError(err, "Getting monit incarnation")
			}

			// Incarnation id can decrease or increase because
			// monit uses time(...) and system time can be changed
			if oldIncarnation != currentIncarnation {
				return nil
			}

			m.logger.Debug(
				monitJobSupervisorLogTag,
				"Waiting for monit to reload: before=%d after=%d",
				oldIncarnation, currentIncarnation,
			)

			time.Sleep(m.reloadOptions.DelayBetweenCheckTries)
		}
	}

	return bosherr.Errorf(
		"Failed to reload monit: before=%d after=%d",
		oldIncarnation, currentIncarnation,
	)
}
Ejemplo n.º 29
0
func (s *SourceOptionsSlice) UnmarshalJSON(data []byte) error {
	var maps []map[string]interface{}

	err := json.Unmarshal(data, &maps)
	if err != nil {
		return bosherr.WrapError(err, "Unmarshalling sources")
	}

	for _, m := range maps {
		if optType, ok := m["Type"]; ok {
			var err error
			var opts SourceOptions

			switch {
			case optType == "HTTP":
				var o HTTPSourceOptions
				err, opts = mapstruc.Decode(m, &o), o

			case optType == "ConfigDrive":
				var o ConfigDriveSourceOptions
				err, opts = mapstruc.Decode(m, &o), o

			case optType == "File":
				var o FileSourceOptions
				err, opts = mapstruc.Decode(m, &o), o

			case optType == "CDROM":
				var o CDROMSourceOptions
				err, opts = mapstruc.Decode(m, &o), o

			default:
				err = bosherr.Errorf("Unknown source type '%s'", optType)
			}

			if err != nil {
				return bosherr.WrapErrorf(err, "Unmarshalling source type '%s'", optType)
			}
			*s = append(*s, opts)
		} else {
			return bosherr.Error("Missing source type")
		}
	}

	return nil
}
Ejemplo n.º 30
0
func (r *requestRetryable) Attempt() (bool, error) {
	var err error

	if r.requestID == "" {
		r.requestID, err = r.uuidGenerator.Generate()
		if err != nil {
			return false, bosherr.WrapError(err, "Generating request uuid")
		}
	}

	if r.request.Body != nil && r.bodyBytes == nil {
		r.bodyBytes, err = ReadAndClose(r.request.Body)
		if err != nil {
			return false, bosherr.WrapError(err, "Buffering request body")
		}
	}

	// reset request body, because readers cannot be re-read
	if r.bodyBytes != nil {
		r.request.Body = ioutil.NopCloser(bytes.NewReader(r.bodyBytes))
	}

	// close previous attempt's response body to prevent HTTP client resource leaks
	if r.response != nil {
		r.response.Body.Close()
	}

	r.attempt++

	r.logger.Debug(r.logTag, "[requestID=%s] Requesting (attempt=%d): %s", r.requestID, r.attempt, r.formatRequest(r.request))
	r.response, err = r.delegate.Do(r.request)
	if err != nil {
		r.logger.Debug(r.logTag, "[requestID=%s] Request attempt failed (attempts=%d), error: %s", r.requestID, r.attempt, err)
		return true, err
	}

	if r.wasSuccessful(r.response) {
		r.logger.Debug(r.logTag, "[requestID=%s] Request succeeded (attempts=%d), response: %s", r.requestID, r.attempt, r.formatResponse(r.response))
		return false, nil
	}

	r.logger.Debug(r.logTag, "[requestID=%s] Request attempt failed (attempts=%d), response: %s", r.requestID, r.attempt, r.formatResponse(r.response))
	return true, bosherr.Errorf("Request failed, response: %s", r.formatResponse(r.response))
}