<commit_before>// Copyright 2011 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// +build !appengine

package main

import (
	"flag"
	"fmt"
	"go/build"
	"io"
	"log"
	"net"
	"net/http"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"strings"
	"time"

	"code.google.com/p/go.tools/playground/socket"

	// Imports so that go build/install automatically installs them.
	_ "code.google.com/p/go-tour/pic"
	_ "code.google.com/p/go-tour/tree"
	_ "code.google.com/p/go-tour/wc"
)

const (
	basePkg    = "code.google.com/p/go-tour/"
	socketPath = "/socket"
)

var (
	httpListen  = flag.String("http", "127.0.0.1:3999", "host:port to listen on")
	openBrowser = flag.Bool("openbrowser", true, "open browser automatically")
)

var (
	// GOPATH containing the tour packages
	gopath = os.Getenv("GOPATH")

	httpAddr string
)

// isRoot reports whether path is the root directory of the tour tree.
// To be the root, it must have content and template subdirectories.
func isRoot(path string) bool {
	_, err := os.Stat(filepath.Join(path, "content", "welcome.article"))
	if err == nil {
		_, err = os.Stat(filepath.Join(path, "template", "index.tmpl"))
	}
	return err == nil
}

func findRoot() (string, error) {
	ctx := build.Default
	p, err := ctx.Import(basePkg, "", build.FindOnly)
	if err == nil && isRoot(p.Dir) {
		return p.Dir, nil
	}
	tourRoot := filepath.Join(runtime.GOROOT(), "misc", "tour")
	ctx.GOPATH = tourRoot
	p, err = ctx.Import(basePkg, "", build.FindOnly)
	if err == nil && isRoot(tourRoot) {
		gopath = tourRoot
		return tourRoot, nil
	}
	return "", fmt.Errorf("could not find go-tour content; check $GOROOT and $GOPATH")
}

func main() {
	flag.Parse()

	// find and serve the go tour files
	root, err := findRoot()
	if err != nil {
		log.Fatalf("Couldn't find tour files: %v", err)
	}

	log.Println("Serving content from", root)

	host, port, err := net.SplitHostPort(*httpListen)
	if err != nil {
		log.Fatal(err)
	}
	if host == "" {
		host = "localhost"
	}
	if host != "127.0.0.1" && host != "localhost" {
		log.Print(localhostWarning)
	}
	httpAddr = host + ":" + port

	if err := initTour(root, "SocketTransport"); err != nil {
		log.Fatal(err)
	}

	http.HandleFunc("/", rootHandler)
	http.HandleFunc("/lesson/", lessonHandler)
	http.Handle(socketPath, socket.Handler)

	// Keep these static file handlers in sync with ../app.yaml.
	static := http.FileServer(http.Dir(root))
	http.Handle("/content/img/", static)
	http.Handle("/static/", static)
	imgDir := filepath.Join(root, "static", "img")
	http.Handle("/favicon.ico", http.FileServer(http.Dir(imgDir)))

	go func() {
		url := "http://" + httpAddr
		if waitServer(url) && *openBrowser && startBrowser(url) {
			log.Printf("A browser window should open. If not, please visit %s", url)
		} else {
			log.Printf("Please open your web browser and visit %s", url)
		}
	}()
	log.Fatal(http.ListenAndServe(httpAddr, nil))
}

// rootHandler returns a handler for all the requests except the ones for lessons.
func rootHandler(w http.ResponseWriter, r *http.Request) {
	if err := renderUI(w); err != nil {
		log.Println(err)
	}
}

// lessonHandler handler the HTTP requests for lessons.
func lessonHandler(w http.ResponseWriter, r *http.Request) {
	lesson := strings.TrimPrefix(r.URL.Path, "/lesson/")
	if err := writeLesson(lesson, w); err != nil {
		if err == lessonNotFound {
			http.NotFound(w, r)
		} else {
			log.Println(err)
		}
	}
}

const localhostWarning = `
WARNING!  WARNING!  WARNING!

I appear to be listening on an address that is not localhost.
Anyone with access to this address and port will have access
to this machine as the user running gotour.

If you don't understand this message, hit Control-C to terminate this process.

WARNING!  WARNING!  WARNING!
`

type response struct {
	Output string `json:"output"`
	Errors string `json:"compile_errors"`
}

func init() {
	socket.Environ = environ
}

// environ returns the original execution environment with GOPATH
// replaced (or added) with the value of the global var gopath.
func environ() (env []string) {
	for _, v := range os.Environ() {
		if !strings.HasPrefix(v, "GOPATH=") {
			env = append(env, v)
		}
	}
	env = append(env, "GOPATH="+gopath)
	return
}

// waitServer waits some time for the http Server to start
// serving url. The return value reports whether it starts.
func waitServer(url string) bool {
	tries := 20
	for tries > 0 {
		resp, err := http.Get(url)
		if err == nil {
			resp.Body.Close()
			return true
		}
		time.Sleep(100 * time.Millisecond)
		tries--
	}
	return false
}

// startBrowser tries to open the URL in a browser, and returns
// whether it succeed.
func startBrowser(url string) bool {
	// try to start the browser
	var args []string
	switch runtime.GOOS {
	case "darwin":
		args = []string{"open"}
	case "windows":
		args = []string{"cmd", "/c", "start"}
	default:
		args = []string{"xdg-open"}
	}
	cmd := exec.Command(args[0], append(args[1:], url)...)
	return cmd.Start() == nil
}

// prepContent for the local tour simply returns the content as-is.
func prepContent(r io.Reader) io.Reader { return r }

// socketAddr returns the WebSocket handler address.
func socketAddr() string { return "ws://" + httpAddr + socketPath }
<commit_msg>go-tour: use new socket interface<commit_after>// Copyright 2011 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// +build !appengine

package main

import (
	"flag"
	"fmt"
	"go/build"
	"io"
	"log"
	"net"
	"net/http"
	"net/url"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"strings"
	"time"

	"code.google.com/p/go.tools/playground/socket"

	// Imports so that go build/install automatically installs them.
	_ "code.google.com/p/go-tour/pic"
	_ "code.google.com/p/go-tour/tree"
	_ "code.google.com/p/go-tour/wc"
)

const (
	basePkg    = "code.google.com/p/go-tour/"
	socketPath = "/socket"
)

var (
	httpListen  = flag.String("http", "127.0.0.1:3999", "host:port to listen on")
	openBrowser = flag.Bool("openbrowser", true, "open browser automatically")
)

var (
	// GOPATH containing the tour packages
	gopath = os.Getenv("GOPATH")

	httpAddr string
)

// isRoot reports whether path is the root directory of the tour tree.
// To be the root, it must have content and template subdirectories.
func isRoot(path string) bool {
	_, err := os.Stat(filepath.Join(path, "content", "welcome.article"))
	if err == nil {
		_, err = os.Stat(filepath.Join(path, "template", "index.tmpl"))
	}
	return err == nil
}

func findRoot() (string, error) {
	ctx := build.Default
	p, err := ctx.Import(basePkg, "", build.FindOnly)
	if err == nil && isRoot(p.Dir) {
		return p.Dir, nil
	}
	tourRoot := filepath.Join(runtime.GOROOT(), "misc", "tour")
	ctx.GOPATH = tourRoot
	p, err = ctx.Import(basePkg, "", build.FindOnly)
	if err == nil && isRoot(tourRoot) {
		gopath = tourRoot
		return tourRoot, nil
	}
	return "", fmt.Errorf("could not find go-tour content; check $GOROOT and $GOPATH")
}

func main() {
	flag.Parse()

	// find and serve the go tour files
	root, err := findRoot()
	if err != nil {
		log.Fatalf("Couldn't find tour files: %v", err)
	}

	log.Println("Serving content from", root)

	host, port, err := net.SplitHostPort(*httpListen)
	if err != nil {
		log.Fatal(err)
	}
	if host == "" {
		host = "localhost"
	}
	if host != "127.0.0.1" && host != "localhost" {
		log.Print(localhostWarning)
	}
	httpAddr = host + ":" + port

	if err := initTour(root, "SocketTransport"); err != nil {
		log.Fatal(err)
	}

	http.HandleFunc("/", rootHandler)
	http.HandleFunc("/lesson/", lessonHandler)

	origin := &url.URL{Scheme: "http", Host: host + ":" + port}
	http.Handle(socketPath, socket.NewHandler(origin))

	// Keep these static file handlers in sync with ../app.yaml.
	static := http.FileServer(http.Dir(root))
	http.Handle("/content/img/", static)
	http.Handle("/static/", static)
	imgDir := filepath.Join(root, "static", "img")
	http.Handle("/favicon.ico", http.FileServer(http.Dir(imgDir)))

	go func() {
		url := "http://" + httpAddr
		if waitServer(url) && *openBrowser && startBrowser(url) {
			log.Printf("A browser window should open. If not, please visit %s", url)
		} else {
			log.Printf("Please open your web browser and visit %s", url)
		}
	}()
	log.Fatal(http.ListenAndServe(httpAddr, nil))
}

// rootHandler returns a handler for all the requests except the ones for lessons.
func rootHandler(w http.ResponseWriter, r *http.Request) {
	if err := renderUI(w); err != nil {
		log.Println(err)
	}
}

// lessonHandler handler the HTTP requests for lessons.
func lessonHandler(w http.ResponseWriter, r *http.Request) {
	lesson := strings.TrimPrefix(r.URL.Path, "/lesson/")
	if err := writeLesson(lesson, w); err != nil {
		if err == lessonNotFound {
			http.NotFound(w, r)
		} else {
			log.Println(err)
		}
	}
}

const localhostWarning = `
WARNING!  WARNING!  WARNING!

I appear to be listening on an address that is not localhost.
Anyone with access to this address and port will have access
to this machine as the user running gotour.

If you don't understand this message, hit Control-C to terminate this process.

WARNING!  WARNING!  WARNING!
`

type response struct {
	Output string `json:"output"`
	Errors string `json:"compile_errors"`
}

func init() {
	socket.Environ = environ
}

// environ returns the original execution environment with GOPATH
// replaced (or added) with the value of the global var gopath.
func environ() (env []string) {
	for _, v := range os.Environ() {
		if !strings.HasPrefix(v, "GOPATH=") {
			env = append(env, v)
		}
	}
	env = append(env, "GOPATH="+gopath)
	return
}

// waitServer waits some time for the http Server to start
// serving url. The return value reports whether it starts.
func waitServer(url string) bool {
	tries := 20
	for tries > 0 {
		resp, err := http.Get(url)
		if err == nil {
			resp.Body.Close()
			return true
		}
		time.Sleep(100 * time.Millisecond)
		tries--
	}
	return false
}

// startBrowser tries to open the URL in a browser, and returns
// whether it succeed.
func startBrowser(url string) bool {
	// try to start the browser
	var args []string
	switch runtime.GOOS {
	case "darwin":
		args = []string{"open"}
	case "windows":
		args = []string{"cmd", "/c", "start"}
	default:
		args = []string{"xdg-open"}
	}
	cmd := exec.Command(args[0], append(args[1:], url)...)
	return cmd.Start() == nil
}

// prepContent for the local tour simply returns the content as-is.
func prepContent(r io.Reader) io.Reader { return r }

// socketAddr returns the WebSocket handler address.
func socketAddr() string { return "ws://" + httpAddr + socketPath }
<|endoftext|>


<commit_before>//
// Copyright (c) 2016 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

package main

import (
	"fmt"

	"github.com/mitchellh/mapstructure"
	"github.com/rackspace/gophercloud"
	"github.com/rackspace/gophercloud/openstack"
	"github.com/rackspace/gophercloud/openstack/identity/v3/tokens"
)

// Project represents a tenant UUID and friendly name.
type Project struct {
	ID   string `mapstructure:"id"`
	Name string `mapstructure:"name"`
}

type getResult struct {
	tokens.GetResult
}

// Domain is a collection of users, groups and projects.
// Here we only need to fetch a domain UUID and friendly name.
type Domain struct {
	ID   string `mapstructure:"id"`
	Name string `mapstructure:"name"`
}

// User represents an Openstack identity (e.g. Keystone) user.
// We fetch the user UUID, friendly name and the domain it belongs
// to.
type User struct {
	ValidDomain Domain `mapstructure:"domain"`
	ID          string `mapstructure:"id"`
	Name        string `mapstructure:"name"`
}

// UserProjects represents the list of projects a user has access to.
type UserProjects struct {
	Projects []struct {
		Description string `json:"description"`
		DomainID    string `json:"domain_id"`
		Enabled     bool   `json:"enabled"`
		ID          string `json:"id"`
		ParentID    string `json:"parent_id"`
		Links       struct {
			Self string `json:"self"`
		} `json:"links"`
		Name string `json:"name"`
	} `json:"projects"`

	Links struct {
		Self     string      `json:"self"`
		Previous interface{} `json:"previous"`
		Next     interface{} `json:"next"`
	} `json:"links"`
}

func (r getResult) extractUserID() (string, error) {
	if r.Err != nil {
		return "", r.Err
	}

	var response struct {
		Token struct {
			ValidUser User `mapstructure:"user"`
		} `mapstructure:"token"`
	}

	err := mapstructure.Decode(r.Body, &response)
	if err != nil {
		return "", err
	}

	return response.Token.ValidUser.ID, nil
}

func (r getResult) extractProject() (string, error) {
	if r.Err != nil {
		return "", r.Err
	}

	var response struct {
		Token struct {
			ValidProject Project `mapstructure:"project"`
		} `mapstructure:"token"`
	}

	err := mapstructure.Decode(r.Body, &response)
	if err != nil {
		return "", err
	}

	return response.Token.ValidProject.ID, nil
}

func getScopedToken(username string, password string, projectScope string) (string, string, string, error) {
	var scope *tokens.Scope

	opt := gophercloud.AuthOptions{
		IdentityEndpoint: *identityURL + "/v3/",
		Username:         username,
		Password:         password,
		DomainID:         "default",
		AllowReauth:      true,
	}

	provider, err := openstack.AuthenticatedClient(opt)
	if err != nil {
		errorf("Could not get AuthenticatedClient %s\n", err)
		return "", "", "", nil
	}

	client := openstack.NewIdentityV3(provider)
	if client == nil {
		errorf("something went wrong")
		return "", "", "", nil
	}

	scope = nil
	if projectScope != "" {
		scope = &tokens.Scope{
			ProjectName: projectScope,
			DomainName:  "default",
		}
	}

	token, err := tokens.Create(client, opt, scope).Extract()
	if err != nil {
		errorf("Could not extract token %s\n", err)
		return "", "", "", nil
	}

	r := tokens.Get(client, token.ID)
	result := getResult{r}
	tenantID, err := result.extractProject()
	if err != nil {
		errorf("Could not extract tenant ID %s\n", err)
		return "", "", "", nil
	}

	userID, err := result.extractUserID()
	if err != nil {
		errorf("Could not extract user ID %s\n", err)
		return "", "", "", nil
	}

	infof("Got token %s for tenant %s, user %s (%s, %s, %s)\n", token.ID, tenantID, userID, username, password, projectScope)

	return token.ID, tenantID, userID, nil
}

func getUnscopedToken(username string, password string) (string, string, string, error) {
	return getScopedToken(username, password, "")
}

func getUserProjects(username string, password string) ([]Project, error) {
	var projects UserProjects
	var userProjects []Project

	token, _, user, err := getUnscopedToken(username, password)
	if err != nil {
		return nil, err
	}

	identity := fmt.Sprintf("%s/v3/users/%s/projects", *identityURL, user)

	resp, err := sendHTTPRequestToken("GET", identity, nil, token, nil)
	if err != nil {
		return nil, err
	}

	err = unmarshalHTTPResponse(resp, &projects)
	if err != nil {
		return nil, err
	}

	for _, project := range projects.Projects {
		newProject := Project{
			ID:   project.ID,
			Name: project.Name,
		}
		userProjects = append(userProjects, newProject)
	}

	return userProjects, nil
}

// IdentityProjects represents the list of all existing projects.
type IdentityProjects struct {
	Links struct {
		Next     interface{} `json:"next"`
		Previous interface{} `json:"previous"`
		Self     string      `json:"self"`
	} `json:"links"`

	Projects []struct {
		Description interface{} `json:"description"`
		DomainID    string      `json:"domain_id"`
		Enabled     bool        `json:"enabled"`
		ID          string      `json:"id"`
		Links       struct {
			Self string `json:"self"`
		} `json:"links"`
		Name     string      `json:"name"`
		ParentID interface{} `json:"parent_id"`
	} `json:"projects"`
}

func getAllProjects(username string, password string) (*IdentityProjects, error) {
	var projects IdentityProjects

	token, _, _, err := getUnscopedToken(username, password)
	if err != nil {
		return nil, err
	}

	identity := fmt.Sprintf("%s/v3/projects", *identityURL)

	resp, err := sendHTTPRequestToken("GET", identity, nil, token, nil)
	if err != nil {
		return nil, err
	}

	err = unmarshalHTTPResponse(resp, &projects)
	if err != nil {
		return nil, err
	}

	return &projects, nil
}

func getTenant(username string, password string, tenantID string) (string, string, error) {
	projects, err := getUserProjects(username, password)
	if err != nil {
		return "", "", err
	}

	if len(projects) == 0 {
		return "", tenantID, fmt.Errorf("No tenant name for %s", username)
	}

	if len(projects) > 1 {
		if tenantID == "" {
			fmt.Printf("Available projects for %s:\n", *identityUser)
			for i, p := range projects {
				fmt.Printf("\t Project[%d]: %s (%s)\n", i+1, p.Name, p.ID)
			}
			return "", "", fmt.Errorf("Please specify a project to use with -tenant-name or -tenant-id")
		}

		for _, p := range projects {
			if p.ID != tenantID {
				continue
			}
			return p.Name, tenantID, nil
		}
		return "", tenantID, fmt.Errorf("No tenant name for %s", tenantID)
	}

	if tenantID != "" && projects[0].ID != tenantID {
		return "", tenantID, fmt.Errorf("No tenant name for %s", tenantID)
	}

	tenantName := projects[0].Name
	if tenantID == "" {
		tenantID = projects[0].ID
	}

	return tenantName, tenantID, nil
}
<commit_msg>ciao-cli: code refactory of getTenant function<commit_after>//
// Copyright (c) 2016 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

package main

import (
	"fmt"

	"github.com/mitchellh/mapstructure"
	"github.com/rackspace/gophercloud"
	"github.com/rackspace/gophercloud/openstack"
	"github.com/rackspace/gophercloud/openstack/identity/v3/tokens"
)

// Project represents a tenant UUID and friendly name.
type Project struct {
	ID   string `mapstructure:"id"`
	Name string `mapstructure:"name"`
}

type getResult struct {
	tokens.GetResult
}

// Domain is a collection of users, groups and projects.
// Here we only need to fetch a domain UUID and friendly name.
type Domain struct {
	ID   string `mapstructure:"id"`
	Name string `mapstructure:"name"`
}

// User represents an Openstack identity (e.g. Keystone) user.
// We fetch the user UUID, friendly name and the domain it belongs
// to.
type User struct {
	ValidDomain Domain `mapstructure:"domain"`
	ID          string `mapstructure:"id"`
	Name        string `mapstructure:"name"`
}

// UserProjects represents the list of projects a user has access to.
type UserProjects struct {
	Projects []struct {
		Description string `json:"description"`
		DomainID    string `json:"domain_id"`
		Enabled     bool   `json:"enabled"`
		ID          string `json:"id"`
		ParentID    string `json:"parent_id"`
		Links       struct {
			Self string `json:"self"`
		} `json:"links"`
		Name string `json:"name"`
	} `json:"projects"`

	Links struct {
		Self     string      `json:"self"`
		Previous interface{} `json:"previous"`
		Next     interface{} `json:"next"`
	} `json:"links"`
}

func (r getResult) extractUserID() (string, error) {
	if r.Err != nil {
		return "", r.Err
	}

	var response struct {
		Token struct {
			ValidUser User `mapstructure:"user"`
		} `mapstructure:"token"`
	}

	err := mapstructure.Decode(r.Body, &response)
	if err != nil {
		return "", err
	}

	return response.Token.ValidUser.ID, nil
}

func (r getResult) extractProject() (string, error) {
	if r.Err != nil {
		return "", r.Err
	}

	var response struct {
		Token struct {
			ValidProject Project `mapstructure:"project"`
		} `mapstructure:"token"`
	}

	err := mapstructure.Decode(r.Body, &response)
	if err != nil {
		return "", err
	}

	return response.Token.ValidProject.ID, nil
}

func getScopedToken(username string, password string, projectScope string) (string, string, string, error) {
	var scope *tokens.Scope

	opt := gophercloud.AuthOptions{
		IdentityEndpoint: *identityURL + "/v3/",
		Username:         username,
		Password:         password,
		DomainID:         "default",
		AllowReauth:      true,
	}

	provider, err := openstack.AuthenticatedClient(opt)
	if err != nil {
		errorf("Could not get AuthenticatedClient %s\n", err)
		return "", "", "", nil
	}

	client := openstack.NewIdentityV3(provider)
	if client == nil {
		errorf("something went wrong")
		return "", "", "", nil
	}

	scope = nil
	if projectScope != "" {
		scope = &tokens.Scope{
			ProjectName: projectScope,
			DomainName:  "default",
		}
	}

	token, err := tokens.Create(client, opt, scope).Extract()
	if err != nil {
		errorf("Could not extract token %s\n", err)
		return "", "", "", nil
	}

	r := tokens.Get(client, token.ID)
	result := getResult{r}
	tenantID, err := result.extractProject()
	if err != nil {
		errorf("Could not extract tenant ID %s\n", err)
		return "", "", "", nil
	}

	userID, err := result.extractUserID()
	if err != nil {
		errorf("Could not extract user ID %s\n", err)
		return "", "", "", nil
	}

	infof("Got token %s for tenant %s, user %s (%s, %s, %s)\n", token.ID, tenantID, userID, username, password, projectScope)

	return token.ID, tenantID, userID, nil
}

func getUnscopedToken(username string, password string) (string, string, string, error) {
	return getScopedToken(username, password, "")
}

func getUserProjects(username string, password string) ([]Project, error) {
	var projects UserProjects
	var userProjects []Project

	token, _, user, err := getUnscopedToken(username, password)
	if err != nil {
		return nil, err
	}

	identity := fmt.Sprintf("%s/v3/users/%s/projects", *identityURL, user)

	resp, err := sendHTTPRequestToken("GET", identity, nil, token, nil)
	if err != nil {
		return nil, err
	}

	err = unmarshalHTTPResponse(resp, &projects)
	if err != nil {
		return nil, err
	}

	for _, project := range projects.Projects {
		newProject := Project{
			ID:   project.ID,
			Name: project.Name,
		}
		userProjects = append(userProjects, newProject)
	}

	return userProjects, nil
}

// IdentityProjects represents the list of all existing projects.
type IdentityProjects struct {
	Links struct {
		Next     interface{} `json:"next"`
		Previous interface{} `json:"previous"`
		Self     string      `json:"self"`
	} `json:"links"`

	Projects []struct {
		Description interface{} `json:"description"`
		DomainID    string      `json:"domain_id"`
		Enabled     bool        `json:"enabled"`
		ID          string      `json:"id"`
		Links       struct {
			Self string `json:"self"`
		} `json:"links"`
		Name     string      `json:"name"`
		ParentID interface{} `json:"parent_id"`
	} `json:"projects"`
}

func getAllProjects(username string, password string) (*IdentityProjects, error) {
	var projects IdentityProjects

	token, _, _, err := getUnscopedToken(username, password)
	if err != nil {
		return nil, err
	}

	identity := fmt.Sprintf("%s/v3/projects", *identityURL)

	resp, err := sendHTTPRequestToken("GET", identity, nil, token, nil)
	if err != nil {
		return nil, err
	}

	err = unmarshalHTTPResponse(resp, &projects)
	if err != nil {
		return nil, err
	}

	return &projects, nil
}

func getTenant(username string, password string, tenantID string) (string, string, error) {
	projects, err := getUserProjects(username, password)
	if err != nil {
		return "", "", err
	}

	if len(projects) <= 0 {
		return "", tenantID, fmt.Errorf("No tenant name for %s", username)
	}

	if tenantID == "" {
		if len(projects) == 1 {
			tenantName := projects[0].Name
			tenantID = projects[0].ID
			return tenantName, tenantID, nil
		}
		fmt.Printf("Available projects for %s:\n", *identityUser)
		for i, p := range projects {
			fmt.Printf("\t Project[%d]: %s (%s)\n", i+1, p.Name, p.ID)
		}
		return "", "", fmt.Errorf("Please specify a project to use with -tenant-name or -tenant-id")
	}

	for _, p := range projects {
		if p.ID == tenantID {
			return p.Name, tenantID, nil
		}
	}
	return "", tenantID, fmt.Errorf("No tenant name for %s", tenantID)
}
<|endoftext|>


<commit_before>// Copyright (c) 2016 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package storage

import (
	"bufio"
	"bytes"
	"encoding/json"
	"fmt"
	"os/exec"
	"strconv"

	"github.com/01org/ciao/ssntp/uuid"
)

// CephDriver maintains context for the ceph driver interface.
type CephDriver struct {
	// SecretPath is the full path to the cephx keyring file.
	SecretPath string

	// ID is the cephx user ID to use
	ID string
}

// CreateBlockDevice will create a rbd image in the ceph cluster.
func (d CephDriver) CreateBlockDevice(imagePath *string, size int) (BlockDevice, error) {
	// generate a UUID to use for this image.
	ID := uuid.Generate().String()

	var cmd *exec.Cmd

	// imageFeatures holds the image features to use when creating a ceph rbd image format 2
	// Currently the kernel rdb client only supports layering but in the future more feaures
	// should be added as they are enabled in the kernel.
	imageFeatures := "--image-feature layering"

	if imagePath != nil {
		cmd = exec.Command("rbd", "--keyring", d.SecretPath, "--id", d.ID, imageFeatures, "import", *imagePath, ID)
	} else {
		// create an empty volume
		cmd = exec.Command("rbd", "--keyring", d.SecretPath, "--id", d.ID, imageFeatures, "create", "--size", strconv.Itoa(size), ID)
	}

	err := cmd.Run()
	if err != nil {
		return BlockDevice{}, err
	}

	return BlockDevice{ID: ID}, nil
}

// DeleteBlockDevice will remove a rbd image from the ceph cluster.
func (d CephDriver) DeleteBlockDevice(volumeUUID string) error {
	cmd := exec.Command("rbd", "--keyring", d.SecretPath, "--id", d.ID, "rm", volumeUUID)
	return cmd.Run()
}

func (d CephDriver) getCredentials() []string {
	args := make([]string, 0, 8)
	if d.SecretPath != "" {
		args = append(args, "--keyring", d.SecretPath)
	}

	if d.ID != "" {
		args = append(args, "--id", d.ID)
	}
	return args
}

// MapVolumeToNode maps a ceph volume to a rbd device on a node.  The
// path to the new device is returned if the mapping succeeds.
func (d CephDriver) MapVolumeToNode(volumeUUID string) (string, error) {
	args := append(d.getCredentials(), "map", volumeUUID)
	cmd := exec.Command("rbd", args...)
	data, err := cmd.Output()
	if err != nil {
		return "", err
	}
	scanner := bufio.NewScanner(bytes.NewBuffer(data))
	if !scanner.Scan() {
		return "", fmt.Errorf("Unable to determine device name for %s", volumeUUID)
	}
	return scanner.Text(), nil
}

// UnmapVolumeFromNode unmaps a ceph volume from a local device on a node.
func (d CephDriver) UnmapVolumeFromNode(volumeUUID string) error {
	args := append(d.getCredentials(), "unmap", volumeUUID)
	return exec.Command("rbd", args...).Run()
}

// GetVolumeMapping returns a map of volumeUUID to mapped devices.
func (d CephDriver) GetVolumeMapping() (map[string][]string, error) {
	args := append(d.getCredentials(), "showmapped", "--format", "json")
	cmd := exec.Command("rbd", args...)
	data, err := cmd.Output()
	if err != nil {
		return nil, err
	}

	vmap := map[string]struct {
		Name   string `json:"name"`
		Device string `json:"device"`
	}{}
	err = json.Unmarshal([]byte(data), &vmap)
	if err != nil {
		return nil, fmt.Errorf("Unable to parse output from rbd show mapped: %v", err)
	}

	volumeDevMap := make(map[string][]string)

	for _, v := range vmap {
		volumeDevMap[v.Name] = append(volumeDevMap[v.Name], v.Device)
	}

	return volumeDevMap, nil
}
<commit_msg>ciao-storage: Specify size unit is GB<commit_after>// Copyright (c) 2016 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package storage

import (
	"bufio"
	"bytes"
	"encoding/json"
	"fmt"
	"os/exec"
	"strconv"

	"github.com/01org/ciao/ssntp/uuid"
)

// CephDriver maintains context for the ceph driver interface.
type CephDriver struct {
	// SecretPath is the full path to the cephx keyring file.
	SecretPath string

	// ID is the cephx user ID to use
	ID string
}

// CreateBlockDevice will create a rbd image in the ceph cluster.
func (d CephDriver) CreateBlockDevice(imagePath *string, size int) (BlockDevice, error) {
	// generate a UUID to use for this image.
	ID := uuid.Generate().String()

	var cmd *exec.Cmd

	// imageFeatures holds the image features to use when creating a ceph rbd image format 2
	// Currently the kernel rdb client only supports layering but in the future more feaures
	// should be added as they are enabled in the kernel.
	imageFeatures := "--image-feature layering"

	if imagePath != nil {
		cmd = exec.Command("rbd", "--keyring", d.SecretPath, "--id", d.ID, imageFeatures, "import", *imagePath, ID)
	} else {
		// create an empty volume
		cmd = exec.Command("rbd", "--keyring", d.SecretPath, "--id", d.ID, imageFeatures, "create", "--size", strconv.Itoa(size)+"G", ID)
	}

	err := cmd.Run()
	if err != nil {
		return BlockDevice{}, err
	}

	return BlockDevice{ID: ID}, nil
}

// DeleteBlockDevice will remove a rbd image from the ceph cluster.
func (d CephDriver) DeleteBlockDevice(volumeUUID string) error {
	cmd := exec.Command("rbd", "--keyring", d.SecretPath, "--id", d.ID, "rm", volumeUUID)
	return cmd.Run()
}

func (d CephDriver) getCredentials() []string {
	args := make([]string, 0, 8)
	if d.SecretPath != "" {
		args = append(args, "--keyring", d.SecretPath)
	}

	if d.ID != "" {
		args = append(args, "--id", d.ID)
	}
	return args
}

// MapVolumeToNode maps a ceph volume to a rbd device on a node.  The
// path to the new device is returned if the mapping succeeds.
func (d CephDriver) MapVolumeToNode(volumeUUID string) (string, error) {
	args := append(d.getCredentials(), "map", volumeUUID)
	cmd := exec.Command("rbd", args...)
	data, err := cmd.Output()
	if err != nil {
		return "", err
	}
	scanner := bufio.NewScanner(bytes.NewBuffer(data))
	if !scanner.Scan() {
		return "", fmt.Errorf("Unable to determine device name for %s", volumeUUID)
	}
	return scanner.Text(), nil
}

// UnmapVolumeFromNode unmaps a ceph volume from a local device on a node.
func (d CephDriver) UnmapVolumeFromNode(volumeUUID string) error {
	args := append(d.getCredentials(), "unmap", volumeUUID)
	return exec.Command("rbd", args...).Run()
}

// GetVolumeMapping returns a map of volumeUUID to mapped devices.
func (d CephDriver) GetVolumeMapping() (map[string][]string, error) {
	args := append(d.getCredentials(), "showmapped", "--format", "json")
	cmd := exec.Command("rbd", args...)
	data, err := cmd.Output()
	if err != nil {
		return nil, err
	}

	vmap := map[string]struct {
		Name   string `json:"name"`
		Device string `json:"device"`
	}{}
	err = json.Unmarshal([]byte(data), &vmap)
	if err != nil {
		return nil, fmt.Errorf("Unable to parse output from rbd show mapped: %v", err)
	}

	volumeDevMap := make(map[string][]string)

	for _, v := range vmap {
		volumeDevMap[v.Name] = append(volumeDevMap[v.Name], v.Device)
	}

	return volumeDevMap, nil
}
<|endoftext|>


<commit_before>package geo

import (
	"math"
)

// Represents a Physical Point in geographic notation [lat, lng]
// @field [float64] lat. The geographic latitude representation of this point.
// @field [float64] lng. The geographic longitude representation of this point.
type Point struct {
	lat float64
	lng float64
}

// Original Implementation from: http://www.movable-type.co.uk/scripts/latlong.html
// @param [float64] dist.  The arc distance in which to transpose the origin point (in meters).
// @param [float64] bearing.  The compass bearing in which to transpose the origin point (in degrees).
// @return [*Point].  Returns a Point struct populated with the lat and lng coordinates
//                    of transposing the origin point a certain arc distance at a certain bearing.
func (p *Point) PointAtDistanceAndBearing(dist float64, bearing float64) *Point {
	// Earth's radius ~= 6,356.7523km
	// TODO Constantize
	dr := dist / 6356.7523

	bearing = (bearing * (math.Pi / 180.0))

	lat1 := (p.lat * (math.Pi / 180.0))
	lng1 := (p.lng * (math.Pi / 180.0))

	lat2_part1 := math.Sin(lat1) * math.Cos(dr)
	lat2_part2 := math.Cos(lat1) * math.Sin(dr) * math.Cos(bearing)

	lat2 := math.Asin(lat2_part1 + lat2_part2)

	lng2_part1 := math.Sin(bearing) * math.Sin(dr) * math.Cos(lat1)
	lng2_part2 := math.Cos(dr) - (math.Sin(lat1) * math.Sin(lat2))

	lng2 := lng1 + math.Atan2(lng2_part1, lng2_part2)
	lng2 = math.Mod((lng2+3*math.Pi), (2*math.Pi)) - math.Pi

	lat2 = lat2 * (180.0 / math.Pi)
	lng2 = lng2 * (180.0 / math.Pi)

	return &Point{lat: lat2, lng: lng2}
}

// Original Implementation from: http://www.movable-type.co.uk/scripts/latlong.html
// Calculates the Haversine distance between two points.
// @param [*Point].  The destination point.
// @return [float64].  The distance between the origin point and the destination point.
func (p *Point) GreatCircleDistance(p2 *Point) float64 {
	r := 6356.7523 // km
	dLat := (p2.lat - p.lat) * (math.Pi / 180.0)
	dLon := (p2.lng - p.lng) * (math.Pi / 180.0)

	lat1 := p.lat * (math.Pi / 180.0)
	lat2 := p2.lat * (math.Pi / 180.0)

	a1 := math.Sin(dLat/2) * math.Sin(dLat/2)
	a2 := math.Sin(dLon/2) * math.Sin(dLon/2) * math.Cos(lat1) * math.Cos(lat2)

	a := a1 + a2

	c := 2 * math.Atan2(math.Sqrt(a), math.Sqrt(1-a))

	return r * c
}
<commit_msg>[src] Reformatting the documentation for point.go and adding in EARTH_RADIUS constant<commit_after>package geo

import (
	"math"
)

// Represents a Physical Point in geographic notation [lat, lng].
type Point struct {
	lat float64
	lng float64
}

const (
	EARTH_RADIUS = 6356.7523 // Earth's radius ~= 6,356.7523km
)

// Returns a Point populated with the lat and lng coordinates of transposing the origin point the distance (in meters) supplied by the compass bearing (in degrees) supplied.
// Original Implementation from: http://www.movable-type.co.uk/scripts/latlong.html
func (p *Point) PointAtDistanceAndBearing(dist float64, bearing float64) *Point {

	dr := dist / EARTH_RADIUS

	bearing = (bearing * (math.Pi / 180.0))

	lat1 := (p.lat * (math.Pi / 180.0))
	lng1 := (p.lng * (math.Pi / 180.0))

	lat2_part1 := math.Sin(lat1) * math.Cos(dr)
	lat2_part2 := math.Cos(lat1) * math.Sin(dr) * math.Cos(bearing)

	lat2 := math.Asin(lat2_part1 + lat2_part2)

	lng2_part1 := math.Sin(bearing) * math.Sin(dr) * math.Cos(lat1)
	lng2_part2 := math.Cos(dr) - (math.Sin(lat1) * math.Sin(lat2))

	lng2 := lng1 + math.Atan2(lng2_part1, lng2_part2)
	lng2 = math.Mod((lng2+3*math.Pi), (2*math.Pi)) - math.Pi

	lat2 = lat2 * (180.0 / math.Pi)
	lng2 = lng2 * (180.0 / math.Pi)

	return &Point{lat: lat2, lng: lng2}
}

// Calculates the Haversine distance between two points.
// Original Implementation from: http://www.movable-type.co.uk/scripts/latlong.html
func (p *Point) GreatCircleDistance(p2 *Point) float64 {
	//r := 6356.7523 // km
	dLat := (p2.lat - p.lat) * (math.Pi / 180.0)
	dLon := (p2.lng - p.lng) * (math.Pi / 180.0)

	lat1 := p.lat * (math.Pi / 180.0)
	lat2 := p2.lat * (math.Pi / 180.0)

	a1 := math.Sin(dLat/2) * math.Sin(dLat/2)
	a2 := math.Sin(dLon/2) * math.Sin(dLon/2) * math.Cos(lat1) * math.Cos(lat2)

	a := a1 + a2

	c := 2 * math.Atan2(math.Sqrt(a), math.Sqrt(1-a))

	return EARTH_RADIUS * c
}<|endoftext|>


<commit_before>// +build !rexray_build_type_client

package cli

import (
	"bytes"
	"fmt"
	"os"
	"os/exec"
	"path"
	"runtime"
	"strings"
	"text/template"

	log "github.com/Sirupsen/logrus"
	"github.com/akutz/gotil"
	"github.com/codedellemc/rexray/util"
)

func init() {
	installFunc = install
	uninstallFunc = uninstall
}

// init system types
const (
	Unknown = iota
	SystemD
	UpdateRcD
	ChkConfig
)

func install() {
	checkOpPerms("installed")
	if runtime.GOOS == "linux" {
		switch getInitSystemType() {
		case SystemD:
			installSystemD()
		case UpdateRcD:
			installUpdateRcd()
		case ChkConfig:
			installChkConfig()
		}
	}
}

func isRpmInstall(pkgName *string) bool {
	exePath := util.BinFilePath
	cmd := exec.Command("rpm", "-qf", exePath)
	output, err := cmd.CombinedOutput()
	soutput := string(output)
	if err != nil {
		log.WithFields(log.Fields{
			"exePath": exePath,
			"output":  soutput,
			"error":   err,
		}).Debug("error checking if rpm install")
		return false
	}
	log.WithField("output", soutput).Debug("rpm install query result")
	*pkgName = gotil.Trim(soutput)

	log.WithFields(log.Fields{
		"exePath": exePath,
		"pkgName": *pkgName,
	}).Debug("is rpm install success")
	return true
}

func isDebInstall(pkgName *string) bool {
	exePath := util.BinFilePath
	cmd := exec.Command("dpkg-query", "-S", exePath)
	output, err := cmd.CombinedOutput()
	soutput := string(output)
	if err != nil {
		log.WithFields(log.Fields{
			"exePath": exePath,
			"output":  soutput,
			"error":   err,
		}).Debug("error checking if deb install")
		return false
	}
	log.WithField("output", soutput).Debug("deb install query result")
	*pkgName = strings.Split(gotil.Trim(soutput), ":")[0]

	log.WithFields(log.Fields{
		"exePath": exePath,
		"pkgName": *pkgName,
	}).Debug("is deb install success")
	return true
}

func uninstallRpm(pkgName string) bool {
	output, err := exec.Command("rpm", "-e", pkgName).CombinedOutput()
	if err != nil {
		log.WithFields(log.Fields{
			"pkgName": pkgName,
			"output":  string(output),
			"error":   err,
		}).Error("error uninstalling rpm")
	}
	return true
}

func uninstallDeb(pkgName string) bool {
	output, err := exec.Command("dpkg", "-r", pkgName).CombinedOutput()
	if err != nil {
		log.WithFields(log.Fields{
			"pkgName": pkgName,
			"output":  string(output),
			"error":   err,
		}).Error("error uninstalling deb")
	}
	return true
}

func uninstall(pkgManager bool) {
	checkOpPerms("uninstalled")

	binFilePath := util.BinFilePath

	// if the uninstall command was executed manually we should check to see
	// if this file is owned by a package manager and remove it that way if so
	if !pkgManager {
		log.WithField("binFilePath", binFilePath).Debug(
			"is this a managed file?")
		var pkgName string
		if isRpmInstall(&pkgName) {
			uninstallRpm(pkgName)
			return
		} else if isDebInstall(&pkgName) {
			uninstallDeb(pkgName)
			return
		}
	}

	func() {
		defer func() {
			recover()
		}()
		stop()
	}()

	switch getInitSystemType() {
	case SystemD:
		uninstallSystemD()
	case UpdateRcD:
		uninstallUpdateRcd()
	case ChkConfig:
		uninstallChkConfig()
	}

	if !pkgManager {
		os.Remove(binFilePath)
		if util.IsPrefixed() {
			os.RemoveAll(util.GetPrefix())
		}
	}
}

func getInitSystemCmd() string {
	switch getInitSystemType() {
	case SystemD:
		return "systemd"
	case UpdateRcD:
		return "update-rc.d"
	case ChkConfig:
		return "chkconfig"
	default:
		return "unknown"
	}
}

func getInitSystemType() int {
	if gotil.FileExistsInPath("systemctl") {
		return SystemD
	}

	if gotil.FileExistsInPath("update-rc.d") {
		return UpdateRcD
	}

	if gotil.FileExistsInPath("chkconfig") {
		return ChkConfig
	}

	return Unknown
}

func installSystemD() {
	createUnitFile()
	createEnvFile()

	cmd := exec.Command("systemctl", "enable", "-q", util.UnitFileName)
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	err := cmd.Run()

	if err != nil {
		log.Fatalf("installation error %v", err)
	}

	fmt.Print("REX-Ray is now installed. Before starting it please check ")
	fmt.Print("http://github.com/codedellemc/rexray for instructions on how to ")
	fmt.Print("configure it.\n\n Once configured the REX-Ray service can be ")
	fmt.Print("started with the command 'sudo systemctl start rexray'.\n\n")
}

func uninstallSystemD() {

	// a link created by systemd as docker should "want" rexray as a service.
	// the uninstaller will fail
	os.Remove(path.Join("/etc/systemd/system/docker.service.wants",
		util.UnitFileName))

	cmd := exec.Command("systemctl", "disable", "-q", util.UnitFileName)
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	err := cmd.Run()

	if err != nil {
		log.Fatalf("uninstallation error %v", err)
	}

	os.Remove(util.UnitFilePath)
}

func installUpdateRcd() {
	createInitFile()
	cmd := exec.Command("update-rc.d", util.InitFileName, "defaults")
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	if err := cmd.Run(); err != nil {
		log.Fatalf("installation error %v", err)
	}
	fmt.Print("REX-Ray is now installed. Before starting it please check ")
	fmt.Print("http://github.com/codedellemc/rexray for instructions on how to ")
	fmt.Print("configure it.\n\n Once configured the REX-Ray service can be ")
	fmt.Print("started with the command ")
	fmt.Printf("'sudo %s start'.\n\n", util.InitFilePath)
}

func uninstallUpdateRcd() {
	os.Remove(util.InitFilePath)
	cmd := exec.Command("update-rc.d", util.InitFileName, "remove")
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	if err := cmd.Run(); err != nil {
		log.Fatalf("uninstallation error %v", err)
	}
}

func installChkConfig() {
	createInitFile()
	cmd := exec.Command("chkconfig", util.InitFileName, "on")
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	if err := cmd.Run(); err != nil {
		log.Fatalf("installation error %v", err)
	}
	fmt.Print("REX-Ray is now installed. Before starting it please check ")
	fmt.Print("http://github.com/codedellemc/rexray for instructions on how to ")
	fmt.Print("configure it.\n\n Once configured the REX-Ray service can be ")
	fmt.Print("started with the command ")
	fmt.Printf("'sudo %s start'.\n\n", util.InitFilePath)
}

func uninstallChkConfig() {
	cmd := exec.Command("chkconfig", "--del", util.InitFileName)
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	if err := cmd.Run(); err != nil {
		log.Fatalf("uninstallation error %v", err)
	}
	os.Remove(util.InitFilePath)
}

func createEnvFile() {
	f, err := os.OpenFile(util.EnvFilePath(), os.O_CREATE|os.O_WRONLY, 0644)
	if err != nil {
		panic(err)
	}
	defer f.Close()
	if util.IsPrefixed() {
		f.WriteString("REXRAY_HOME=")
		f.WriteString(util.GetPrefix())
	}
}

func createUnitFile() {
	data := struct {
		BinFileName string
		BinFilePath string
		EnvFilePath string
	}{
		util.BinFileName,
		util.BinFilePath,
		util.EnvFilePath(),
	}
	tmpl, err := template.New("UnitFile").Parse(unitFileTemplate)
	if err != nil {
		panic(err)
	}
	var buf bytes.Buffer
	err = tmpl.Execute(&buf, data)
	if err != nil {
		panic(err)
	}
	text := buf.String()
	f, err := os.OpenFile(util.UnitFilePath, os.O_CREATE|os.O_WRONLY, 0644)
	if err != nil {
		panic(err)
	}
	defer f.Close()
	f.WriteString(text)
}

const unitFileTemplate = `[Unit]
Description={{.BinFileName}}
Before=docker.service

[Service]
EnvironmentFile={{.EnvFilePath}}
ExecStart={{.BinFilePath}} start -f
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process

[Install]
WantedBy=docker.service
Wants=scini.service
Before=docker.service
After=scini.service
`

func createInitFile() {
	data := struct {
		BinFileName string
		BinFilePath string
	}{
		util.BinFileName,
		util.BinFilePath,
	}
	tmpl, err := template.New("InitScript").Parse(initScriptTemplate)
	if err != nil {
		panic(err)
	}
	var buf bytes.Buffer
	err = tmpl.Execute(&buf, data)
	if err != nil {
		panic(err)
	}
	text := buf.String()
	// wrapped in a function to defer the close to ensure file is written to
	// disk before subsequent chmod below
	func() {
		f, err := os.OpenFile(util.InitFilePath, os.O_CREATE|os.O_WRONLY, 0644)
		if err != nil {
			panic(err)
		}
		defer f.Close()
		f.WriteString(text)
	}()
	os.Chmod(util.InitFilePath, 0755)
}

const initScriptTemplate = `### BEGIN INIT INFO
# Provides:          {{.BinFileName}}
# Required-Start:    $remote_fs $syslog
# Required-Stop:     $remote_fs $syslog
# Should-Start:      scini
# X-Start-Before:    docker
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Start daemon at boot time
# Description:       Enable service provided by daemon.
### END INIT INFO

case "$1" in
  start)
    {{.BinFilePath}} start
    ;;
  stop)
    {{.BinFilePath}} stop
    ;;
  status)
    {{.BinFilePath}} status
    ;;
  restart)
    {{.BinFilePath}} restart
    ;;
  reload)
    {{.BinFilePath}} reload
    ;;
  force-reload)
    {{.BinFilePath}} force-reload
    ;;
  *)
    echo "Usage: $0 {start|stop|status|restart|reload|force-reload}"
esac
`
<commit_msg>Fix Unit File Sections<commit_after>// +build !rexray_build_type_client

package cli

import (
	"bytes"
	"fmt"
	"os"
	"os/exec"
	"path"
	"runtime"
	"strings"
	"text/template"

	log "github.com/Sirupsen/logrus"
	"github.com/akutz/gotil"
	"github.com/codedellemc/rexray/util"
)

func init() {
	installFunc = install
	uninstallFunc = uninstall
}

// init system types
const (
	Unknown = iota
	SystemD
	UpdateRcD
	ChkConfig
)

func install() {
	checkOpPerms("installed")
	if runtime.GOOS == "linux" {
		switch getInitSystemType() {
		case SystemD:
			installSystemD()
		case UpdateRcD:
			installUpdateRcd()
		case ChkConfig:
			installChkConfig()
		}
	}
}

func isRpmInstall(pkgName *string) bool {
	exePath := util.BinFilePath
	cmd := exec.Command("rpm", "-qf", exePath)
	output, err := cmd.CombinedOutput()
	soutput := string(output)
	if err != nil {
		log.WithFields(log.Fields{
			"exePath": exePath,
			"output":  soutput,
			"error":   err,
		}).Debug("error checking if rpm install")
		return false
	}
	log.WithField("output", soutput).Debug("rpm install query result")
	*pkgName = gotil.Trim(soutput)

	log.WithFields(log.Fields{
		"exePath": exePath,
		"pkgName": *pkgName,
	}).Debug("is rpm install success")
	return true
}

func isDebInstall(pkgName *string) bool {
	exePath := util.BinFilePath
	cmd := exec.Command("dpkg-query", "-S", exePath)
	output, err := cmd.CombinedOutput()
	soutput := string(output)
	if err != nil {
		log.WithFields(log.Fields{
			"exePath": exePath,
			"output":  soutput,
			"error":   err,
		}).Debug("error checking if deb install")
		return false
	}
	log.WithField("output", soutput).Debug("deb install query result")
	*pkgName = strings.Split(gotil.Trim(soutput), ":")[0]

	log.WithFields(log.Fields{
		"exePath": exePath,
		"pkgName": *pkgName,
	}).Debug("is deb install success")
	return true
}

func uninstallRpm(pkgName string) bool {
	output, err := exec.Command("rpm", "-e", pkgName).CombinedOutput()
	if err != nil {
		log.WithFields(log.Fields{
			"pkgName": pkgName,
			"output":  string(output),
			"error":   err,
		}).Error("error uninstalling rpm")
	}
	return true
}

func uninstallDeb(pkgName string) bool {
	output, err := exec.Command("dpkg", "-r", pkgName).CombinedOutput()
	if err != nil {
		log.WithFields(log.Fields{
			"pkgName": pkgName,
			"output":  string(output),
			"error":   err,
		}).Error("error uninstalling deb")
	}
	return true
}

func uninstall(pkgManager bool) {
	checkOpPerms("uninstalled")

	binFilePath := util.BinFilePath

	// if the uninstall command was executed manually we should check to see
	// if this file is owned by a package manager and remove it that way if so
	if !pkgManager {
		log.WithField("binFilePath", binFilePath).Debug(
			"is this a managed file?")
		var pkgName string
		if isRpmInstall(&pkgName) {
			uninstallRpm(pkgName)
			return
		} else if isDebInstall(&pkgName) {
			uninstallDeb(pkgName)
			return
		}
	}

	func() {
		defer func() {
			recover()
		}()
		stop()
	}()

	switch getInitSystemType() {
	case SystemD:
		uninstallSystemD()
	case UpdateRcD:
		uninstallUpdateRcd()
	case ChkConfig:
		uninstallChkConfig()
	}

	if !pkgManager {
		os.Remove(binFilePath)
		if util.IsPrefixed() {
			os.RemoveAll(util.GetPrefix())
		}
	}
}

func getInitSystemCmd() string {
	switch getInitSystemType() {
	case SystemD:
		return "systemd"
	case UpdateRcD:
		return "update-rc.d"
	case ChkConfig:
		return "chkconfig"
	default:
		return "unknown"
	}
}

func getInitSystemType() int {
	if gotil.FileExistsInPath("systemctl") {
		return SystemD
	}

	if gotil.FileExistsInPath("update-rc.d") {
		return UpdateRcD
	}

	if gotil.FileExistsInPath("chkconfig") {
		return ChkConfig
	}

	return Unknown
}

func installSystemD() {
	createUnitFile()
	createEnvFile()

	cmd := exec.Command("systemctl", "enable", "-q", util.UnitFileName)
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	err := cmd.Run()

	if err != nil {
		log.Fatalf("installation error %v", err)
	}

	fmt.Print("REX-Ray is now installed. Before starting it please check ")
	fmt.Print("http://github.com/codedellemc/rexray for instructions on how to ")
	fmt.Print("configure it.\n\n Once configured the REX-Ray service can be ")
	fmt.Print("started with the command 'sudo systemctl start rexray'.\n\n")
}

func uninstallSystemD() {

	// a link created by systemd as docker should "want" rexray as a service.
	// the uninstaller will fail
	os.Remove(path.Join("/etc/systemd/system/docker.service.wants",
		util.UnitFileName))

	cmd := exec.Command("systemctl", "disable", "-q", util.UnitFileName)
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	err := cmd.Run()

	if err != nil {
		log.Fatalf("uninstallation error %v", err)
	}

	os.Remove(util.UnitFilePath)
}

func installUpdateRcd() {
	createInitFile()
	cmd := exec.Command("update-rc.d", util.InitFileName, "defaults")
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	if err := cmd.Run(); err != nil {
		log.Fatalf("installation error %v", err)
	}
	fmt.Print("REX-Ray is now installed. Before starting it please check ")
	fmt.Print("http://github.com/codedellemc/rexray for instructions on how to ")
	fmt.Print("configure it.\n\n Once configured the REX-Ray service can be ")
	fmt.Print("started with the command ")
	fmt.Printf("'sudo %s start'.\n\n", util.InitFilePath)
}

func uninstallUpdateRcd() {
	os.Remove(util.InitFilePath)
	cmd := exec.Command("update-rc.d", util.InitFileName, "remove")
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	if err := cmd.Run(); err != nil {
		log.Fatalf("uninstallation error %v", err)
	}
}

func installChkConfig() {
	createInitFile()
	cmd := exec.Command("chkconfig", util.InitFileName, "on")
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	if err := cmd.Run(); err != nil {
		log.Fatalf("installation error %v", err)
	}
	fmt.Print("REX-Ray is now installed. Before starting it please check ")
	fmt.Print("http://github.com/codedellemc/rexray for instructions on how to ")
	fmt.Print("configure it.\n\n Once configured the REX-Ray service can be ")
	fmt.Print("started with the command ")
	fmt.Printf("'sudo %s start'.\n\n", util.InitFilePath)
}

func uninstallChkConfig() {
	cmd := exec.Command("chkconfig", "--del", util.InitFileName)
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	if err := cmd.Run(); err != nil {
		log.Fatalf("uninstallation error %v", err)
	}
	os.Remove(util.InitFilePath)
}

func createEnvFile() {
	f, err := os.OpenFile(util.EnvFilePath(), os.O_CREATE|os.O_WRONLY, 0644)
	if err != nil {
		panic(err)
	}
	defer f.Close()
	if util.IsPrefixed() {
		f.WriteString("REXRAY_HOME=")
		f.WriteString(util.GetPrefix())
	}
}

func createUnitFile() {
	data := struct {
		BinFileName string
		BinFilePath string
		EnvFilePath string
	}{
		util.BinFileName,
		util.BinFilePath,
		util.EnvFilePath(),
	}
	tmpl, err := template.New("UnitFile").Parse(unitFileTemplate)
	if err != nil {
		panic(err)
	}
	var buf bytes.Buffer
	err = tmpl.Execute(&buf, data)
	if err != nil {
		panic(err)
	}
	text := buf.String()
	f, err := os.OpenFile(util.UnitFilePath, os.O_CREATE|os.O_WRONLY, 0644)
	if err != nil {
		panic(err)
	}
	defer f.Close()
	f.WriteString(text)
}

const unitFileTemplate = `[Unit]
Description={{.BinFileName}}
Wants=scini.service
Before=docker.service
After=scini.service

[Service]
EnvironmentFile={{.EnvFilePath}}
ExecStart={{.BinFilePath}} start -f
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process

[Install]
WantedBy=docker.service
`

func createInitFile() {
	data := struct {
		BinFileName string
		BinFilePath string
	}{
		util.BinFileName,
		util.BinFilePath,
	}
	tmpl, err := template.New("InitScript").Parse(initScriptTemplate)
	if err != nil {
		panic(err)
	}
	var buf bytes.Buffer
	err = tmpl.Execute(&buf, data)
	if err != nil {
		panic(err)
	}
	text := buf.String()
	// wrapped in a function to defer the close to ensure file is written to
	// disk before subsequent chmod below
	func() {
		f, err := os.OpenFile(util.InitFilePath, os.O_CREATE|os.O_WRONLY, 0644)
		if err != nil {
			panic(err)
		}
		defer f.Close()
		f.WriteString(text)
	}()
	os.Chmod(util.InitFilePath, 0755)
}

const initScriptTemplate = `### BEGIN INIT INFO
# Provides:          {{.BinFileName}}
# Required-Start:    $remote_fs $syslog
# Required-Stop:     $remote_fs $syslog
# Should-Start:      scini
# X-Start-Before:    docker
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Start daemon at boot time
# Description:       Enable service provided by daemon.
### END INIT INFO

case "$1" in
  start)
    {{.BinFilePath}} start
    ;;
  stop)
    {{.BinFilePath}} stop
    ;;
  status)
    {{.BinFilePath}} status
    ;;
  restart)
    {{.BinFilePath}} restart
    ;;
  reload)
    {{.BinFilePath}} reload
    ;;
  force-reload)
    {{.BinFilePath}} force-reload
    ;;
  *)
    echo "Usage: $0 {start|stop|status|restart|reload|force-reload}"
esac
`
<|endoftext|>


<commit_before>package cli

import (
	"strings"

	"github.com/jwaldrip/odin/cli/values"
)

func (cmd *CLI) parseParams(args []string) []string {
	var seenParams paramsList

	if len(cmd.params) == 0 {
		return args
	}
	i := 0
	for i < len(args) && i < len(cmd.params) {
		param := cmd.params[i]
		seenParams = append(seenParams, param)
		str := ""
		if cmd.paramValues == nil {
			cmd.paramValues = make(map[*Param]values.Value)
		}
		cmd.paramValues[param] = values.NewString(args[i], &str)
		i++
	}
	missingParams := cmd.params.Compare(seenParams)
	if len(missingParams) > 0 {
		var msg string
		if len(missingParams) == 1 {
			msg = "missing param"
		} else {
			msg = "missing params"
		}
		cmd.errf("%s: %s", msg, strings.Join(missingParams.Names(), ", "))
	}

	return args[i:]
}
<commit_msg>account for missing params<commit_after>package cli

import (
	"strings"

	"github.com/jwaldrip/odin/cli/values"
)

func (cmd *CLI) parseParams(args []string) []string {
	var i int
	var seenParams paramsList

	if len(cmd.params) == 0 {
		return args
	}
	for _, param := range cmd.params {
		cmd.setParamValue(param, "")
	}
	for i < len(args) && i < len(cmd.params) {
		param := cmd.params[i]
		seenParams = append(seenParams, param)
		cmd.setParamValue(param, args[i])
		i++
	}
	missingParams := cmd.params.Compare(seenParams)
	if len(missingParams) > 0 {
		var msg string
		if len(missingParams) == 1 {
			msg = "missing param"
		} else {
			msg = "missing params"
		}
		cmd.errf("%s: %s", msg, strings.Join(missingParams.Names(), ", "))
	}

	return args[i:]
}

func (cmd *CLI) setParamValue(param *Param, value string) {
	str := ""
	if cmd.paramValues == nil {
		cmd.paramValues = make(map[*Param]values.Value)
	}
	cmd.paramValues[param] = values.NewString(value, &str)
}
<|endoftext|>


<commit_before>// Copyright 2016 The appc Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package docker2aci

import "github.com/appc/spec/schema"

var Version = "0.9.1+git"
var AppcVersion = schema.AppContainerVersion
<commit_msg>version: bump to v0.9.2<commit_after>// Copyright 2016 The appc Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package docker2aci

import "github.com/appc/spec/schema"

var Version = "0.9.2"
var AppcVersion = schema.AppContainerVersion
<|endoftext|>


<commit_before>// Copyright 2016 The appc Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package docker2aci

import "github.com/appc/spec/schema"

var Version = "0.12.0"
var AppcVersion = schema.AppContainerVersion
<commit_msg>version: bump to v0.12.0+git<commit_after>// Copyright 2016 The appc Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package docker2aci

import "github.com/appc/spec/schema"

var Version = "0.12.0+git"
var AppcVersion = schema.AppContainerVersion
<|endoftext|>


<commit_before>package lib

const (
	// Version is the version number the client believes it is
	Version = "3.5"
)
<commit_msg>bump version to 4.0<commit_after>package lib

const (
	// Version is the version number the client believes it is
	Version = "4.0"
)
<|endoftext|>


<commit_before>// Copyright 2016 The appc Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package docker2aci

import "github.com/appc/spec/schema"

var Version = "0.16.0"
var AppcVersion = schema.AppContainerVersion
<commit_msg>version: bump to v0.16.0+git<commit_after>// Copyright 2016 The appc Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package docker2aci

import "github.com/appc/spec/schema"

var Version = "0.16.0+git"
var AppcVersion = schema.AppContainerVersion
<|endoftext|>


<commit_before>package main

import (
    "os"
    "os/signal"
    "syscall"
    "bufio"
    "fmt"
    "log"
    //"bytes"
    //"encoding/binary"
    "strings"
    "path/filepath"
    "net"
    "mob/proto"
    "mob/client/music"
    //"github.com/tcolgate/mp3"
    "github.com/cenkalti/rpc2"
    "time"
    "sync"
)

// TCP and RPC handlers for the tracker
var conn net.Conn
var client *rpc2.Client

// UDP handler for handshake packets
var packetConn net.PacketConn

// This client's LAN IP address
// TODO: this is a cmd line arg; want to discover this automatically
var publicIp string

// Control flags
var connectedToTracker bool // did join a tracker
var isSeeder bool           // tells us if we have access to the mp3 or not
var alreadySeeding bool     // prevent tracker rpc from being over called

// Seeder's data structures
var peerToConn map[string]net.Conn
var seedees []string

var maxSeedees int

// Assume mp3 is no larger than 50MB. We reuse this buffer for each song we play.
// Don't need to worry when it gets GCed since we're using it the whole time
var songBuf [20 * 1024 * 1024]byte

// TODO: clients make rpc to say that they are done with the song
func main() {
    // Handle kill signal gracefully
    c := make(chan os.Signal, 2)
    signal.Notify(c, os.Interrupt, syscall.SIGTERM)
    go func() {
        <-c
        if client != nil {
            handleLeave()
        }
        os.Exit(1)
    }()

    // Initialize SDL audio
    music.Init()
    defer music.Quit()

    // Get our local network IP address
    publicIp = os.Args[1]

    // Set max number of seedees to our stream to prevent congestion on peers
    maxSeedees = 1
    seedees = make([]string, 0)
    peerToConn = make(map[string]net.Conn)
    connectedToTracker = false
    isSeeder = false
    alreadySeeding = false

    // Start the shell
    fmt.Print(
`
              ___.
  _____   ____\_ |__
 /     \ /  _ \| __ \
|  Y Y  (  <_> ) \_\ \
|__|_|  /\____/|___  /
      \/           \/
`)

    fmt.Println()
    fmt.Println("internet radio version 0.0.0")
    reader := bufio.NewReader(os.Stdin)

    for {
        fmt.Print(">>> ")
        input, _ := reader.ReadString('\n')
        input = strings.TrimSuffix(input, "\n")
        input = strings.TrimSpace(input)

        strs := strings.Split(input, " ")
        switch strs[0] {
        case "join": // join 192.168.1.12:1234
            handleJoin(strs[1])
        case "leave": // leave the network
            handleLeave()
        case "list-songs": // list
            handleListSongs()
        case "list-peers":
            handleListPeers()
        case "play": // play blah.mp3
            handlePlay(strs[1])
        case "quit": // quit the program
            if connectedToTracker {
                handleLeave()
            }
            return
        case "help": // help
            handleHelp()
        default:     // error message continue
            fmt.Println("Error: not a valid command")
            //handleHelp()
        }
    }
}

func handleJoin(input string) {
    if connectedToTracker {
        handleLeave()
    }

    var err error
    conn, err = net.Dial("tcp", input)
    if err != nil {
        log.Println(err)
    }

    client = rpc2.NewClient(conn)

    // Register the rpc handlers for seedToPeers() so that tracker can notify
    // client when to start seeding
    client.Handle("seed", func(client *rpc2.Client, args *proto.TrackerRes, reply *proto.HandshakePacket) error {
        if (alreadySeeding) {
          return nil
        }

        // Start seeding
        alreadySeeding = true
        isSeeder = true
        // TODO: set alreadyseeding to false once a done rpc is issued to the tracker
        go seedToPeers(args.Res)
        return nil
    })

    client.Handle("start-playing", func(client *rpc2.Client, args *proto.ClientInfoMsg, reply *proto.TrackerRes) error {
        // TODO: rpc for client to say song is done playing
        // currSong = ""
        return nil
    })

    go client.Run()

    connectedToTracker = true
    fmt.Println("Begin listen for peers")
    go listenForPeers()
    go handlePing()

    _, port, _ := net.SplitHostPort(conn.LocalAddr().String())
    client.Call("join", proto.ClientInfoMsg{net.JoinHostPort(publicIp, port), getSongNames()}, nil)
}

func handleLeave() {
    if !connectedToTracker {
        fmt.Println("Error: not connected to a tracker")
        return
    }

    connectedToTracker = false
    client.Call("leave", proto.ClientInfoMsg{conn.LocalAddr().String(), nil}, nil)
    fmt.Println("Leaving the tracker in 5 sec ...")
    time.Sleep(5000 * time.Millisecond)
    packetConn.Close()
    fmt.Println("done")
    //conn.Close() // TODO: is this right?
}

func handleListSongs() {
    if !connectedToTracker {
        fmt.Println("Error: not connected to a tracker")
        return
    }

    var res proto.TrackerSlice
    client.Call("list-songs", proto.ClientCmdMsg{""}, &res)
    fmt.Println(res.Res)
}

func handleListPeers() {
    if !connectedToTracker {
        fmt.Println("Error: not connected to a tracker")
        return
    }

    var res proto.TrackerSlice
    client.Call("list-peers", proto.ClientCmdMsg{""}, &res)
    fmt.Println(res.Res)
}

// need to listen for when to start playing to others
func handlePlay(input string) {
    if !connectedToTracker {
        fmt.Println("Error: not connected to a tracker")
        return
    }

    client.Call("play", proto.ClientCmdMsg{input}, nil)
}

func handleHelp() {
    fmt.Print(
`commands:
    join  - connect to a tracker
    leave - disconnect from a tracker
    list-songs - list all available songs
    list-peers - list all peers on the network
    play - enqueue a song to be played
    help - show commands
    quit - exit the program
`)
}

func handlePing() {
    _, port, _ := net.SplitHostPort(conn.LocalAddr().String())
    for {
        client.Call("ping", proto.ClientInfoMsg{net.JoinHostPort(publicIp, port), nil}, nil)
        time.Sleep(500 * time.Millisecond)
    }
}

// TODO: when song is done playing, set songBuf = songBuf[:0] to clear it
func listenForMp3Frames(publicIp string) {
    //mp3FrameAddr  := net.UDPAddr{IP: net.ParseIP(publicIp), Port: 6122,}
    //udpMp3Framer, _  = net.ListenUDP("udp", &mp3FrameAddr)

    // TODO: add second level seeding!

    //for {
    //    n, addr, err := udpHandshaker.ReadFromUDP(songBuf)
    //     go seedToPeers(currSong)
    //}
}

// Listens for udp request packets from peers in order to build the stream graph
// Handles all possible handshake packets that will be sent to this peer.
// Called in handleJoin when you join a tracker
func listenForPeers() {
    // listen to incoming udp packets
    fmt.Println("listening for peers!")
    var err error
    packetConn, err = net.ListenPacket("udp", net.JoinHostPort(publicIp, "6121"))
    if err != nil {
        log.Fatal(err)
    }
    //defer pc.Close()

    // Continously listen for handshake packets
    // Eventually after a successful round of handshaking, all peers will
    // be seeders and will block on the next ReadFrom() call until the next
    // round
    for connectedToTracker { // terminate when we leave a tracker
        // Read a packet
        buffer := make([]byte, 2048)
        n, addr, e := packetConn.ReadFrom(buffer) // block here
        if e != nil {
            log.Fatal("error when reading packet")
            return
        }
        s := string(buffer[:n])
        substrs := strings.Split(s, ":")
        ip, port, _ := net.SplitHostPort(addr.String())
        //dest := net.JoinHostPort(ip, "6121")
        fmt.Println(ip)
        fmt.Println(port)
        fmt.Println(s)
        //raddr := net.UDPAddr{IP: net.ParseIP(ip), Port: 6121}

        // Process the packet and handle
        switch substrs[0] {
        case "request": // where this client is a non-seeder
            if isSeeder || hasSongLocally(substrs[1]) {
                go func() {
                    for i := 0; i < 10; i++ { // redundancy
                        packetConn.WriteTo([]byte("reject"), addr)
                        time.Sleep(500 * time.Microsecond)
                    }
                }()
            } else {
                go func() {
                    for i := 0; i < 10; i++ { // redundancy
                        packetConn.WriteTo([]byte("accept"), addr)
                        time.Sleep(500 * time.Microsecond)
                    }
                }()
            }
        case "confirm": // where this client is a non-seeder
            if isSeeder {
                go func() {
                    for i := 0; i < 10; i++ { // redundancy
                        packetConn.WriteTo([]byte("reject"), addr)
                        time.Sleep(500 * time.Microsecond)
                    }
                }()
            } else {
                // Set this to false after the song finishes playing
                isSeeder = true
                go seedToPeers(substrs[1])
            }
        case "accept": // where this client is a seeder
            if isSeeder && len(seedees) < maxSeedees {
                ip, _, _ := net.SplitHostPort(addr.String())
                seedees = append(seedees, ip)
                go func() {
                    for i := 0; i < 10; i++ { // redundancy
                        packetConn.WriteTo([]byte("confirm"), addr)
                        time.Sleep(500 * time.Microsecond)
                    }
                }()
                peerToConn[ip].Close()
                peerToConn[ip] = nil
            } else if isSeeder && len(seedees) >= maxSeedees {
                peerToConn[ip].Close()
                peerToConn[ip] = nil
            } else {
                // is a non-seeder; shouldn't get here
                log.Fatal("non-seeder tried to accept other non-seeder")
            }
        case "reject": // where this client is a seeder
            // Clean up our connection to this peer
            peerToConn[ip].Close()
            peerToConn[ip] = nil
        }
    }
}

// If this client has access to mp3 stream, find peers to stream to.
// Broadcasts packets to peers until every peer has responded.
// Called by tracker rpc.
func seedToPeers(songFile string) {
    var wg sync.WaitGroup

    // Get list of peers from tracker
    var peers proto.TrackerSlice
    client.Call("list-peers", proto.ClientCmdMsg{""}, &peers)

    peerToConn = make(map[string]net.Conn)
    seedees = make([]string, 0)

    // Loop to acquire udp connections to all other peers
    for _, peer := range peers.Res {
        ip, _, _ := net.SplitHostPort(peer)

        if ip != publicIp { // check not this client
            // Connect to an available peer
            laddr := net.UDPAddr{IP: net.ParseIP(publicIp), Port: 6121}
	        raddr := net.UDPAddr{IP: net.ParseIP(ip), Port: 6121}

	        pc, _ := net.DialUDP("udp", &laddr, &raddr)

            //pc, _ := net.Dial("udp", net.JoinHostPort(ip, "6121"))
            fmt.Println("contacting " + net.JoinHostPort(ip, "6121") + " ...")
            peerToConn[ip] = pc

            wg.Add(1)
            // ARQ requests to the peer until we set its net.Conn to nil
            go func() {
                defer wg.Done()
                for peerToConn[ip] != nil {
                    pc.Write([]byte("request:" + songFile))
                    time.Sleep(500 * time.Microsecond)
                }
            }()
        }
    }

    wg.Wait()
    fmt.Println(seedees)
    // Done our job in stream graph; make rpc to tracker?
    // Or have ping have us move forward
    // TODO:
    fmt.Println("This client is ready to play!")
}

func handleStartPlaying() {
    // tracker will call this client rpc on ping when all peers are ready to
    // play
    //
    //
}

func handleDonePlaying() {
    // reset globals

    // make rpc call to tracker
}

// Returns csv of all song names in the songs folder.
func getSongNames() ([]string) {
    var songs []string
    filepath.Walk("../songs", func (p string, i os.FileInfo, err error) error {
        if err != nil {
            log.Println(err)
            return nil
        }

        s := filepath.Base(p)
        if strings.Compare(s, "songs") != 0 && strings.Contains(s, ".mp3") {
            songs = append(songs, s)
        }

        return nil
    })

    return songs
}

func hasSongLocally(songFile string) bool {
    for _, song := range getSongNames() {
        if song == songFile {
            return true
        }
    }

    return false
}
<commit_msg>don't store net.Conn, store booleans for peer responses<commit_after>package main

import (
    "os"
    "os/signal"
    "syscall"
    "bufio"
    "fmt"
    "log"
    //"bytes"
    //"encoding/binary"
    "strings"
    "path/filepath"
    "net"
    "mob/proto"
    "mob/client/music"
    //"github.com/tcolgate/mp3"
    "github.com/cenkalti/rpc2"
    "time"
    "sync"
)

// TCP and RPC handlers for the tracker
var conn net.Conn
var client *rpc2.Client

// UDP handler for handshake packets
var packetConn net.PacketConn

// This client's LAN IP address
// TODO: this is a cmd line arg; want to discover this automatically
var publicIp string

// Control flags
var connectedToTracker bool // did join a tracker
var isSeeder bool           // tells us if we have access to the mp3 or not
var alreadySeeding bool     // prevent tracker rpc from being over called

// Seeder's data structures
var peerToConn map[string]bool
var seedees []string

var maxSeedees int

// Assume mp3 is no larger than 50MB. We reuse this buffer for each song we play.
// Don't need to worry when it gets GCed since we're using it the whole time
var songBuf [20 * 1024 * 1024]byte

// TODO: clients make rpc to say that they are done with the song
func main() {
    // Handle kill signal gracefully
    c := make(chan os.Signal, 2)
    signal.Notify(c, os.Interrupt, syscall.SIGTERM)
    go func() {
        <-c
        if client != nil {
            handleLeave()
        }
        os.Exit(1)
    }()

    // Initialize SDL audio
    music.Init()
    defer music.Quit()

    // Get our local network IP address
    publicIp = os.Args[1]

    // Set max number of seedees to our stream to prevent congestion on peers
    maxSeedees = 1
    seedees = make([]string, 0)
    peerToConn = make(map[string]bool)
    connectedToTracker = false
    isSeeder = false
    alreadySeeding = false

    // Start the shell
    fmt.Print(
`
              ___.
  _____   ____\_ |__
 /     \ /  _ \| __ \
|  Y Y  (  <_> ) \_\ \
|__|_|  /\____/|___  /
      \/           \/
`)

    fmt.Println()
    fmt.Println("internet radio version 0.0.0")
    reader := bufio.NewReader(os.Stdin)

    for {
        fmt.Print(">>> ")
        input, _ := reader.ReadString('\n')
        input = strings.TrimSuffix(input, "\n")
        input = strings.TrimSpace(input)

        strs := strings.Split(input, " ")
        switch strs[0] {
        case "join": // join 192.168.1.12:1234
            handleJoin(strs[1])
        case "leave": // leave the network
            handleLeave()
        case "list-songs": // list
            handleListSongs()
        case "list-peers":
            handleListPeers()
        case "play": // play blah.mp3
            handlePlay(strs[1])
        case "quit": // quit the program
            if connectedToTracker {
                handleLeave()
            }
            return
        case "help": // help
            handleHelp()
        default:     // error message continue
            fmt.Println("Error: not a valid command")
            //handleHelp()
        }
    }
}

func handleJoin(input string) {
    if connectedToTracker {
        handleLeave()
    }

    var err error
    conn, err = net.Dial("tcp", input)
    if err != nil {
        log.Println(err)
    }

    client = rpc2.NewClient(conn)

    // Register the rpc handlers for seedToPeers() so that tracker can notify
    // client when to start seeding
    client.Handle("seed", func(client *rpc2.Client, args *proto.TrackerRes, reply *proto.HandshakePacket) error {
        if (alreadySeeding) {
          return nil
        }

        // Start seeding
        alreadySeeding = true
        isSeeder = true
        // TODO: set alreadyseeding to false once a done rpc is issued to the tracker
        go seedToPeers(args.Res)
        return nil
    })

    client.Handle("start-playing", func(client *rpc2.Client, args *proto.ClientInfoMsg, reply *proto.TrackerRes) error {
        // TODO: rpc for client to say song is done playing
        // currSong = ""
        return nil
    })

    go client.Run()

    connectedToTracker = true
    fmt.Println("Begin listen for peers")
    go listenForPeers()
    go handlePing()

    _, port, _ := net.SplitHostPort(conn.LocalAddr().String())
    client.Call("join", proto.ClientInfoMsg{net.JoinHostPort(publicIp, port), getSongNames()}, nil)
}

func handleLeave() {
    if !connectedToTracker {
        fmt.Println("Error: not connected to a tracker")
        return
    }

    connectedToTracker = false
    client.Call("leave", proto.ClientInfoMsg{conn.LocalAddr().String(), nil}, nil)
    fmt.Println("Leaving the tracker in 5 sec ...")
    time.Sleep(5000 * time.Millisecond)
    packetConn.Close()
    fmt.Println("done")
    //conn.Close() // TODO: is this right?
}

func handleListSongs() {
    if !connectedToTracker {
        fmt.Println("Error: not connected to a tracker")
        return
    }

    var res proto.TrackerSlice
    client.Call("list-songs", proto.ClientCmdMsg{""}, &res)
    fmt.Println(res.Res)
}

func handleListPeers() {
    if !connectedToTracker {
        fmt.Println("Error: not connected to a tracker")
        return
    }

    var res proto.TrackerSlice
    client.Call("list-peers", proto.ClientCmdMsg{""}, &res)
    fmt.Println(res.Res)
}

// need to listen for when to start playing to others
func handlePlay(input string) {
    if !connectedToTracker {
        fmt.Println("Error: not connected to a tracker")
        return
    }

    client.Call("play", proto.ClientCmdMsg{input}, nil)
}

func handleHelp() {
    fmt.Print(
`commands:
    join  - connect to a tracker
    leave - disconnect from a tracker
    list-songs - list all available songs
    list-peers - list all peers on the network
    play - enqueue a song to be played
    help - show commands
    quit - exit the program
`)
}

func handlePing() {
    _, port, _ := net.SplitHostPort(conn.LocalAddr().String())
    for {
        client.Call("ping", proto.ClientInfoMsg{net.JoinHostPort(publicIp, port), nil}, nil)
        time.Sleep(500 * time.Millisecond)
    }
}

// TODO: when song is done playing, set songBuf = songBuf[:0] to clear it
func listenForMp3Frames(publicIp string) {
    //mp3FrameAddr  := net.UDPAddr{IP: net.ParseIP(publicIp), Port: 6122,}
    //udpMp3Framer, _  = net.ListenUDP("udp", &mp3FrameAddr)

    // TODO: add second level seeding!

    //for {
    //    n, addr, err := udpHandshaker.ReadFromUDP(songBuf)
    //     go seedToPeers(currSong)
    //}
}

// Listens for udp request packets from peers in order to build the stream graph
// Handles all possible handshake packets that will be sent to this peer.
// Called in handleJoin when you join a tracker
func listenForPeers() {
    // listen to incoming udp packets
    fmt.Println("listening for peers!")
    var err error
    packetConn, err = net.ListenPacket("udp", net.JoinHostPort(publicIp, "6121"))
    if err != nil {
        log.Fatal(err)
    }
    //defer pc.Close()

    // Continously listen for handshake packets
    // Eventually after a successful round of handshaking, all peers will
    // be seeders and will block on the next ReadFrom() call until the next
    // round
    for connectedToTracker { // terminate when we leave a tracker
        // Read a packet
        buffer := make([]byte, 2048)
        n, addr, e := packetConn.ReadFrom(buffer) // block here
        if e != nil {
            log.Fatal("error when reading packet")
            return
        }
        s := string(buffer[:n])
        substrs := strings.Split(s, ":")
        ip, port, _ := net.SplitHostPort(addr.String())
        //dest := net.JoinHostPort(ip, "6121")
        fmt.Println(ip)
        fmt.Println(port)
        fmt.Println(s)
        //raddr := net.UDPAddr{IP: net.ParseIP(ip), Port: 6121}

        // Process the packet and handle
        switch substrs[0] {
        case "request": // where this client is a non-seeder
            if isSeeder || hasSongLocally(substrs[1]) {
                go func() {
                    for i := 0; i < 10; i++ { // redundancy
                        packetConn.WriteTo([]byte("reject"), addr)
                        time.Sleep(500 * time.Microsecond)
                    }
                }()
            } else {
                go func() {
                    for i := 0; i < 10; i++ { // redundancy
                        packetConn.WriteTo([]byte("accept"), addr)
                        time.Sleep(500 * time.Microsecond)
                    }
                }()
            }
        case "confirm": // where this client is a non-seeder
            if isSeeder {
                go func() {
                    for i := 0; i < 10; i++ { // redundancy
                        packetConn.WriteTo([]byte("reject"), addr)
                        time.Sleep(500 * time.Microsecond)
                    }
                }()
            } else {
                // Set this to false after the song finishes playing
                isSeeder = true
                go seedToPeers(substrs[1])
            }
        case "accept": // where this client is a seeder
            if isSeeder && len(seedees) < maxSeedees {
                ip, _, _ := net.SplitHostPort(addr.String())
                seedees = append(seedees, ip)
                go func() {
                    for i := 0; i < 10; i++ { // redundancy
                        packetConn.WriteTo([]byte("confirm"), addr)
                        time.Sleep(500 * time.Microsecond)
                    }
                }()
                //peerToConn[ip].Close()
                peerToConn[ip] = true
            } else if isSeeder && len(seedees) >= maxSeedees {
                //peerToConn[ip].Close()
                peerToConn[ip] = true
            } else {
                // is a non-seeder; shouldn't get here
                log.Fatal("non-seeder tried to accept other non-seeder")
            }
        case "reject": // where this client is a seeder
            // Clean up our connection to this peer
            //peerToConn[ip].Close()
            peerToConn[ip] = true
        }
    }
}

// If this client has access to mp3 stream, find peers to stream to.
// Broadcasts packets to peers until every peer has responded.
// Called by tracker rpc.
func seedToPeers(songFile string) {
    var wg sync.WaitGroup

    // Get list of peers from tracker
    var peers proto.TrackerSlice
    client.Call("list-peers", proto.ClientCmdMsg{""}, &peers)

    peerToConn = make(map[string]bool)
    seedees = make([]string, 0)

    // Loop to acquire udp connections to all other peers
    for _, peer := range peers.Res {
        ip, _, _ := net.SplitHostPort(peer)

        if ip != publicIp { // check not this client
            // Connect to an available peer
            laddr := net.UDPAddr{IP: net.ParseIP(publicIp), Port: 6121}
	        raddr := net.UDPAddr{IP: net.ParseIP(ip), Port: 6121}

	        pc, _ := net.DialUDP("udp", &laddr, &raddr)

            //pc, _ := net.Dial("udp", net.JoinHostPort(ip, "6121"))
            fmt.Println("contacting " + net.JoinHostPort(ip, "6121") + " ...")
            peerToConn[ip] = false

            wg.Add(1)
            // ARQ requests to the peer until we set its net.Conn to nil
            go func() {
                defer wg.Done()
                defer pc.Close()
                for !peerToConn[ip] {
                    pc.Write([]byte("request:" + songFile))
                    time.Sleep(500 * time.Microsecond)
                }
            }()
        }
    }

    wg.Wait()
    fmt.Println(seedees)
    // Done our job in stream graph; make rpc to tracker?
    // Or have ping have us move forward
    // TODO:
    fmt.Println("This client is ready to play!")
}

func handleStartPlaying() {
    // tracker will call this client rpc on ping when all peers are ready to
    // play
    //
    //
}

func handleDonePlaying() {
    // reset globals

    // make rpc call to tracker
}

// Returns csv of all song names in the songs folder.
func getSongNames() ([]string) {
    var songs []string
    filepath.Walk("../songs", func (p string, i os.FileInfo, err error) error {
        if err != nil {
            log.Println(err)
            return nil
        }

        s := filepath.Base(p)
        if strings.Compare(s, "songs") != 0 && strings.Contains(s, ".mp3") {
            songs = append(songs, s)
        }

        return nil
    })

    return songs
}

func hasSongLocally(songFile string) bool {
    for _, song := range getSongNames() {
        if song == songFile {
            return true
        }
    }

    return false
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/bytbox/procfs.go/procfs"
	"json"
	"log"
)

func main() {
	var pfs procfs.ProcFS
	pfs.Fill()
	str, err := json.MarshalIndent(pfs, "", "  ")
	if err != nil {
		log.Fatal("ERR: ", err)
	}
	println(string(str))
}
<commit_msg>Performing periodic updates<commit_after>package main

import (
	"flag"
	"log"
	"time"
	"sync"

	"github.com/bytbox/procfs.go/procfs"
)

var pfs *procfs.ProcFS
var pfsMutex sync.Mutex
var interval = flag.Int64("interval", 10, "update interval")

func main() {
	flag.Parse()

	go updater()

/*
	var pfs procfs.ProcFS
	pfs.Fill()
	str, err := json.MarshalIndent(pfs, "", "  ")
	if err != nil {
		log.Fatal("ERR: ", err)
	}
	println(string(str))
*/

	<-make(chan int)
}

// Maintain an updated version of ProcFS
func updater() {
	ticker := time.Tick(1e9 * *interval)
	for true {
		log.Print("Updating...")
		sn := time.Nanoseconds()
		var pfs2 procfs.ProcFS
		pfs2.Fill()
		pfsMutex.Lock()
		pfs = &pfs2
		pfsMutex.Unlock()
		en := time.Nanoseconds()
		log.Print("Done in ", (en-sn)/1000, "μs")
		<-ticker
	}
}
<|endoftext|>


<commit_before>// This file is subject to a 1-clause BSD license.
// Its contents can be found in the enclosed LICENSE file.

package main

import (
	"log"
	"strings"
)

// Bind binds protocol message handlers.
func Bind(c *proto.Client) {
	c.Bind(proto.Unknown, onAny)
	c.Bind(proto.CmdPing, onPing)
	c.Bind(proto.EndOfMOTD, onJoinChannels)
	c.Bind(proto.ErrNoMOTD, onJoinChannels)
	c.Bind(proto.ErrNicknameInUse, onNickInUse)
	c.Bind(proto.CmdPrivMsg, onPrivMsg)
}

// onAny is a catch-all handler for all incoming messages.
// It is used to write incoming messages to a log.
func onAny(c *proto.Client, m *proto.Message) {
	log.Printf("> [%03d] [%s] %s", m.Command, m.Receiver, m.Data)
}

// onPing handles PING messages.
func onPing(c *proto.Client, m *proto.Message) {
	c.Pong(m.Data)
}

// onJoinChannels is used to complete the login procedure.
// We have just received the server's MOTD and now is a good time to
// start joining channels.
func onJoinChannels(c *proto.Client, m *proto.Message) {
	c.Join(config.Channels)
}

// onNickInUse is called whenever we receive a notification that our
// nickname is already in use. We will attempt to re-acquire it by
// identifying with our password. Otherwise we will pick a new name.
func onNickInUse(c *proto.Client, m *proto.Message) {
	if len(config.NickservPassword) > 0 {
		c.Recover(config.Nickname, config.NickservPassword)
		return
	}

	config.SetNickname(config.Nickname + "_")
	c.Nick(config.Nickname, "")
}

// onPrivMsg handles private messages directed at us.
// We want to know if it concerns a CTCP request, a bot command
// or just random talk.
func onPrivMsg(c *proto.Client, m *proto.Message) {
	if ctcpVersion(c, m) {
		return
	}

	if ctcpPing(c, m) {
		return
	}

	if readCommand(c, m) {
		return
	}
}
<commit_msg>Removes unused import for real this time.<commit_after>// This file is subject to a 1-clause BSD license.
// Its contents can be found in the enclosed LICENSE file.

package main

import (
	"github.com/jteeuwen/ircb/proto"
	"log"
)

// Bind binds protocol message handlers.
func Bind(c *proto.Client) {
	c.Bind(proto.Unknown, onAny)
	c.Bind(proto.CmdPing, onPing)
	c.Bind(proto.EndOfMOTD, onJoinChannels)
	c.Bind(proto.ErrNoMOTD, onJoinChannels)
	c.Bind(proto.ErrNicknameInUse, onNickInUse)
	c.Bind(proto.CmdPrivMsg, onPrivMsg)
}

// onAny is a catch-all handler for all incoming messages.
// It is used to write incoming messages to a log.
func onAny(c *proto.Client, m *proto.Message) {
	log.Printf("> [%03d] [%s] %s", m.Command, m.Receiver, m.Data)
}

// onPing handles PING messages.
func onPing(c *proto.Client, m *proto.Message) {
	c.Pong(m.Data)
}

// onJoinChannels is used to complete the login procedure.
// We have just received the server's MOTD and now is a good time to
// start joining channels.
func onJoinChannels(c *proto.Client, m *proto.Message) {
	c.Join(config.Channels)
}

// onNickInUse is called whenever we receive a notification that our
// nickname is already in use. We will attempt to re-acquire it by
// identifying with our password. Otherwise we will pick a new name.
func onNickInUse(c *proto.Client, m *proto.Message) {
	if len(config.NickservPassword) > 0 {
		c.Recover(config.Nickname, config.NickservPassword)
		return
	}

	config.SetNickname(config.Nickname + "_")
	c.Nick(config.Nickname, "")
}

// onPrivMsg handles private messages directed at us.
// We want to know if it concerns a CTCP request, a bot command
// or just random talk.
func onPrivMsg(c *proto.Client, m *proto.Message) {
	if ctcpVersion(c, m) {
		return
	}

	if ctcpPing(c, m) {
		return
	}

	if readCommand(c, m) {
		return
	}
}
<|endoftext|>