func (net UbuntuNetManager) SetupNetworking(networks boshsettings.Networks, errCh chan error) error { staticConfigs, dhcpConfigs, dnsServers, err := net.ComputeNetworkConfig(networks) if err != nil { return bosherr.WrapError(err, "Computing network configuration") } interfacesChanged, err := net.writeNetworkInterfaces(dhcpConfigs, staticConfigs, dnsServers) if err != nil { return bosherr.WrapError(err, "Writing network configuration") } dhcpChanged := false if len(dhcpConfigs) > 0 { dhcpChanged, err = net.writeDHCPConfiguration(dnsServers) if err != nil { return err } } if interfacesChanged || dhcpChanged { err = net.removeDhcpDNSConfiguration() if err != nil { return err } net.restartNetworkingInterfaces() } net.broadcastIps(staticConfigs, dhcpConfigs, errCh) return nil }
func (p linux) partitionEphemeralDisk(realPath string) (string, string, error) { p.logger.Info(logTag, "Creating swap & ephemeral partitions on ephemeral disk...") p.logger.Debug(logTag, "Getting device size of `%s'", realPath) diskSizeInBytes, err := p.diskManager.GetPartitioner().GetDeviceSizeInBytes(realPath) if err != nil { return "", "", bosherr.WrapError(err, "Getting device size") } p.logger.Debug(logTag, "Calculating ephemeral disk partition sizes of `%s' with total disk size %dB", realPath, diskSizeInBytes) swapSizeInBytes, linuxSizeInBytes, err := p.calculateEphemeralDiskPartitionSizes(diskSizeInBytes) if err != nil { return "", "", bosherr.WrapError(err, "Calculating partition sizes") } partitions := []boshdisk.Partition{ {SizeInBytes: swapSizeInBytes, Type: boshdisk.PartitionTypeSwap}, {SizeInBytes: linuxSizeInBytes, Type: boshdisk.PartitionTypeLinux}, } p.logger.Info(logTag, "Partitioning ephemeral disk `%s' with %s", realPath, partitions) err = p.diskManager.GetPartitioner().Partition(realPath, partitions) if err != nil { return "", "", bosherr.WrapErrorf(err, "Partitioning ephemeral disk `%s'", realPath) } swapPartitionPath := realPath + "1" dataPartitionPath := realPath + "2" return swapPartitionPath, dataPartitionPath, nil }
func (a Agent) handleSyslogMsg(errCh chan error) boshsyslog.CallbackFunc { return func(msg boshsyslog.Msg) { alertAdapter := boshalert.NewSSHAdapter( msg, a.settingsService, a.uuidGenerator, a.timeService, a.logger, ) if alertAdapter.IsIgnorable() { a.logger.Debug(agentLogTag, "Ignored ssh event: ", msg.Content) return } alert, err := alertAdapter.Alert() if err != nil { errCh <- bosherr.WrapError(err, "Adapting SSH alert") } err = a.mbusHandler.Send(boshhandler.HealthMonitor, boshhandler.Alert, alert) if err != nil { errCh <- bosherr.WrapError(err, "Sending SSH alert") } } }
func (h *natsHandler) Start(handlerFunc boshhandler.Func) error { h.RegisterAdditionalFunc(handlerFunc) connProvider, err := h.getConnectionInfo() if err != nil { return bosherr.WrapError(err, "Getting connection info") } err = h.client.Connect(connProvider) if err != nil { return bosherr.WrapError(err, "Connecting") } settings := h.settingsService.GetSettings() subject := fmt.Sprintf("agent.%s", settings.AgentID) h.logger.Info(h.logTag, "Subscribing to %s", subject) _, err = h.client.Subscribe(subject, func(natsMsg *yagnats.Message) { for _, handlerFunc := range h.handlerFuncs { h.handleNatsMsg(natsMsg, handlerFunc) } }) if err != nil { return bosherr.WrapErrorf(err, "Subscribing to %s", subject) } return nil }
func marshalResponse(response Response, maxResponseLength int, logger boshlog.Logger) ([]byte, error) { respJSON, err := json.Marshal(response) if err != nil { logger.Error(mbusHandlerLogTag, "Failed to marshal response: %s", err.Error()) return respJSON, bosherr.WrapError(err, "Marshalling JSON response") } if maxResponseLength == UnlimitedResponseLength { return respJSON, nil } if len(respJSON) > maxResponseLength { respJSON, err = json.Marshal(response.Shorten()) if err != nil { logger.Error(mbusHandlerLogTag, "Failed to marshal response: %s", err.Error()) return respJSON, bosherr.WrapError(err, "Marshalling JSON response") } } if len(respJSON) > maxResponseLength { respJSON, err = BuildErrorWithJSON(responseMaxLengthErrMsg, logger) if err != nil { logger.Error(mbusHandlerLogTag, "Failed to build 'max length exceeded' response: %s", err.Error()) return respJSON, bosherr.WrapError(err, "Building error") } } return respJSON, nil }
func (net UbuntuNetManager) writeNetworkInterfaces(dhcpConfigs DHCPInterfaceConfigurations, staticConfigs StaticInterfaceConfigurations, dnsServers []string) (bool, error) { sort.Stable(dhcpConfigs) sort.Stable(staticConfigs) networkInterfaceValues := networkInterfaceConfig{ DHCPConfigs: dhcpConfigs, StaticConfigs: staticConfigs, HasDNSNameServers: true, DNSServers: dnsServers, } buffer := bytes.NewBuffer([]byte{}) t := template.Must(template.New("network-interfaces").Parse(networkInterfacesTemplate)) err := t.Execute(buffer, networkInterfaceValues) if err != nil { return false, bosherr.WrapError(err, "Generating config from template") } changed, err := net.fs.ConvergeFileContents("/etc/network/interfaces", buffer.Bytes()) if err != nil { return changed, bosherr.WrapError(err, "Writing to /etc/network/interfaces") } return changed, nil }
func (a Agent) handleJobFailure(errCh chan error) boshjobsuper.JobFailureHandler { return func(monitAlert boshalert.MonitAlert) error { alertAdapter := boshalert.NewMonitAdapter(monitAlert, a.settingsService, a.timeService) if alertAdapter.IsIgnorable() { a.logger.Debug(agentLogTag, "Ignored monit event: ", monitAlert.Event) return nil } severity, found := alertAdapter.Severity() if !found { a.logger.Error(agentLogTag, "Unknown monit event name `%s', using default severity %d", monitAlert.Event, severity) } alert, err := alertAdapter.Alert() if err != nil { errCh <- bosherr.WrapError(err, "Adapting monit alert") } err = a.mbusHandler.Send(boshhandler.HealthMonitor, boshhandler.Alert, alert) if err != nil { errCh <- bosherr.WrapError(err, "Sending monit alert") } return nil } }
func (a DrainAction) Run(drainType DrainType, newSpecs ...boshas.V1ApplySpec) (int, error) { currentSpec, err := a.specService.Get() if err != nil { return 0, bosherr.WrapError(err, "Getting current spec") } params, err := a.determineParams(drainType, currentSpec, newSpecs) if err != nil { return 0, err } a.logger.Debug(a.logTag, "Unmonitoring") err = a.jobSupervisor.Unmonitor() if err != nil { return 0, bosherr.WrapError(err, "Unmonitoring services") } var scripts []boshscript.Script for _, job := range currentSpec.Jobs() { script := a.jobScriptProvider.NewDrainScript(job.BundleName(), params) scripts = append(scripts, script) } parallelScript := a.jobScriptProvider.NewParallelScript("drain", scripts) return 0, parallelScript.Run() }
func (a ApplyAction) Run(desiredSpec boshas.V1ApplySpec) (string, error) { settings := a.settingsService.GetSettings() resolvedDesiredSpec, err := a.specService.PopulateDHCPNetworks(desiredSpec, settings) if err != nil { return "", bosherr.WrapError(err, "Resolving dynamic networks") } if desiredSpec.ConfigurationHash != "" { currentSpec, err := a.specService.Get() if err != nil { return "", bosherr.WrapError(err, "Getting current spec") } err = a.applier.Apply(currentSpec, resolvedDesiredSpec) if err != nil { return "", bosherr.WrapError(err, "Applying") } } err = a.specService.Set(resolvedDesiredSpec) if err != nil { return "", bosherr.WrapError(err, "Persisting apply spec") } return "applied", nil }
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 }
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 }
func (a SSHAction) setupSSH(params SSHParams) (SSHResult, error) { var result SSHResult boshSSHPath := filepath.Join(a.dirProvider.BaseDir(), "bosh_ssh") err := a.platform.CreateUser(params.User, params.Password, boshSSHPath) if err != nil { return result, bosherr.WrapError(err, "Creating user") } err = a.platform.AddUserToGroups(params.User, []string{boshsettings.VCAPUsername, boshsettings.AdminGroup}) if err != nil { return result, bosherr.WrapError(err, "Adding user to groups") } err = a.platform.SetupSSH(params.PublicKey, params.User) if err != nil { return result, bosherr.WrapError(err, "Setting ssh public key") } settings := a.settingsService.GetSettings() defaultIP, found := settings.Networks.DefaultIP() if !found { return result, errors.New("No default ip could be found") } result = SSHResult{ Command: "setup", Status: "success", IP: defaultIP, } return result, nil }
func (p linux) findRootDevicePath() (string, error) { mounts, err := p.diskManager.GetMountsSearcher().SearchMounts() if err != nil { return "", bosherr.WrapError(err, "Searching mounts") } for _, mount := range mounts { if mount.MountPoint == "/" && strings.HasPrefix(mount.PartitionPath, "/dev/") { p.logger.Debug(logTag, "Found root partition: `%s'", mount.PartitionPath) stdout, _, _, err := p.cmdRunner.RunCommand("readlink", "-f", mount.PartitionPath) if err != nil { return "", bosherr.WrapError(err, "Shelling out to readlink") } rootPartition := strings.Trim(stdout, "\n") p.logger.Debug(logTag, "Symlink is: `%s'", rootPartition) validRootPartition := regexp.MustCompile(`^/dev/[a-z]+1$`) if !validRootPartition.MatchString(rootPartition) { return "", bosherr.Error("Root partition is not the first partition") } return strings.Trim(rootPartition, "1"), nil } } return "", bosherr.Error("Getting root partition device") }
func (ms httpMetadataService) GetInstanceID() (string, error) { err := ms.ensureMinimalNetworkSetup() if err != nil { return "", err } url := fmt.Sprintf("%s/latest/meta-data/instance-id", ms.metadataHost) resp, err := http.Get(url) if err != nil { return "", bosherr.WrapError(err, "Getting instance id from url") } defer func() { if err := resp.Body.Close(); err != nil { ms.logger.Warn(ms.logTag, "Failed to close response body when getting instance id: %s", err.Error()) } }() bytes, err := ioutil.ReadAll(resp.Body) if err != nil { return "", bosherr.WrapError(err, "Reading instance id response body") } return string(bytes), nil }
func (ms httpMetadataService) getUserData() (UserDataContentsType, error) { var userData UserDataContentsType err := ms.ensureMinimalNetworkSetup() if err != nil { return userData, err } userDataURL := fmt.Sprintf("%s/latest/user-data", ms.metadataHost) userDataResp, err := http.Get(userDataURL) if err != nil { return userData, bosherr.WrapError(err, "Getting user data from url") } 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.WrapError(err, "Unmarshalling user data") } return userData, nil }
func (net centosNetManager) detectMacAddresses() (map[string]string, error) { addresses := map[string]string{} filePaths, err := net.fs.Glob("/sys/class/net/*") if err != nil { return addresses, bosherr.WrapError(err, "Getting file list from /sys/class/net") } var macAddress string for _, filePath := range filePaths { isPhysicalDevice := net.fs.FileExists(filepath.Join(filePath, "device")) if isPhysicalDevice { macAddress, err = net.fs.ReadFileString(filepath.Join(filePath, "address")) if err != nil { return addresses, bosherr.WrapError(err, "Reading mac address from file") } macAddress = strings.Trim(macAddress, "\n") interfaceName := filepath.Base(filePath) addresses[macAddress] = interfaceName } } return addresses, nil }
func (p linux) MigratePersistentDisk(fromMountPoint, toMountPoint string) (err error) { p.logger.Debug(logTag, "Migrating persistent disk %v to %v", fromMountPoint, toMountPoint) err = p.diskManager.GetMounter().RemountAsReadonly(fromMountPoint) if err != nil { err = bosherr.WrapError(err, "Remounting persistent disk as readonly") return } // Golang does not implement a file copy that would allow us to preserve dates... // So we have to shell out to tar to perform the copy instead of delegating to the FileSystem tarCopy := fmt.Sprintf("(tar -C %s -cf - .) | (tar -C %s -xpf -)", fromMountPoint, toMountPoint) _, _, _, err = p.cmdRunner.RunCommand("sh", "-c", tarCopy) if err != nil { err = bosherr.WrapError(err, "Copying files from old disk to new disk") return } _, err = p.diskManager.GetMounter().Unmount(fromMountPoint) if err != nil { err = bosherr.WrapError(err, "Unmounting old persistent disk") return } err = p.diskManager.GetMounter().Remount(toMountPoint, fromMountPoint) if err != nil { err = bosherr.WrapError(err, "Remounting new disk on original mountpoint") } return }
func (r concreteRunner) Run(action Action, payloadBytes []byte) (value interface{}, err error) { payloadArgs, err := r.extractJSONArguments(payloadBytes) if err != nil { err = bosherr.WrapError(err, "Extracting json arguments") return } actionValue := reflect.ValueOf(action) runMethodValue := actionValue.MethodByName("Run") if runMethodValue.Kind() != reflect.Func { err = bosherr.Error("Run method not found") return } runMethodType := runMethodValue.Type() if r.invalidReturnTypes(runMethodType) { err = bosherr.Error("Run method should return a value and an error") return } methodArgs, err := r.extractMethodArgs(runMethodType, payloadArgs) if err != nil { err = bosherr.WrapError(err, "Extracting method arguments from payload") return } values := runMethodValue.Call(methodArgs) return r.extractReturns(values) }
func (p linux) SetupHostname(hostname string) (err error) { _, _, _, err = p.cmdRunner.RunCommand("hostname", hostname) if err != nil { err = bosherr.WrapError(err, "Shelling out to hostname") return } err = p.fs.WriteFileString("/etc/hostname", hostname) if err != nil { err = bosherr.WrapError(err, "Writing /etc/hostname") return } buffer := bytes.NewBuffer([]byte{}) t := template.Must(template.New("etc-hosts").Parse(etcHostsTemplate)) err = t.Execute(buffer, hostname) if err != nil { err = bosherr.WrapError(err, "Generating config from template") return } err = p.fs.WriteFile("/etc/hosts", buffer.Bytes()) if err != nil { err = bosherr.WrapError(err, "Writing to /etc/hosts") } return }
func (ms *configDriveMetadataService) loadFromDiskPath(diskPath string) error { contentPaths := []string{ms.metaDataFilePath, ms.userDataFilePath} contents, err := ms.platform.GetFilesContentsFromDisk(diskPath, contentPaths) if err != nil { return bosherr.WrapError(err, "Reading files on config drive") } var metadata MetadataContentsType err = json.Unmarshal(contents[0], &metadata) if err != nil { return bosherr.WrapError(err, "Parsing config drive metadata from meta_data.json") } ms.metaDataContents = metadata var userdata UserDataContentsType err = json.Unmarshal(contents[1], &userdata) if err != nil { return bosherr.WrapError(err, "Parsing config drive metadata from user_data") } ms.userDataContents = userdata return nil }
func (net centosNetManager) writeNetworkInterfaces(dhcpInterfaceConfigurations []DHCPInterfaceConfiguration, staticInterfaceConfigurations []StaticInterfaceConfiguration, dnsServers []string) (bool, error) { anyInterfaceChanged := false staticConfig := centosStaticIfcfg{} staticConfig.DNSServers = newDNSConfigs(dnsServers) staticTemplate := template.Must(template.New("ifcfg").Parse(centosStaticIfcfgTemplate)) for i := range staticInterfaceConfigurations { staticConfig.StaticInterfaceConfiguration = &staticInterfaceConfigurations[i] changed, err := net.writeIfcfgFile(staticConfig.StaticInterfaceConfiguration.Name, staticTemplate, staticConfig) if err != nil { return false, bosherr.WrapError(err, "Writing static config") } anyInterfaceChanged = anyInterfaceChanged || changed } dhcpTemplate := template.Must(template.New("ifcfg").Parse(centosDHCPIfcfgTemplate)) for i := range dhcpInterfaceConfigurations { config := &dhcpInterfaceConfigurations[i] changed, err := net.writeIfcfgFile(config.Name, dhcpTemplate, config) if err != nil { return false, bosherr.WrapError(err, "Writing dhcp config") } anyInterfaceChanged = anyInterfaceChanged || changed } return anyInterfaceChanged, nil }
func (s concreteService) Get() (vitals Vitals, err error) { var ( loadStats boshstats.CPULoad cpuStats boshstats.CPUStats memStats boshstats.Usage swapStats boshstats.Usage diskStats DiskVitals ) loadStats, err = s.statsCollector.GetCPULoad() if err != nil { err = bosherr.WrapError(err, "Getting CPU Load") return } cpuStats, err = s.statsCollector.GetCPUStats() if err != nil { err = bosherr.WrapError(err, "Getting CPU Stats") return } memStats, err = s.statsCollector.GetMemStats() if err != nil { err = bosherr.WrapError(err, "Getting Memory Stats") return } swapStats, err = s.statsCollector.GetSwapStats() if err != nil { err = bosherr.WrapError(err, "Getting Swap Stats") return } diskStats, err = s.getDiskStats() if err != nil { err = bosherr.WrapError(err, "Getting Disk Stats") return } vitals = Vitals{ Load: []string{ fmt.Sprintf("%.2f", loadStats.One), fmt.Sprintf("%.2f", loadStats.Five), fmt.Sprintf("%.2f", loadStats.Fifteen), }, CPU: CPUVitals{ User: cpuStats.UserPercent().FormatFractionOf100(1), Sys: cpuStats.SysPercent().FormatFractionOf100(1), Wait: cpuStats.WaitPercent().FormatFractionOf100(1), }, Mem: createMemVitals(memStats), Swap: createMemVitals(swapStats), Disk: diskStats, } return }
func (p sfdiskPartitioner) GetDeviceSizeInBytes(devicePath string) (uint64, error) { stdout, _, _, err := p.cmdRunner.RunCommand("sfdisk", "-s", devicePath) if err != nil { return 0, bosherr.WrapError(err, "Shelling out to sfdisk") } sizeInKb, err := strconv.ParseUint(strings.Trim(stdout, "\n"), 10, 64) if err != nil { return 0, bosherr.WrapError(err, "Converting disk size to integer") } return p.convertFromKbToBytes(sizeInKb), nil }
func (p linux) StartMonit() error { err := p.fs.Symlink(filepath.Join("/etc", "sv", "monit"), filepath.Join("/etc", "service", "monit")) if err != nil { return bosherr.WrapError(err, "Symlinking /etc/service/monit to /etc/sv/monit") } err = p.monitRetryStrategy.Try() if err != nil { return bosherr.WrapError(err, "Retrying to start monit") } return nil }
func (m *concreteManager) writeInfos(taskInfos map[string]Info) error { newTasksJSON, err := json.Marshal(taskInfos) if err != nil { return bosherr.WrapError(err, "Marshalling tasks json") } err = m.fs.WriteFile(m.tasksPath, newTasksJSON) if err != nil { return bosherr.WrapError(err, "Writing tasks json") } return nil }
func (a PrepareConfigureNetworksAction) Run() (string, error) { err := a.settingsService.InvalidateSettings() if err != nil { return "", bosherr.WrapError(err, "Invalidating settings") } err = a.platform.PrepareForNetworkingChange() if err != nil { return "", bosherr.WrapError(err, "Preparing for networking change") } return "ok", nil }
// Set unmarshals and writes to the file. func (s concreteV1Service) Set(spec V1ApplySpec) error { specBytes, err := json.Marshal(spec) if err != nil { return bosherr.WrapError(err, "Marshalling apply spec") } err = s.fs.WriteFile(s.specFilePath, specBytes) if err != nil { return bosherr.WrapError(err, "Writing spec to disk") } return nil }
func (b externalBlobstore) writeConfigFile() error { configJSON, err := json.Marshal(b.options) if err != nil { return bosherr.WrapError(err, "Marshalling JSON") } err = b.fs.WriteFile(b.configFilePath, configJSON) if err != nil { return bosherr.WrapError(err, "Writing config file") } return nil }
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 }
func (a Agent) sendHeartbeat(errCh chan error) { heartbeat, err := a.getHeartbeat() if err != nil { err = bosherr.WrapError(err, "Building heartbeat") errCh <- err return } err = a.mbusHandler.Send(boshhandler.HealthMonitor, boshhandler.Heartbeat, heartbeat) if err != nil { err = bosherr.WrapError(err, "Sending heartbeat") errCh <- err } }