Пример #1
0
func verifyMigrationSupportsVersion(fsrbin, v string) error {
	stump.VLog("  - verifying migration supports version %s", v)
	vn, err := strconv.Atoi(v)
	if err != nil {
		return fmt.Errorf("given migration version was not a number: %q", v)
	}

	sn, err := migrationsVersion(fsrbin)
	if err != nil {
		return err
	}

	if sn >= vn {
		return nil
	}

	stump.VLog("  - migrations doesnt support version %s, attempting to update", v)
	_, err = GetMigrations()
	if err != nil {
		return err
	}

	stump.VLog("  - migrations updated")

	sn, err = migrationsVersion(fsrbin)
	if err != nil {
		return err
	}

	if sn >= vn {
		return nil
	}

	return fmt.Errorf("no known migration supports version %s", v)
}
Пример #2
0
func RunMigration(oldv, newv string) error {
	migrateBin := "fs-repo-migrations"
	stump.VLog("  - checking for migrations binary...")
	_, err := exec.LookPath(migrateBin)
	if err != nil {
		stump.VLog("  - migrations not found on system, attempting to install")
		loc, err := GetMigrations()
		if err != nil {
			return err
		}

		migrateBin = loc
	}

	// check to make sure migrations binary supports our target version
	err = verifyMigrationSupportsVersion(migrateBin, newv)
	if err != nil {
		return err
	}

	cmd := exec.Command(migrateBin, "-to", newv, "-y")

	cmd.Stdout = stump.LogOut
	cmd.Stderr = stump.ErrOut

	stump.Log("running migration: '%s -to %s -y'", migrateBin, newv)

	err = cmd.Run()
	if err != nil {
		return fmt.Errorf("migration failed: %s", err)
	}

	stump.Log("migration succeeded!")
	return nil
}
Пример #3
0
func (i *Install) postInstallMigrationCheck() error {
	if util.BeforeVersion("v0.3.10", i.TargetVers) {
		stump.VLog("  - ipfs pre v0.3.10 does not support checking of repo version through the tool")
		stump.VLog("  - if a migration is needed, you will be prompted when starting ipfs")
		return nil
	}

	return CheckMigration()
}
Пример #4
0
func GetCurrentVersion() (string, error) {
	fix := func(s string) string {
		if !strings.HasPrefix(s, "v") {
			s = "v" + s
		}
		return s
	}

	// try checking a locally running daemon first
	apiurl, err := util.ApiEndpoint(util.IpfsDir())
	if err == nil {
		sh := api.NewShell(apiurl)
		v, _, err := sh.Version()
		if err == nil {
			return fix(v), nil
		}
	}

	stump.VLog("daemon check failed: %s", err)

	_, err = exec.LookPath("ipfs")
	if err != nil {
		return "none", nil
	}

	// try running the ipfs binary in the users path
	out, err := exec.Command("ipfs", "version", "-n").CombinedOutput()
	if err != nil {
		return "", fmt.Errorf("version check failed: %s - %s", string(out), err)
	}

	return fix(strings.Trim(string(out), " \n\t")), nil
}
Пример #5
0
func testRefsList(tdir, bin string) error {
	stump.VLog("  - checking that file shows up in ipfs refs local")
	c := exec.Command(bin, "refs", "local")
	c.Env = []string{"IPFS_PATH=" + tdir}
	out, err := c.CombinedOutput()
	if err != nil {
		stump.Error("testfileadd fail: %s", err)
		stump.Error(string(out))
		return err
	}

	hashes := strings.Split(string(out), "\n")
	exp := "QmTFJQ68kaArzsqz2Yjg1yMyEA5TXTfNw6d9wSFhxtBxz2"
	var found bool
	for _, h := range hashes {
		if h == exp {
			found = true
			break
		}
	}
	if !found {
		return fmt.Errorf("expected to see %s in the local refs!", exp)
	}

	return nil
}
Пример #6
0
func testFileAdd(tdir, bin string) error {
	stump.VLog("  - checking that we can add and cat a file")
	text := "hello world! This node should work"
	data := bytes.NewBufferString(text)
	c := exec.Command(bin, "add", "-q", "--progress=false")
	c.Env = []string{"IPFS_PATH=" + tdir}
	c.Stdin = data
	out, err := c.CombinedOutput()
	if err != nil {
		stump.Error("testfileadd fail: %s", err)
		stump.Error(string(out))
		return err
	}

	hash := strings.Trim(string(out), "\n \t\r")
	fiout, err := runCmd(tdir, bin, "cat", hash)
	if err != nil {
		return err
	}

	if fiout != text {
		return fmt.Errorf("add/cat check failed")
	}

	return nil
}
Пример #7
0
func (i *Install) Run() error {
	defer i.RevertOnFailure()

	var err error
	i.CurrentVers, err = GetCurrentVersion()
	if err != nil {
		return err
	}

	if i.CurrentVers == "none" {
		stump.VLog("no pre-existing ipfs installation found")
	} else if i.CurrentVers == i.TargetVers {
		stump.Log("Already have version %s installed, skipping.", i.TargetVers)
		i.Succeeded = true
		return nil
	}

	err = i.DownloadNewBinary()
	if err != nil {
		return err
	}

	if !i.NoCheck {
		stump.Log("binary downloaded, verifying...")
		err = test.TestBinary(i.TmpBinPath, i.TargetVers)
		if err != nil {
			return err
		}
	} else {
		stump.Log("skipping tests since '--no-check' was passed")
	}

	err = i.MaybeStash()
	if err != nil {
		return err
	}

	err = i.SelectGoodInstallLoc()
	if err != nil {
		return err
	}

	stump.Log("installing new binary to %s", i.InstallPath)
	err = InstallBinaryTo(i.TmpBinPath, i.InstallPath)
	if err != nil {
		// in case of error here, replace old binary
		stump.Error("Install failed: ", err)

		return err
	}

	err = i.postInstallMigrationCheck()
	if err != nil {
		stump.Error("Migration Failed: ", err)
		return err
	}

	i.Succeeded = true
	return nil
}
Пример #8
0
func Fetch(ipfspath string) (io.ReadCloser, error) {
	stump.VLog("  - fetching %q", ipfspath)
	ep, err := ApiEndpoint(IpfsDir())
	if err == nil {
		sh := api.NewShell(ep)
		if sh.IsUp() {
			stump.VLog("  - using local ipfs daemon for transfer")
			rc, err := sh.Cat(ipfspath)
			if err != nil {
				return nil, err
			}

			return newLimitReadCloser(rc, fetchSizeLimit), nil
		}
	}

	return httpFetch(GlobalGatewayUrl + ipfspath)
}
Пример #9
0
func getMigrationsGoGet() (string, error) {
	stump.VLog("  - fetching migrations using 'go get'")
	cmd := exec.Command("go", "get", "-u", "github.com/ipfs/fs-repo-migrations")
	out, err := cmd.CombinedOutput()
	if err != nil {
		return "", fmt.Errorf("%s %s", string(out), err)
	}
	stump.VLog("  - success. verifying...")

	// verify we can see the binary now
	p, err := exec.LookPath("fs-repo-migrations")
	if err != nil {
		return "", fmt.Errorf("install succeeded, but failed to find binary afterwards. (%s)", err)
	}
	stump.VLog("  - fs-repo-migrations now installed at %s", p)

	return filepath.Join(os.Getenv("GOPATH"), "bin", migrations), nil
}
Пример #10
0
func CheckMigration() error {
	stump.Log("checking if repo migration is needed...")
	p := util.IpfsDir()

	vfilePath := filepath.Join(p, "version")
	_, err := os.Stat(vfilePath)
	if os.IsNotExist(err) {
		stump.VLog("  - no prexisting repo to migrate")
		return nil
	}

	oldverB, err := ioutil.ReadFile(vfilePath)
	if err != nil {
		return err
	}

	oldver := strings.Trim(string(oldverB), "\n \t")
	stump.VLog("  - old repo version is", oldver)

	nbinver, err := util.RunCmd("", "ipfs", "version", "--repo")
	if err != nil {
		stump.Log("Failed to check new binary repo version.")
		stump.VLog("Reason: ", err)
		stump.Log("This is not an error.")
		stump.Log("This just means that you may have to manually run the migration")
		stump.Log("You will be prompted to do so upon starting the ipfs daemon if necessary")
		return nil
	}

	stump.VLog("  - repo version of new binary is ", nbinver)

	if oldver != nbinver {
		stump.Log("  check complete, migration required.")
		return RunMigration(oldver, nbinver)
	}

	stump.VLog("  check complete, no migration required.")

	return nil
}
Пример #11
0
func GetBinaryForVersion(distname, binnom, root, vers, out string) error {
	stump.Log("fetching %s version %s", distname, vers)
	dir, err := ioutil.TempDir("", "ipfs-update")
	if err != nil {
		return err
	}

	stump.VLog("  - using GOOS=%s and GOARCH=%s", runtime.GOOS, runtime.GOARCH)
	var archive string
	switch runtime.GOOS {
	case "windows":
		archive = "zip"
	default:
		archive = "tar.gz"
	}
	finame := fmt.Sprintf("%s_%s_%s-%s.%s", distname, vers, runtime.GOOS, runtime.GOARCH, archive)

	distpath := fmt.Sprintf("%s/%s/%s/%s", root, distname, vers, finame)

	data, err := util.Fetch(distpath)
	if err != nil {
		return err
	}

	arcpath := filepath.Join(dir, finame)
	fi, err := os.Create(arcpath)
	if err != nil {
		return err
	}

	stump.VLog("  - writing to", arcpath)
	_, err = io.Copy(fi, data)
	if err != nil {
		return err
	}
	fi.Close()

	return unpackArchive(distname, binnom, arcpath, out, archive)
}
Пример #12
0
func runCmd(p, bin string, args ...string) (string, error) {
	cmd := exec.Command(bin, args...)
	cmd.Env = []string{"IPFS_PATH=" + p}
	stump.VLog("  - running: %s", cmd.Args)
	out, err := cmd.CombinedOutput()
	if err != nil {
		return "", fmt.Errorf("%s: %s", err, string(out))
	}

	if out[len(out)-1] == '\n' {
		return string(out[:len(out)-1]), nil
	}
	return string(out), nil
}
Пример #13
0
func waitForApi(ipfspath string) error {
	stump.VLog("  - waiting on daemon to come online")
	var endpoint string
	nloops := 15
	var success bool
	for i := 0; i < nloops; i++ {
		ep, err := util.ApiEndpoint(ipfspath)
		if err == nil {
			stump.VLog("  - found api file")
			endpoint = ep
			success = true
			break
		}
		if !os.IsNotExist(err) {
			return err
		}

		time.Sleep(time.Millisecond * (100 * time.Duration(i+1)))
	}

	if !success {
		stump.VLog("  - no api file found, trying fallback (happens pre 0.3.8)")
		endpoint = "localhost:5001"
	}

	for i := 0; i < 10; i++ {
		_, err := net.Dial("tcp", endpoint)
		if err == nil {
			return nil
		}

		time.Sleep(time.Millisecond * (100 * time.Duration(i+1)))
	}

	return fmt.Errorf("failed to come online")
}
Пример #14
0
func httpFetch(url string) (io.ReadCloser, error) {
	stump.VLog("fetching url: %s", url)
	resp, err := httpGet(url)
	if err != nil {
		return nil, err
	}

	if resp.StatusCode >= 400 {
		stump.Error("fetching resource: %s", resp.Status)
		mes, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			return nil, fmt.Errorf("error reading error body: %s", err)
		}

		return nil, fmt.Errorf("%s: %s", resp.Status, string(mes))
	}

	return newLimitReadCloser(resp.Body, fetchSizeLimit), nil
}
Пример #15
0
func (i *Install) MaybeStash() error {
	if i.CurrentVers != "none" {
		stump.Log("stashing old binary")
		oldpath, err := StashOldBinary(i.CurrentVers, false)
		if err != nil {
			if strings.Contains(err.Error(), "could not find old") {
				stump.Log("stash failed, no binary found.")
				stump.Log(util.BoldText("this could be because you have a daemon running, but no ipfs binary in your path."))
				stump.Log("continuing anyways, but skipping stash")
				return nil
			}
			return err
		}
		i.StashedFromPath = filepath.Dir(oldpath)
	} else {
		stump.VLog("skipping stash, no previous install")
	}

	return nil
}
Пример #16
0
// StashOldBinary moves the existing ipfs binary to a backup directory
// and returns the path to the original location of the old binary
func StashOldBinary(tag string, keep bool) (string, error) {
	loc, err := exec.LookPath("ipfs")
	if err != nil {
		return "", fmt.Errorf("could not find old binary: %s", err)
	}

	ipfsdir := util.IpfsDir()

	olddir := filepath.Join(ipfsdir, "old-bin")
	npath := filepath.Join(olddir, "ipfs-"+tag)
	pathpath := filepath.Join(olddir, "path-old")

	err = os.MkdirAll(olddir, 0700)
	if err != nil {
		return "", fmt.Errorf("could not create dir to backup old binary: %s", err)
	}

	// write the old path of the binary to the backup dir
	err = ioutil.WriteFile(pathpath, []byte(loc), 0644)
	if err != nil {
		return "", fmt.Errorf("couldnt stash path: ", err)
	}

	f := util.Move
	if keep {
		f = util.CopyTo
	}

	stump.VLog("  - moving %s to %s", loc, npath)
	err = f(loc, npath)
	if err != nil {
		return "", fmt.Errorf("could not move old binary: %s", err)
	}

	return loc, nil
}
Пример #17
0
	},
	Action: func(c *cli.Context) error {
		vers := c.Args().First()
		if vers == "" {
			stump.Fatal("please specify a version to install")
		}
		if vers == "latest" {
			latest, err := GetLatestVersion(util.IpfsVersionPath, "go-ipfs")
			if err != nil {
				stump.Fatal("error resolving 'latest': ", err)
			}
			vers = latest
		}

		if !strings.HasPrefix(vers, "v") && looksLikeSemver(vers) {
			stump.VLog("Version strings must start with 'v'. Autocorrecting...")
			vers = "v" + vers
		}

		i, err := NewInstall(util.IpfsVersionPath, vers, c.Bool("no-check"))
		if err != nil {
			return err
		}

		err = i.Run()
		if err != nil {
			return err
		}
		stump.Log("\nInstallation complete!")

		if util.HasDaemonRunning() {
Пример #18
0
func TestBinary(bin, version string) error {
	_, err := os.Stat(bin)
	if err != nil {
		return err
	}

	// make sure binary is executable
	err = os.Chmod(bin, 0755)
	if err != nil {
		return err
	}

	staging := filepath.Join(util.IpfsDir(), "update-staging")
	err = os.MkdirAll(staging, 0755)
	if err != nil {
		return fmt.Errorf("error creating test staging directory: %s", err)
	}

	tdir, err := ioutil.TempDir(staging, "test")
	if err != nil {
		return err
	}

	err = os.MkdirAll(tdir, 0755)
	if err != nil {
		return fmt.Errorf("error creating test staging directory: %s", err)
	}

	defer func(dir string) {
		// defer cleanup, bound param to avoid mistakes
		err = os.RemoveAll(dir)
		if err != nil {
			stump.Error("error cleaning up staging directory: ", err)
		}
	}(tdir)

	stump.VLog("  - running init in '%s' with new binary", tdir)
	_, err = runCmd(tdir, bin, "init")
	if err != nil {
		return fmt.Errorf("error initializing with new binary: %s", err)
	}

	stump.VLog("  - checking new binary outputs correct version")
	rversion, err := runCmd(tdir, bin, "version")
	if err != nil {
		return err
	}

	parts := strings.Fields(rversion)
	if !versionMatch(parts[len(parts)-1], version[1:]) {
		return fmt.Errorf("version didnt match")
	}

	if util.BeforeVersion("v0.3.8", version) {
		stump.Log("== skipping tests with daemon, versions before 0.3.8 do not support port zero ==")
		return nil
	}

	// set up ports in config so we dont interfere with an already running daemon
	stump.VLog("  - tweaking test config to avoid external interference")
	err = tweakConfig(tdir)
	if err != nil {
		return err
	}

	stump.VLog("  - starting up daemon")
	daemon, err := StartDaemon(tdir, bin)
	if err != nil {
		return fmt.Errorf("error starting daemon: %s", err)
	}
	defer func() {
		stump.VLog("  - killing test daemon")
		err := daemon.Close()
		if err != nil {
			stump.VLog("  - error killing test daemon: %s (continuing anyway)", err)
		}
		stump.Log("success!")
	}()

	// test some basic things against the daemon
	err = testFileAdd(tdir, bin)
	if err != nil {
		return fmt.Errorf("test file add: %s", err)
	}

	err = testRefsList(tdir, bin)
	if err != nil {
		return fmt.Errorf("test refs list: %s", err)
	}

	return nil
}