func Test_Build(t *testing.T) { ip, err := utils.GetIPAddress() if err != nil { t.Fatalf("Unexpected error %v", err) } empty := make([]string, 0) host, err := Build("", "65535", "test_pool", empty...) glog.Infof("build error %v", err) if err != nil { t.Errorf("Unexpected error %v", err) } if err = host.ValidEntity(); err != nil { t.Errorf("Validation failed %v", err) } if len(host.IPs) != 1 { t.Errorf("Unexpected result %v", host.IPs) } if host.IPAddr != ip { t.Errorf("Expected ip %v, got %v", ip, host.IPs) } if host.IPs[0].IPAddress != ip { t.Errorf("Expected ip %v, got %v", ip, host.IPs) } }
func TestGetInfo(t *testing.T) { ip, err := utils.GetIPAddress() if err != nil { t.Fatalf("Unexpected error %v", err) } staticIPs := []string{ip} agent := NewServer(staticIPs) h := host.New() request := BuildHostRequest{IP: "", PoolID: "testpool"} err = agent.BuildHost(request, h) if err != nil && !strings.Contains(err.Error(), "not valid for this host") { t.Fatalf("Unexpected error %v", err) } if len(h.IPs) != 0 { t.Fatalf("Unexpected result %v (%d)", h.IPs, len(h.IPs)) } request = BuildHostRequest{IP: "127.0.0.1", PoolID: "testpool"} err = agent.BuildHost(request, h) if err == nil || err.Error() != "loopback address 127.0.0.1 cannot be used to register a host" { t.Fatalf("Unexpected error %v", err) } request = BuildHostRequest{IP: "", PoolID: "testpool"} err = agent.BuildHost(request, h) if err == nil || !strings.Contains(err.Error(), "not valid for this host") { t.Errorf("Unexpected error %v", err) } }
// GetAgentIP returns the agent ip address func GetAgentIP(defaultRPCPort int) string { if options.Endpoint != "" { return options.Endpoint } agentIP, err := utils.GetIPAddress() if err != nil { panic(err) } return agentIP + fmt.Sprintf(":%d", defaultRPCPort) }
func init() { ip, err := utils.GetIPAddress() if err != nil { glog.Errorf("Could not determine ip %v", err) } validatetable = []validateCase{ validateCase{"", 65535, "", "", []string{"empty string for Host.ID", "empty string for Host.PoolID", "invalid IP Address "}}, validateCase{"hostid", 65535, "", "", []string{"empty string for Host.PoolID", "invalid IP Address "}}, validateCase{"", 65535, "poolid", "", []string{"empty string for Host.ID", "invalid IP Address "}}, validateCase{"hostid", 65535, "poolid", "", []string{"invalid IP Address "}}, validateCase{"hostid", 65535, "poolid", "blam", []string{"invalid IP Address blam"}}, validateCase{"hostid", 65535, "poolid", "127.0.0.1", []string{"host ip can not be a loopback address"}}, validateCase{"hostid", -1, "poolid", ip, []string{"not in valid port range: -1"}}, validateCase{"hostid", 65536, "poolid", ip, []string{"not in valid port range: 65536"}}, validateCase{"deadb30f", 65535, "poolid", ip, []string{}}, } }
func Test_getIPResources(t *testing.T) { ips, err := getIPResources("dummy_hostId", "123") if err == nil || err.Error() != "IP address 123 not valid for this host" { t.Errorf("Unexpected error %v", err) } if len(ips) != 0 { t.Errorf("Unexpected result %v", ips) } ips, err = getIPResources("dummy_hostId", "127.0.0.1") if err == nil || err.Error() != "loopback address 127.0.0.1 cannot be used as an IP Resource" { t.Errorf("Unexpected error %v", err) } if len(ips) != 0 { t.Errorf("Unexpected result %v", ips) } ip, err := utils.GetIPAddress() if err != nil { t.Fatalf("Unexpected error %v", err) } validIPs := []string{ip, strings.ToLower(ip), strings.ToUpper(ip)} for _, validIP := range validIPs { ips, err = getIPResources("dummy_hostId", validIP) if err != nil { if err != nil { t.Errorf("Unexpected error %v", err) } if len(ips) != 1 { t.Errorf("Unexpected result %v", ips) } } } }
func (d *daemon) startAgent() error { muxListener, err := createMuxListener() if err != nil { return err } mux, err := proxy.NewTCPMux(muxListener) if err != nil { return err } agentIP := options.OutboundIP if agentIP == "" { var err error agentIP, err = utils.GetIPAddress() if err != nil { glog.Fatalf("Failed to acquire ip address: %s", err) } } rpcPort := "0" parts := strings.Split(options.Listen, ":") if len(parts) > 1 { rpcPort = parts[1] } thisHost, err := host.Build(agentIP, rpcPort, "unknown") if err != nil { panic(err) } myHostID, err := utils.HostID() if err != nil { return fmt.Errorf("HostID failed: %v", err) } else if err := validation.ValidHostID(myHostID); err != nil { glog.Errorf("invalid hostid: %s", myHostID) } go func() { var poolID string for { poolID = func() string { glog.Infof("Trying to discover my pool...") var myHost *host.Host masterClient, err := master.NewClient(d.servicedEndpoint) if err != nil { glog.Errorf("master.NewClient failed (endpoint %+v) : %v", d.servicedEndpoint, err) return "" } defer masterClient.Close() myHost, err = masterClient.GetHost(myHostID) if err != nil { glog.Warningf("masterClient.GetHost %v failed: %v (has this host been added?)", myHostID, err) return "" } poolID = myHost.PoolID glog.Infof(" My PoolID: %v", poolID) //send updated host info updatedHost, err := host.UpdateHostInfo(*myHost) if err != nil { glog.Infof("Could not send updated host information: %v", err) return poolID } err = masterClient.UpdateHost(updatedHost) if err != nil { glog.Warningf("Could not update host information: %v", err) return poolID } glog.V(2).Infof("Sent updated host info %#v", updatedHost) return poolID }() if poolID != "" { break } select { case <-d.shutdown: return case <-time.After(5 * time.Second): continue } } thisHost.PoolID = poolID basePoolPath := "/pools/" + poolID dsn := coordzk.NewDSN(options.Zookeepers, time.Second*15).String() glog.Infof("zookeeper dsn: %s", dsn) zClient, err := coordclient.New("zookeeper", dsn, basePoolPath, nil) if err != nil { glog.Errorf("failed create a new coordclient: %v", err) } zzk.InitializeLocalClient(zClient) poolBasedConn, err := zzk.GetLocalConnection(zzk.GeneratePoolPath(poolID)) if err != nil { glog.Errorf("Error in getting a connection based on pool %v: %v", poolID, err) } if options.NFSClient != "0" { nfsClient, err := storage.NewClient(thisHost, path.Join(options.VarPath, "volumes")) if err != nil { glog.Fatalf("could not create an NFS client: %s", err) } go func() { <-d.shutdown glog.Infof("shutting down storage client") nfsClient.Close() }() //loop and log waiting for Storage Leader nfsDone := make(chan struct{}) go func() { defer close(nfsDone) nfsClient.Wait() }() //wait indefinitely(?) for storage to work before starting glog.Info("Waiting for Storage Leader") nfsUp := false for !nfsUp { select { case <-nfsDone: nfsUp = true glog.Info("Found Storage Leader") break case <-time.After(time.Second * 30): glog.Info("Waiting for Storage Leader, will not be available for running services. ") continue } } } else { glog.Info("NFS Client disabled") } agentOptions := node.AgentOptions{ PoolID: thisHost.PoolID, Master: options.Endpoint, UIPort: options.UIPort, RPCPort: options.RPCPort, DockerDNS: options.DockerDNS, VarPath: options.VarPath, Mount: options.Mount, FSType: options.FSType, Zookeepers: options.Zookeepers, Mux: mux, UseTLS: options.TLS, DockerRegistry: dockerRegistry, MaxContainerAge: time.Duration(int(time.Second) * options.MaxContainerAge), VirtualAddressSubnet: options.VirtualAddressSubnet, } // creates a zClient that is not pool based! hostAgent, err := node.NewHostAgent(agentOptions) d.hostAgent = hostAgent d.waitGroup.Add(1) go func() { hostAgent.Start(d.shutdown) glog.Info("Host Agent has shutdown") d.waitGroup.Done() }() // register the API glog.V(0).Infoln("registering ControlPlaneAgent service") if err = d.rpcServer.RegisterName("ControlPlaneAgent", hostAgent); err != nil { glog.Fatalf("could not register ControlPlaneAgent RPC server: %v", err) } if options.ReportStats { statsdest := fmt.Sprintf("http://%s/api/metrics/store", options.HostStats) statsduration := time.Duration(options.StatsPeriod) * time.Second glog.V(1).Infoln("Staring container statistics reporter") statsReporter, err := stats.NewStatsReporter(statsdest, statsduration, poolBasedConn) if err != nil { glog.Errorf("Error kicking off stats reporter %v", err) } else { go func() { defer statsReporter.Close() <-d.shutdown }() } } }() glog.Infof("agent start staticips: %v [%d]", d.staticIPs, len(d.staticIPs)) if err = d.rpcServer.RegisterName("Agent", agent.NewServer(d.staticIPs)); err != nil { glog.Fatalf("could not register Agent RPC server: %v", err) } if err != nil { glog.Fatalf("Could not start ControlPlane agent: %v", err) } // TODO: Integrate this server into the rpc server, or something. // Currently its only use is for command execution. go func() { sio := shell.NewProcessExecutorServer(options.Endpoint, dockerRegistry) http.ListenAndServe(":50000", sio) }() return nil }
func (d *daemon) startMaster() error { agentIP := options.OutboundIP if agentIP == "" { var err error agentIP, err = utils.GetIPAddress() if err != nil { glog.Fatalf("Failed to acquire ip address: %s", err) } } // This is storage related rpcPort := "0" parts := strings.Split(options.Listen, ":") if len(parts) > 1 { rpcPort = parts[1] } thisHost, err := host.Build(agentIP, rpcPort, d.masterPoolID) if err != nil { glog.Errorf("could not build host for agent IP %s: %v", agentIP, err) return err } if err := os.MkdirAll(options.VarPath, 0755); err != nil { glog.Errorf("could not create varpath %s: %s", options.VarPath, err) return err } volumesPath := path.Join(options.VarPath, "volumes") if d.networkDriver, err = nfs.NewServer(volumesPath, "serviced_var_volumes", "0.0.0.0/0"); err != nil { return err } else { d.storageHandler, err = storage.NewServer(d.networkDriver, thisHost, volumesPath) if err != nil { return err } } if d.dsDriver, err = d.initDriver(); err != nil { return err } if d.dsContext, err = d.initContext(); err != nil { return err } localClient, err := d.initZK(options.Zookeepers) if err != nil { glog.Errorf("failed to create a local coordclient: %v", err) return err } zzk.InitializeLocalClient(localClient) if len(options.RemoteZookeepers) > 0 { remoteClient, err := d.initZK(options.RemoteZookeepers) if err != nil { glog.Warningf("failed to create a remote coordclient; running in disconnected mode: %v", err) } else { zzk.InitializeRemoteClient(remoteClient) } } d.facade = d.initFacade() if d.cpDao, err = d.initDAO(); err != nil { return err } health.SetDao(d.cpDao) go health.Cleanup(d.shutdown) if err = d.facade.CreateDefaultPool(d.dsContext, d.masterPoolID); err != nil { return err } if err = d.registerMasterRPC(); err != nil { return err } d.initWeb() d.addTemplates() d.startScheduler() return nil }
// ListBackups lists all the backups in a given directory func (dfs *DistributedFilesystem) ListBackups(dirpath string) ([]dao.BackupFile, error) { backups := make([]dao.BackupFile, 0) if dirpath = strings.TrimSpace(dirpath); dirpath == "" { dirpath = utils.BackupDir(dfs.varpath) } else { dirpath = filepath.Clean(dirpath) } // Validate the path if fp, err := os.Stat(dirpath); os.IsNotExist(err) { // Directory not found means no backups yet return backups, nil } else if err != nil { glog.Errorf("Error looking up path %s: %s", dirpath, err) return nil, err } else if !fp.IsDir() { return nil, fmt.Errorf("path is not a directory") } // Get the list of files files, err := ioutil.ReadDir(dirpath) if err != nil { return nil, err } // Get the ip address hostIP, err := utils.GetIPAddress() if err != nil { return nil, err } // Filter backup files filemap := make(map[string]dao.BackupFile) for _, file := range files { if file.IsDir() { // If it is a directory, it could be the directory file for a // backup tgz, so mark the file as InProgress backup := filemap[file.Name()] backup.InProgress = true filemap[file.Name()] = backup } else if ext := filepath.Ext(file.Name()); ext == ".tgz" { // Create the backup file object abspath := filepath.Join(dirpath, file.Name()) name := strings.TrimSuffix(file.Name(), ext) backup := filemap[name] backup.FullPath = fmt.Sprintf("%s:%s", hostIP, abspath) backup.Name = abspath backup.Size = file.Size() backup.Mode = file.Mode() backup.ModTime = file.ModTime() filemap[name] = backup } } // Clean up non-backups for _, backup := range filemap { if backup.FullPath != "" { // Directories without a related backup file get filtered backups = append(backups, backup) } } return backups, nil }