コード例 #1
0
ファイル: main.go プロジェクト: datatonic/Dominator
func main() {
	flag.Usage = printUsage
	flag.Parse()
	if flag.NArg() < 1 {
		printUsage()
		os.Exit(2)
	}
	setupTls(*certFile, *keyFile)
	clientName := fmt.Sprintf("%s:%d",
		*imageServerHostname, *imageServerPortNum)
	imageClient, err := rpc.DialHTTP("tcp", clientName)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error dialing\t%s\n", err)
		os.Exit(1)
	}
	imageSClient, err := srpc.DialHTTP("tcp", clientName)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error dialing\t%s\n", err)
		os.Exit(1)
	}
	objectClient := objectclient.NewObjectClient(clientName)
	for _, subcommand := range subcommands {
		if flag.Arg(0) == subcommand.command {
			if flag.NArg()-1 != subcommand.numArgs {
				printUsage()
				os.Exit(2)
			}
			subcommand.cmdFunc(imageClient, imageSClient, objectClient,
				flag.Args()[1:])
			os.Exit(3)
		}
	}
	printUsage()
	os.Exit(2)
}
コード例 #2
0
ファイル: pushImage.go プロジェクト: keep94/Dominator
func getImageRetry(clientName, imageName string,
	timeoutTime time.Time) (*image.Image, error) {
	imageSrpcClient, err := srpc.DialHTTP("tcp", clientName, 0)
	if err != nil {
		return nil, err
	}
	defer imageSrpcClient.Close()
	for ; time.Now().Before(timeoutTime); time.Sleep(time.Second) {
		img, err := imgclient.GetImage(imageSrpcClient, imageName)
		if err != nil {
			return nil, err
		} else if img != nil {
			if err := img.FileSystem.RebuildInodePointers(); err != nil {
				return nil, err
			}
			img.FileSystem.InodeToFilenamesTable()
			img.FileSystem.FilenameToInodeTable()
			img.FileSystem.HashToInodesTable()
			img.FileSystem.ComputeTotalDataBytes()
			img.FileSystem.BuildEntryMap()
			return img, nil
		}
	}
	return nil, errors.New("timed out getting image")
}
コード例 #3
0
ファイル: main.go プロジェクト: keep94/Dominator
func main() {
	flag.Usage = printUsage
	flag.Parse()
	if flag.NArg() < 1 {
		printUsage()
		os.Exit(2)
	}
	if err := setupclient.SetupTls(true); err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
	clientName := fmt.Sprintf("%s:%d", *domHostname, *domPortNum)
	client, err := srpc.DialHTTP("tcp", clientName, 0)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error dialing\t%s\n", err)
		os.Exit(1)
	}
	for _, subcommand := range subcommands {
		if flag.Arg(0) == subcommand.command {
			if flag.NArg()-1 != subcommand.numArgs {
				printUsage()
				os.Exit(2)
			}
			subcommand.cmdFunc(client, flag.Args()[1:])
			os.Exit(3)
		}
	}
	printUsage()
	os.Exit(2)
}
コード例 #4
0
ファイル: sub.go プロジェクト: datatonic/Dominator
func (sub *Sub) connectAndPoll() {
	previousStatus := sub.status
	sub.status = statusConnecting
	hostname := strings.SplitN(sub.hostname, "*", 2)[0]
	address := fmt.Sprintf("%s:%d", hostname, constants.SubPortNumber)
	sub.lastConnectionStartTime = time.Now()
	srpcClient, err := srpc.DialHTTP("tcp", address)
	if err != nil {
		if err, ok := err.(*net.OpError); ok {
			if _, ok := err.Err.(*net.DNSError); ok {
				sub.status = statusDNSError
				return
			}
		}
		sub.status = statusFailedToConnect
		return
	}
	defer srpcClient.Close()
	sub.status = statusWaitingToPoll
	sub.lastConnectionSucceededTime = time.Now()
	sub.lastConnectDuration =
		sub.lastConnectionSucceededTime.Sub(sub.lastConnectionStartTime)
	connectDistribution.Add(sub.lastConnectDuration)
	if sub.herd.getImage(sub.requiredImage) == nil {
		sub.status = statusImageNotReady
		return
	}
	sub.herd.pollSemaphore <- true
	sub.status = statusPolling
	sub.poll(srpcClient, previousStatus)
	<-sub.herd.pollSemaphore
}
コード例 #5
0
ファイル: getObjects.go プロジェクト: datatonic/Dominator
func (objClient *ObjectClient) getObjects(hashes []hash.Hash) (
	*ObjectsReader, error) {
	client, err := srpc.DialHTTP("tcp", objClient.address)
	if err != nil {
		return nil, errors.New(fmt.Sprintf("Error dialing\t%s\n", err))
	}
	conn, err := client.Call("ObjectServer.GetObjects")
	if err != nil {
		return nil, errors.New(fmt.Sprintf("Error calling\t%s\n", err))
	}
	var request objectserver.GetObjectsRequest
	var reply objectserver.GetObjectsResponse
	request.Exclusive = objClient.exclusiveGet
	request.Hashes = hashes
	encoder := gob.NewEncoder(conn)
	encoder.Encode(request)
	conn.Flush()
	var objectsReader ObjectsReader
	objectsReader.client = client
	objectsReader.reader = conn
	decoder := gob.NewDecoder(objectsReader.reader)
	err = decoder.Decode(&reply)
	if err != nil {
		return nil, err
	}
	if reply.ResponseString != "" {
		return nil, errors.New(reply.ResponseString)
	}
	objectsReader.nextIndex = -1
	objectsReader.sizes = reply.ObjectSizes
	return &objectsReader, nil
}
コード例 #6
0
ファイル: main.go プロジェクト: keep94/Dominator
func getSubClient() *srpc.Client {
	clientName := fmt.Sprintf("%s:%d", *subHostname, *subPortNum)
	client, err := srpc.DialHTTP("tcp", clientName, time.Second*5)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error dialing %s: %s\n", clientName, err)
		os.Exit(3)
	}
	return client
}
コード例 #7
0
ファイル: poll.go プロジェクト: datatonic/Dominator
func pollSubcommand(srpcClient *srpc.Client, args []string) {
	var err error
	clientName := fmt.Sprintf("%s:%d", *subHostname, *subPortNum)
	for iter := 0; *numPolls < 0 || iter < *numPolls; iter++ {
		if iter > 0 {
			time.Sleep(time.Duration(*interval) * time.Second)
		}
		if srpcClient == nil {
			srpcClient, err = srpc.DialHTTP("tcp", clientName)
			if err != nil {
				fmt.Fprintf(os.Stderr, "Error dialing\t%s\n", err)
				os.Exit(1)
			}
		}
		var request sub.PollRequest
		var reply sub.PollResponse
		pollStartTime := time.Now()
		err = client.CallPoll(srpcClient, request, &reply)
		fmt.Printf("Poll duration: %s\n", time.Since(pollStartTime))
		if err != nil {
			fmt.Fprintf(os.Stderr, "Error calling\t%s\n", err)
			os.Exit(1)
		}
		if *newConnection {
			srpcClient.Close()
			srpcClient = nil
		}
		fs := reply.FileSystem
		if fs == nil {
			fmt.Println("No FileSystem pointer")
		} else {
			fs.RebuildInodePointers()
			if *debug {
				fs.List(os.Stdout)
			} else {
				fmt.Println(fs)
			}
			fmt.Printf("Num objects: %d\n", len(reply.ObjectCache))
			if *file != "" {
				f, err := os.Create(*file)
				if err != nil {
					fmt.Fprintf(os.Stderr, "Error creating: %s\t%s\n",
						*file, err)
					os.Exit(1)
				}
				encoder := gob.NewEncoder(f)
				encoder.Encode(fs)
				f.Close()
			}
		}
	}
	time.Sleep(time.Duration(*wait) * time.Second)
}
コード例 #8
0
ファイル: main.go プロジェクト: keep94/Dominator
func getClients() (*srpc.Client, *objectclient.ObjectClient) {
	if imageSrpcClient == nil {
		var err error
		clientName := fmt.Sprintf("%s:%d",
			*imageServerHostname, *imageServerPortNum)
		imageSrpcClient, err = srpc.DialHTTP("tcp", clientName, 0)
		if err != nil {
			fmt.Fprintf(os.Stderr, "Error dialing\t%s\n", err)
			os.Exit(1)
		}
		theObjectClient = objectclient.NewObjectClient(clientName)
	}
	return imageSrpcClient, theObjectClient
}
コード例 #9
0
ファイル: client.go プロジェクト: keep94/Dominator
func (objClient *ObjectClient) getClient() (*srpc.Client, error) {
	if objClient.client != nil {
		return objClient.client, nil
	}
	if objClient.address == "" {
		return nil, errors.New("no client address")
	}
	srpcClient, err := srpc.DialHTTP("tcp", objClient.address, 0)
	if err != nil {
		return nil, fmt.Errorf("error dialing: %s: %s", objClient.address, err)
	}
	objClient.client = srpcClient
	return objClient.client, nil
}
コード例 #10
0
ファイル: addImagesub.go プロジェクト: keep94/Dominator
func copyMissingObjects(fs *filesystem.FileSystem, imageSClient *srpc.Client,
	objectClient *objectclient.ObjectClient, subName string) error {
	// Check to see which objects are in the objectserver.
	hashes := make([]hash.Hash, 0, fs.NumRegularInodes)
	for hash, _ := range fs.HashToInodesTable() {
		hashes = append(hashes, hash)
	}
	objectSizes, err := objectClient.CheckObjects(hashes)
	if err != nil {
		return err
	}
	missingHashes := make([]hash.Hash, 0)
	for index, size := range objectSizes {
		if size < 1 {
			missingHashes = append(missingHashes, hashes[index])
		}
	}
	if len(missingHashes) < 1 {
		return nil
	}
	// Get missing objects from sub.
	filesForMissingObjects := make([]string, 0, len(missingHashes))
	for _, hash := range missingHashes {
		if inums, ok := fs.HashToInodesTable()[hash]; !ok {
			return fmt.Errorf("no inode for object: %x", hash)
		} else if files, ok := fs.InodeToFilenamesTable()[inums[0]]; !ok {
			return fmt.Errorf("no file for inode: %d", inums[0])
		} else {
			filesForMissingObjects = append(filesForMissingObjects, files[0])
		}
	}
	objAdderQueue, err := objectclient.NewObjectAdderQueue(imageSClient)
	if err != nil {
		return err
	}
	subClient, err := srpc.DialHTTP("tcp",
		fmt.Sprintf("%s:%d", subName, constants.SubPortNumber), 0)
	if err != nil {
		return fmt.Errorf("error dialing %s", err)
	}
	defer subClient.Close()
	if err := subclient.GetFiles(subClient, filesForMissingObjects,
		func(reader io.Reader, size uint64) error {
			_, err := objAdderQueue.Add(reader, size)
			return err
		}); err != nil {
		return err
	}
	return objAdderQueue.Close()
}
コード例 #11
0
ファイル: addObject.go プロジェクト: datatonic/Dominator
func (objClient *ObjectClient) addObject(reader io.Reader, length uint64,
	expectedHash *hash.Hash) (hash.Hash, bool, error) {
	var request objectserver.AddObjectRequest
	var reply objectserver.AddObjectResponse
	if length < 1 {
		return reply.Hash, false, errors.New(
			"zero length object cannot be added")
	}
	srpcClient, err := srpc.DialHTTP("tcp", objClient.address)
	if err != nil {
		return reply.Hash, false, errors.New(
			fmt.Sprintf("Error dialing\t%s\n", err.Error()))
	}
	defer srpcClient.Close()
	conn, err := srpcClient.Call("ObjectServer.AddObjects")
	if err != nil {
		return reply.Hash, false, err
	}
	defer conn.Close()
	request.Length = length
	request.ExpectedHash = expectedHash
	encoder := gob.NewEncoder(conn)
	encoder.Encode(request)
	nCopied, err := io.Copy(conn, reader)
	if err != nil {
		return reply.Hash, false, err
	}
	if uint64(nCopied) != length {
		return reply.Hash, false, errors.New(fmt.Sprintf(
			"failed to copy, wanted: %d, got: %d bytes", length, nCopied))
	}
	conn.Flush()
	decoder := gob.NewDecoder(conn)
	if err := decoder.Decode(&reply); err != nil {
		return reply.Hash, false, err
	}
	if reply.Error != nil {
		return reply.Hash, false, err
	}
	if expectedHash != nil && *expectedHash != reply.Hash {
		return reply.Hash, false, errors.New(fmt.Sprintf(
			"received hash: %x != expected: %x",
			reply.Hash, *expectedHash))
	}
	return reply.Hash, reply.Added, nil
}
コード例 #12
0
ファイル: image.go プロジェクト: datatonic/Dominator
func (herd *Herd) getImageHaveLock(name string) *image.Image {
	if name == "" {
		return nil
	}
	if image := herd.imagesByName[name]; image != nil {
		return image
	}
	// Image not yet known. If it was recently found to be missing, report it
	// as missing. This avoids hammering the imageserver with "are we there
	// yet?", "are we there yet?", "are we there yet?" queries.
	if lastCheck, ok := herd.missingImages[name]; ok {
		if time.Since(lastCheck).Seconds() < 1 {
			return nil
		}
	}
	imageClient, err := srpc.DialHTTP("tcp", herd.imageServerAddress)
	if err != nil {
		herd.logger.Println(err)
		return nil
	}
	defer imageClient.Close()
	var request imageserver.GetImageRequest
	request.ImageName = name
	var reply imageserver.GetImageResponse
	err = client.CallGetImage(imageClient, request, &reply)
	if err != nil {
		herd.logger.Printf("Error calling\t%s\n", err)
		return nil
	}
	if reply.Image == nil {
		herd.missingImages[name] = time.Now()
	} else {
		if err := reply.Image.FileSystem.RebuildInodePointers(); err != nil {
			herd.logger.Printf("Error building inode pointers for image: %s %s",
				name, err)
			return nil
		}
		delete(herd.missingImages, name)
		reply.Image.FileSystem.BuildEntryMap()
		reply.Image.FileSystem.BuildInodeToFilenamesTable()
		reply.Image.FileSystem.BuildHashToInodesTable()
		herd.imagesByName[name] = reply.Image
		herd.logger.Printf("Got image: %s\n", name)
	}
	return reply.Image
}
コード例 #13
0
ファイル: addObjects.go プロジェクト: keep94/Dominator
func addObjects(address string, filenames []string) error {
	client, err := srpc.DialHTTP("tcp", address, 0)
	if err != nil {
		return err
	}
	defer client.Close()
	objQ, err := objectclient.NewObjectAdderQueue(client)
	if err != nil {
		return err
	}
	for _, filename := range filenames {
		if err := addObject(objQ, filename); err != nil {
			objQ.Close()
			return err
		}
	}
	return objQ.Close()
}
コード例 #14
0
ファイル: diffImages.go プロジェクト: keep94/Dominator
func pollImage(name string) (*filesystem.FileSystem, error) {
	clientName := fmt.Sprintf("%s:%d", name, constants.SubPortNumber)
	srpcClient, err := srpc.DialHTTP("tcp", clientName, 0)
	if err != nil {
		return nil, errors.New(fmt.Sprintf("Error dialing %s", err))
	}
	defer srpcClient.Close()
	var request sub.PollRequest
	var reply sub.PollResponse
	if err = subclient.CallPoll(srpcClient, request, &reply); err != nil {
		return nil, err
	}
	if reply.FileSystem == nil {
		return nil, errors.New("no poll data")
	}
	reply.FileSystem.RebuildInodePointers()
	return reply.FileSystem, nil
}
コード例 #15
0
ファイル: main.go プロジェクト: keep94/Dominator
func getSubClientRetry() *srpc.Client {
	clientName := fmt.Sprintf("%s:%d", *subHostname, *subPortNum)
	var client *srpc.Client
	var err error
	for time.Now().Before(timeoutTime) {
		client, err = srpc.DialHTTP("tcp", clientName, time.Second*5)
		if err == nil {
			return client
		}
		if err == srpc.ErrorMissingCertificate ||
			err == srpc.ErrorBadCertificate ||
			err == srpc.ErrorAccessToMethodDenied {
			// Never going to happen. Bail out.
			fmt.Fprintf(os.Stderr, "Error dialing %s: %s\n", clientName, err)
			os.Exit(3)
		}
	}
	fmt.Fprintf(os.Stderr, "Error dialing %s: %s\n", clientName, err)
	os.Exit(3)
	return nil
}
コード例 #16
0
ファイル: queue.go プロジェクト: datatonic/Dominator
func newObjectAdderQueue(objClient *ObjectClient) (*ObjectAdderQueue, error) {
	var objQ ObjectAdderQueue
	var err error
	objQ.client, err = srpc.DialHTTP("tcp", objClient.address)
	if err != nil {
		return nil, errors.New(fmt.Sprintf("Error dialing\t%s\n", err.Error()))
	}
	objQ.conn, err = objQ.client.Call("ObjectServer.AddObjects")
	if err != nil {
		objQ.client.Close()
		return nil, err
	}
	objQ.encoder = gob.NewEncoder(objQ.conn)
	getResponseChan := make(chan bool, 65536)
	errorChan := make(chan error, 1024)
	objQ.getResponseChan = getResponseChan
	objQ.errorChan = errorChan
	objQ.sendSemaphore = make(chan bool, 1)
	go readResponses(objQ.conn, getResponseChan, errorChan)
	return &objQ, nil
}
コード例 #17
0
ファイル: manager.go プロジェクト: keep94/Dominator
func manageSource(sourceName string, sourceReconnectChannel chan<- string,
	clientRequestChannel <-chan *proto.ClientRequest,
	serverMessageChannel chan<- *serverMessageType, logger *log.Logger) {
	closeNotifyChannel := make(chan struct{})
	initialRetryTimeout := time.Millisecond * 100
	retryTimeout := initialRetryTimeout
	reconnect := false
	for ; ; time.Sleep(retryTimeout) {
		if retryTimeout < time.Minute {
			retryTimeout *= 2
		}
		client, err := srpc.DialHTTP("tcp", sourceName, time.Second*15)
		if err != nil {
			logger.Printf("error connecting to: %s: %s\n", sourceName, err)
			continue
		}
		conn, err := client.Call("FileGenerator.Connect")
		if err != nil {
			client.Close()
			logger.Println(err)
			continue
		}
		retryTimeout = initialRetryTimeout
		// The server keeps the same encoder/decoder pair over the lifetime of
		// the connection, so we must do the same.
		go handleServerMessages(sourceName, gob.NewDecoder(conn),
			serverMessageChannel, closeNotifyChannel, logger)
		if reconnect {
			sourceReconnectChannel <- sourceName
		} else {
			reconnect = true
		}
		sendClientRequests(conn, clientRequestChannel, closeNotifyChannel,
			logger)
		conn.Close()
		client.Close()
	}
}
コード例 #18
0
ファイル: impl.go プロジェクト: keep94/Dominator
func (m *Manager) loadImage(imageClient *srpc.Client, name string) (
	*srpc.Client, *image.Image, error) {
	if imageClient == nil {
		var err error
		imageClient, err = srpc.DialHTTP("tcp", m.imageServerAddress, 0)
		if err != nil {
			if !m.loggedDialFailure {
				m.logger.Printf("Error dialing: %s: %s\n",
					m.imageServerAddress, err)
				m.loggedDialFailure = true
			}
			return nil, nil, err
		}
	}
	img, err := client.GetImage(imageClient, name)
	if err != nil {
		m.logger.Printf("Error calling: %s\n", err)
		imageClient.Close()
		return nil, nil, err
	}
	if img == nil || m.scheduleExpiration(img, name) {
		return imageClient, nil, nil
	}
	if err := img.FileSystem.RebuildInodePointers(); err != nil {
		m.logger.Printf("Error building inode pointers for image: %s %s",
			name, err)
		return imageClient, nil, err
	}
	// Build cache data now to avoid potential concurrent builds later.
	img.FileSystem.InodeToFilenamesTable()
	img.FileSystem.FilenameToInodeTable()
	img.FileSystem.HashToInodesTable()
	img.FileSystem.ComputeTotalDataBytes()
	img.FileSystem.BuildEntryMap()
	m.logger.Printf("Got image: %s\n", name)
	return imageClient, img, nil
}
コード例 #19
0
ファイル: watchd.go プロジェクト: keep94/Dominator
func serverWatchDaemon(mdbServerHostname string, mdbServerPortNum uint,
	mdbFileName string, mdbChannel chan<- *mdb.Mdb, logger *log.Logger) {
	var lastMdb *mdb.Mdb
	if file, err := os.Open(mdbFileName); err == nil {
		lastMdb = loadFile(file, mdbFileName, logger)
		file.Close()
		if lastMdb != nil {
			sort.Sort(lastMdb)
			mdbChannel <- lastMdb
		}
	}
	address := fmt.Sprintf("%s:%d", mdbServerHostname, mdbServerPortNum)
	for ; ; time.Sleep(time.Second) {
		client, err := srpc.DialHTTP("tcp", address, time.Second*15)
		if err != nil {
			logger.Println(err)
			continue
		}
		conn, err := client.Call("MdbServer.GetMdbUpdates")
		if err != nil {
			logger.Println(err)
			client.Close()
			continue
		}
		decoder := gob.NewDecoder(conn)
		firstUpdate := true
		for {
			var mdbUpdate mdbserver.MdbUpdate
			if err := decoder.Decode(&mdbUpdate); err != nil {
				logger.Println(err)
				break
			} else {
				if firstUpdate {
					lastMdb = &mdb.Mdb{}
					firstUpdate = false
				}
				lastMdb = processUpdate(lastMdb, mdbUpdate)
				sort.Sort(lastMdb)
				mdbChannel <- lastMdb
				if file, err := os.Create(mdbFileName + "~"); err != nil {
					logger.Println(err)
				} else {
					writer := bufio.NewWriter(file)
					var err error
					if isGob(mdbFileName) {
						encoder := gob.NewEncoder(writer)
						err = encoder.Encode(lastMdb.Machines)
					} else {
						err = jsonwriter.WriteWithIndent(writer, "    ",
							lastMdb.Machines)
					}
					if err != nil {
						logger.Println(err)
						os.Remove(mdbFileName + "~")
					} else {
						writer.Flush()
						file.Close()
						os.Rename(mdbFileName+"~", mdbFileName)
					}
				}
			}
		}
		conn.Close()
		client.Close()
	}
}