Beispiel #1
0
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)
	}

}
Beispiel #2
0
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)
	}

}
Beispiel #3
0
// 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)
}
Beispiel #4
0
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{}},
	}

}
Beispiel #5
0
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)
			}
		}
	}
}
Beispiel #6
0
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
}
Beispiel #7
0
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
}
Beispiel #8
0
// 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
}