<commit_before>/*
Copyright 2020 The Skaffold 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 initializer

import (
	"bytes"
	"context"
	"fmt"
	"os"
	"path/filepath"
	"strings"
	"testing"

	"github.com/GoogleContainerTools/skaffold/pkg/skaffold/config"
	"github.com/GoogleContainerTools/skaffold/pkg/skaffold/schema"
	"github.com/GoogleContainerTools/skaffold/testutil"
)

func TestDoInit(t *testing.T) {
	tests := []struct {
		name      string
		dir       string
		config    Config
		shouldErr bool
	}{
		//TODO: mocked kompose test
		{
			name: "getting-started",
			dir:  "testdata/init/hello",
			config: Config{
				Opts: config.SkaffoldOptions{
					ConfigurationFile: "skaffold.yaml.out",
				},
			},
		},
		{
			name: "ignore existing tags",
			dir:  "testdata/init/ignore-tags",
			config: Config{
				Opts: config.SkaffoldOptions{
					ConfigurationFile: "skaffold.yaml.out",
				},
			},
		},
		{
			name: "microservices (backwards compatibility)",
			dir:  "testdata/init/microservices",
			config: Config{
				CliArtifacts: []string{
					"leeroy-app/Dockerfile=gcr.io/k8s-skaffold/leeroy-app",
					"leeroy-web/Dockerfile=gcr.io/k8s-skaffold/leeroy-web",
				},
				Opts: config.SkaffoldOptions{
					ConfigurationFile: "skaffold.yaml.out",
				},
			},
		},
		{
			name: "microservices",
			dir:  "testdata/init/microservices",
			config: Config{
				CliArtifacts: []string{
					`{"builder":"Docker","payload":{"path":"leeroy-app/Dockerfile"},"image":"gcr.io/k8s-skaffold/leeroy-app"}`,
					`{"builder":"Docker","payload":{"path":"leeroy-web/Dockerfile"},"image":"gcr.io/k8s-skaffold/leeroy-web"}`,
				},
				Opts: config.SkaffoldOptions{
					ConfigurationFile: "skaffold.yaml.out",
				},
			},
		},
		{
			name: "error writing config file",
			dir:  "testdata/init/microservices",

			config: Config{
				CliArtifacts: []string{
					`{"builder":"Docker","payload":{"path":"leeroy-app/Dockerfile"},"image":"gcr.io/k8s-skaffold/leeroy-app"}`,
					`{"builder":"Docker","payload":{"path":"leeroy-web/Dockerfile"},"image":"gcr.io/k8s-skaffold/leeroy-web"}`,
				},
				Opts: config.SkaffoldOptions{
					// erroneous config file as . is a directory
					ConfigurationFile: ".",
				},
			},
			shouldErr: true,
		},
		{
			name: "error no manifests",
			dir:  "testdata/init/hello-no-manifest",

			config: Config{
				Opts: config.SkaffoldOptions{
					ConfigurationFile: "skaffold.yaml.out",
				},
			},
			shouldErr: true,
		},
	}
	for _, test := range tests {
		testutil.Run(t, test.name, func(t *testutil.T) {
			t.Chdir(test.dir)
			// we still need as a "no-prompt" mode
			test.config.Force = true
			err := DoInit(context.TODO(), os.Stdout, test.config)
			t.CheckError(test.shouldErr, err)
			if !test.shouldErr {
				checkGeneratedConfig(t, ".")
			}
		})
	}
}

func TestDoInitAnalyze(t *testing.T) {
	tests := []struct {
		name        string
		dir         string
		config      Config
		expectedOut string
	}{
		{
			name: "analyze microservices",
			dir:  "testdata/init/microservices",
			config: Config{
				Analyze: true,
			},
			expectedOut: strip(`{
							"dockerfiles":["leeroy-app/Dockerfile","leeroy-web/Dockerfile"],
							"images":["gcr.io/k8s-skaffold/leeroy-app","gcr.io/k8s-skaffold/leeroy-web"]
							}`) + "\n",
		},
		{
			name: "analyze microservices new format",
			dir:  "testdata/init/microservices",
			config: Config{
				Analyze:       true,
				EnableJibInit: true,
			},
			expectedOut: strip(`{
									"builders":[
										{"name":"Docker","payload":{"path":"leeroy-app/Dockerfile"}},
										{"name":"Docker","payload":{"path":"leeroy-web/Dockerfile"}}
									],
									"images":[
										{"name":"gcr.io/k8s-skaffold/leeroy-app","foundMatch":false},
										{"name":"gcr.io/k8s-skaffold/leeroy-web","foundMatch":false}]}`) + "\n",
		},
		{
			name: "no error with no manifests in analyze mode with skip-deploy",
			dir:  "testdata/init/hello-no-manifest",

			config: Config{
				Analyze:    true,
				SkipDeploy: true,
				Opts: config.SkaffoldOptions{
					ConfigurationFile: "skaffold.yaml.out",
				},
			},

			expectedOut: strip(`{"dockerfiles":["Dockerfile"]}`),
		},
	}

	for _, test := range tests {
		testutil.Run(t, test.name, func(t *testutil.T) {
			var out bytes.Buffer
			t.Chdir(test.dir)
			err := DoInit(context.TODO(), &out, test.config)
			t.CheckErrorAndDeepEqual(false, err, test.expectedOut, out.String())
		})
	}
}

func strip(s string) string {
	cutString := "\n\t\r"
	stripped := ""
	for _, r := range s {
		if strings.ContainsRune(cutString, r) {
			continue
		}
		stripped = fmt.Sprintf("%s%c", stripped, r)
	}
	return stripped
}

func checkGeneratedConfig(t *testutil.T, dir string) {
	expectedOutput, err := schema.ParseConfig(filepath.Join(dir, "skaffold.yaml"), false)
	t.CheckNoError(err)

	output, err := schema.ParseConfig(filepath.Join(dir, "skaffold.yaml.out"), false)
	t.CheckNoError(err)
	t.CheckDeepEqual(expectedOutput, output)
}
<commit_msg>Fix test expectation<commit_after>/*
Copyright 2020 The Skaffold 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 initializer

import (
	"bytes"
	"context"
	"fmt"
	"os"
	"path/filepath"
	"strings"
	"testing"

	"github.com/GoogleContainerTools/skaffold/pkg/skaffold/config"
	"github.com/GoogleContainerTools/skaffold/pkg/skaffold/schema"
	"github.com/GoogleContainerTools/skaffold/testutil"
)

func TestDoInit(t *testing.T) {
	tests := []struct {
		name      string
		dir       string
		config    Config
		shouldErr bool
	}{
		//TODO: mocked kompose test
		{
			name: "getting-started",
			dir:  "testdata/init/hello",
			config: Config{
				Opts: config.SkaffoldOptions{
					ConfigurationFile: "skaffold.yaml.out",
				},
			},
		},
		{
			name: "ignore existing tags",
			dir:  "testdata/init/ignore-tags",
			config: Config{
				Opts: config.SkaffoldOptions{
					ConfigurationFile: "skaffold.yaml.out",
				},
			},
		},
		{
			name: "microservices (backwards compatibility)",
			dir:  "testdata/init/microservices",
			config: Config{
				CliArtifacts: []string{
					"leeroy-app/Dockerfile=gcr.io/k8s-skaffold/leeroy-app",
					"leeroy-web/Dockerfile=gcr.io/k8s-skaffold/leeroy-web",
				},
				Opts: config.SkaffoldOptions{
					ConfigurationFile: "skaffold.yaml.out",
				},
			},
		},
		{
			name: "microservices",
			dir:  "testdata/init/microservices",
			config: Config{
				CliArtifacts: []string{
					`{"builder":"Docker","payload":{"path":"leeroy-app/Dockerfile"},"image":"gcr.io/k8s-skaffold/leeroy-app"}`,
					`{"builder":"Docker","payload":{"path":"leeroy-web/Dockerfile"},"image":"gcr.io/k8s-skaffold/leeroy-web"}`,
				},
				Opts: config.SkaffoldOptions{
					ConfigurationFile: "skaffold.yaml.out",
				},
			},
		},
		{
			name: "error writing config file",
			dir:  "testdata/init/microservices",

			config: Config{
				CliArtifacts: []string{
					`{"builder":"Docker","payload":{"path":"leeroy-app/Dockerfile"},"image":"gcr.io/k8s-skaffold/leeroy-app"}`,
					`{"builder":"Docker","payload":{"path":"leeroy-web/Dockerfile"},"image":"gcr.io/k8s-skaffold/leeroy-web"}`,
				},
				Opts: config.SkaffoldOptions{
					// erroneous config file as . is a directory
					ConfigurationFile: ".",
				},
			},
			shouldErr: true,
		},
		{
			name: "error no manifests",
			dir:  "testdata/init/hello-no-manifest",

			config: Config{
				Opts: config.SkaffoldOptions{
					ConfigurationFile: "skaffold.yaml.out",
				},
			},
			shouldErr: true,
		},
	}
	for _, test := range tests {
		testutil.Run(t, test.name, func(t *testutil.T) {
			t.Chdir(test.dir)
			// we still need as a "no-prompt" mode
			test.config.Force = true
			err := DoInit(context.TODO(), os.Stdout, test.config)
			t.CheckError(test.shouldErr, err)
			if !test.shouldErr {
				checkGeneratedConfig(t, ".")
			}
		})
	}
}

func TestDoInitAnalyze(t *testing.T) {
	tests := []struct {
		name        string
		dir         string
		config      Config
		expectedOut string
	}{
		{
			name: "analyze microservices",
			dir:  "testdata/init/microservices",
			config: Config{
				Analyze: true,
			},
			expectedOut: strip(`{
							"dockerfiles":["leeroy-app/Dockerfile","leeroy-web/Dockerfile"],
							"images":["gcr.io/k8s-skaffold/leeroy-app","gcr.io/k8s-skaffold/leeroy-web"]
							}`) + "\n",
		},
		{
			name: "analyze microservices new format",
			dir:  "testdata/init/microservices",
			config: Config{
				Analyze:       true,
				EnableJibInit: true,
			},
			expectedOut: strip(`{
									"builders":[
										{"name":"Docker","payload":{"path":"leeroy-app/Dockerfile"}},
										{"name":"Docker","payload":{"path":"leeroy-web/Dockerfile"}}
									],
									"images":[
										{"name":"gcr.io/k8s-skaffold/leeroy-app","foundMatch":false},
										{"name":"gcr.io/k8s-skaffold/leeroy-web","foundMatch":false}]}`) + "\n",
		},
		{
			name: "no error with no manifests in analyze mode with skip-deploy",
			dir:  "testdata/init/hello-no-manifest",

			config: Config{
				Analyze:    true,
				SkipDeploy: true,
				Opts: config.SkaffoldOptions{
					ConfigurationFile: "skaffold.yaml.out",
				},
			},

			expectedOut: strip(`{"dockerfiles":["Dockerfile"]}`) + "\n",
		},
	}

	for _, test := range tests {
		testutil.Run(t, test.name, func(t *testutil.T) {
			var out bytes.Buffer
			t.Chdir(test.dir)
			err := DoInit(context.TODO(), &out, test.config)
			t.CheckErrorAndDeepEqual(false, err, test.expectedOut, out.String())
		})
	}
}

func strip(s string) string {
	cutString := "\n\t\r"
	stripped := ""
	for _, r := range s {
		if strings.ContainsRune(cutString, r) {
			continue
		}
		stripped = fmt.Sprintf("%s%c", stripped, r)
	}
	return stripped
}

func checkGeneratedConfig(t *testutil.T, dir string) {
	expectedOutput, err := schema.ParseConfig(filepath.Join(dir, "skaffold.yaml"), false)
	t.CheckNoError(err)

	output, err := schema.ParseConfig(filepath.Join(dir, "skaffold.yaml.out"), false)
	t.CheckNoError(err)
	t.CheckDeepEqual(expectedOutput, output)
}
<|endoftext|>


<commit_before>package executor

import (
	"bufio"
	"io"
	"log"
)

// bindLoggingPipe spawns a goroutine for passing through logging of the given output pipe.
func bindLoggingPipe(name string, pipe io.Reader, output io.Writer) {
	log.Printf("Started logging %s from function.", name)

	scanner := bufio.NewScanner(pipe)
	logger := log.New(output, log.Prefix(), log.Flags())

	go func() {
		for scanner.Scan() {
			logger.Println(scanner.Text())
		}
		if err := scanner.Err(); err != nil {
			log.Printf("Error scanning %s: %s", name, err.Error())
		}
	}()
}
<commit_msg>Readd the pipe name to logging ouput.<commit_after>package executor

import (
	"bufio"
	"io"
	"log"
)

// bindLoggingPipe spawns a goroutine for passing through logging of the given output pipe.
func bindLoggingPipe(name string, pipe io.Reader, output io.Writer) {
	log.Printf("Started logging %s from function.", name)

	scanner := bufio.NewScanner(pipe)
	logger := log.New(output, log.Prefix(), log.Flags())

	go func() {
		for scanner.Scan() {
			logger.Printf("%s: %s", name, scanner.Text())
		}
		if err := scanner.Err(); err != nil {
			log.Printf("Error scanning %s: %s", name, err.Error())
		}
	}()
}
<|endoftext|>


<commit_before><commit_msg>Updated tests for oglematchers interface change.<commit_after><|endoftext|>


<commit_before>package software_lists

import (
	"fmt"
	"io"
	"strconv"
	"time"
)

type SoftwareList struct {
	ID               string             `json:"id"`
	Name             string             `json:"name"`
	Version          string             `json:"version"`
	Supplier         string             `json:"supplier"`
	ContactName      string             `json:"contact_name"`
	ContactEmail     string             `json:"contact_email"`
	MonitorFrequency string             `json:"monitor_frequency"`
	Status           SoftwareListStatus `json:"status"`
	CreatedAt        time.Time          `json:"created_at"`
	UpdatedAt        time.Time          `json:"updated_at"`
	DeletedAt        *time.Time         `json:"deleted_at"`
	EntryCount       *int               `json:"entry_count"`
	Metrics          Metrics            `json:"metrics"`
	Entries          []Component        `json:"entries"`
	TeamID           string             `json:"team_id"`
	OrgID            string             `json:"org_id"`
	RulesetID        string             `json:"ruleset_id"`
}

type SoftwareListStatus string

const (
	SoftwareListStatusCreated          SoftwareListStatus = "created"
	SoftwareListStatusAutocompletedone SoftwareListStatus = "autocompletedone"
	SoftwareListStatusAllconfirmed     SoftwareListStatus = "allconfirmed"
)

var AllSoftwareListStatus = []SoftwareListStatus{
	SoftwareListStatusCreated,
	SoftwareListStatusAutocompletedone,
	SoftwareListStatusAllconfirmed,
}

func (e SoftwareListStatus) IsValid() bool {
	switch e {
	case SoftwareListStatusCreated, SoftwareListStatusAutocompletedone, SoftwareListStatusAllconfirmed:
		return true
	}
	return false
}

func (e SoftwareListStatus) String() string {
	return string(e)
}

func (e *SoftwareListStatus) UnmarshalGQL(v interface{}) error {
	str, ok := v.(string)
	if !ok {
		return fmt.Errorf("enums must be strings")
	}

	*e = SoftwareListStatus(str)
	if !e.IsValid() {
		return fmt.Errorf("%s is not a valid SoftwareListStatus", str)
	}
	return nil
}

func (e SoftwareListStatus) MarshalGQL(w io.Writer) {
	fmt.Fprint(w, strconv.Quote(e.String()))
}
<commit_msg>Missed one<commit_after>package software_lists

import (
	"fmt"
	"io"
	"strconv"
	"time"
)

type SoftwareInventory struct {
	ID            string         `json:"id"`
	Organization  Metrics        `json:"organization"`
	SoftwareLists []SoftwareList `json:"softwareLists"`
}

type SoftwareList struct {
	ID               string             `json:"id"`
	Name             string             `json:"name"`
	Version          string             `json:"version"`
	Supplier         string             `json:"supplier"`
	ContactName      string             `json:"contact_name"`
	ContactEmail     string             `json:"contact_email"`
	MonitorFrequency string             `json:"monitor_frequency"`
	Status           SoftwareListStatus `json:"status"`
	CreatedAt        time.Time          `json:"created_at"`
	UpdatedAt        time.Time          `json:"updated_at"`
	DeletedAt        *time.Time         `json:"deleted_at"`
	EntryCount       *int               `json:"entry_count"`
	Metrics          Metrics            `json:"metrics"`
	Entries          []Component        `json:"entries"`
	TeamID           string             `json:"team_id"`
	OrgID            string             `json:"org_id"`
	RulesetID        string             `json:"ruleset_id"`
}

type SoftwareListStatus string

const (
	SoftwareListStatusCreated          SoftwareListStatus = "created"
	SoftwareListStatusAutocompletedone SoftwareListStatus = "autocompletedone"
	SoftwareListStatusAllconfirmed     SoftwareListStatus = "allconfirmed"
)

var AllSoftwareListStatus = []SoftwareListStatus{
	SoftwareListStatusCreated,
	SoftwareListStatusAutocompletedone,
	SoftwareListStatusAllconfirmed,
}

func (e SoftwareListStatus) IsValid() bool {
	switch e {
	case SoftwareListStatusCreated, SoftwareListStatusAutocompletedone, SoftwareListStatusAllconfirmed:
		return true
	}
	return false
}

func (e SoftwareListStatus) String() string {
	return string(e)
}

func (e *SoftwareListStatus) UnmarshalGQL(v interface{}) error {
	str, ok := v.(string)
	if !ok {
		return fmt.Errorf("enums must be strings")
	}

	*e = SoftwareListStatus(str)
	if !e.IsValid() {
		return fmt.Errorf("%s is not a valid SoftwareListStatus", str)
	}
	return nil
}

func (e SoftwareListStatus) MarshalGQL(w io.Writer) {
	fmt.Fprint(w, strconv.Quote(e.String()))
}
<|endoftext|>


<commit_before>package daemon

import (
    "reflect"
    "github.com/sevlyar/go-daemon"
    "github.com/Sirupsen/logrus"
    "github.com/BluePecker/JwtAuth/server"
    "github.com/BluePecker/JwtAuth/storage"
    "github.com/BluePecker/JwtAuth/server/router/token"
    "github.com/BluePecker/JwtAuth/server/router"
    "os"
    _ "github.com/BluePecker/JwtAuth/storage/redis"
    //_ "github.com/BluePecker/JwtAuth/storage/ram"
    "fmt"
    "github.com/dgrijalva/jwt-go"
    "time"
)

const (
    TOKEN_TTL = 2 * 3600

    VERSION = "1.0.0"

    ALLOW_LOGIN_NUM = 3
)

type Storage struct {
    Driver     string
    Path       string
    Host       string
    Port       int
    MaxRetries int
    Username   string
    Password   string
    PoolSize   int
    Database   string
}

type Security struct {
    TLS  bool
    Key  string
    Cert string
}

type Options struct {
    PidFile  string
    LogFile  string
    LogLevel string
    Port     int
    Host     string
    Daemon   bool
    Version  bool
    Security Security
    Storage  Storage
}

type Daemon struct {
    Options *Options
    Server  *server.Server
    Storage storage.Driver
    // jwt secret
    Secret  string
}

type (
    CustomClaims struct {
        Device    string `json:"device"`
        UserId    string `json:"user_id"`
        Timestamp int64  `json:"timestamp"`
        Address   string `json:"address"`
        jwt.StandardClaims
    }
)

func (d *Daemon) storageOptionInject(p2 *storage.Option) {
    p1 := &(d.Options.Storage)
    u1 := reflect.ValueOf(p1).Elem()
    u2 := reflect.ValueOf(p2).Elem()

    for seq := 0; seq < u2.NumField(); seq++ {
        item := u2.Type().Field(seq)
        v1 := u1.FieldByName(item.Name)
        v2 := u2.FieldByName(item.Name)
        if v1.IsValid() {
            if v2.Type() == v1.Type() {
                v2.Set(v1)
            }
        }
    }
}

func (d *Daemon) NewStorage() (*storage.Driver, error) {
    option := &storage.Option{}
    d.storageOptionInject(option)
    driver, err := storage.New(d.Options.Storage.Driver, *option)
    return &driver, err
}

func (d *Daemon) NewServer() {
    d.Server = &server.Server{}
}

func (d *Daemon) Listen() {
    if d.Server == nil {
        d.NewServer()
    }

    options := server.Options{
        Host: d.Options.Host,
        Port: d.Options.Port,
    }

    if d.Options.Security.TLS {
        options.Tls = &server.TLS{
            Cert: d.Options.Security.Cert,
            Key: d.Options.Security.Key,
        }
    }

    d.Server.Accept(options)
}

func (d *Daemon) addRouter(routers... router.Router) {
    if d.Server == nil {
        d.NewServer()
    }
    for _, route := range routers {
        d.Server.AddRouter(route)
    }
}

func (d *Daemon) Generate(userId, device, address string) (string, error) {
    Claims := CustomClaims{
        device,
        userId,
        time.Now().Unix(),
        address,
        jwt.StandardClaims{
            ExpiresAt: time.Now().Add(time.Second * TOKEN_TTL).Unix(),
            Issuer: "shuc324@gmail.com",
        },
    }
    Token := jwt.NewWithClaims(jwt.SigningMethodHS256, Claims)
    if Signed, err := Token.SignedString([]byte(d.Secret)); err != nil {
        return "", err
    } else {
        err := d.Storage.LKeep(userId, Signed, ALLOW_LOGIN_NUM, TOKEN_TTL)
        if err != nil {
            return "", err
        }
        return Signed, err
    }
}

func (d *Daemon) Auth(token string) (string, error) {
    Token, err := jwt.ParseWithClaims(token, &CustomClaims{}, func(token *jwt.Token) (interface{}, error) {
        if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
            return nil, fmt.Errorf("Unexpected signing method %v", token.Header["alg"])
        }
        return []byte(d.Secret), nil
    })

    logrus.Info(Token)
    return "", err
}

func (d *Daemon) Upgrade(jwt string) (string, error) {
    // todo
    return "", nil
}

func NewStart(args Options) {
    var err error;

    if args.Version == true {
        fmt.Printf("JwtAuth version %s.\n", VERSION)
        os.Exit(0)
    }

    if args.Daemon == true {
        dCtx := daemon.Context{
            PidFileName: args.PidFile,
            PidFilePerm: 0644,
            LogFilePerm: 0640,
            Umask:       027,
            WorkDir:     "/",
            LogFileName: args.LogFile,
        }

        level, err := logrus.ParseLevel(args.LogLevel)
        if err == nil {
            logrus.SetLevel(level)
            logrus.SetFormatter(&logrus.TextFormatter{
                TimestampFormat: "2006-01-02 15:04:05",
            })
        } else {
            logrus.Fatal(err)
        }
        defer dCtx.Release()

        if child, err := dCtx.Reborn(); err != nil {
            logrus.Fatal(err)
        } else if child != nil {
            return
        }
    }

    Daemon := &Daemon{
        Options: &args,
    }

    Storage, err := Daemon.NewStorage()
    if err != nil {
        logrus.Error(err)
        os.Exit(0)
    }
    Daemon.Storage = *Storage

    Daemon.addRouter(token.NewRouter(Daemon))
    Daemon.Listen()
}<commit_msg>fix bug<commit_after>package daemon

import (
    "reflect"
    "github.com/sevlyar/go-daemon"
    "github.com/Sirupsen/logrus"
    "github.com/BluePecker/JwtAuth/server"
    "github.com/BluePecker/JwtAuth/storage"
    "github.com/BluePecker/JwtAuth/server/router/token"
    "github.com/BluePecker/JwtAuth/server/router"
    "os"
    _ "github.com/BluePecker/JwtAuth/storage/redis"
    //_ "github.com/BluePecker/JwtAuth/storage/ram"
    "fmt"
    "github.com/dgrijalva/jwt-go"
    "time"
)

const (
    TOKEN_TTL = 2 * 3600

    VERSION = "1.0.0"

    ALLOW_LOGIN_NUM = 3
)

type Storage struct {
    Driver     string
    Path       string
    Host       string
    Port       int
    MaxRetries int
    Username   string
    Password   string
    PoolSize   int
    Database   string
}

type Security struct {
    TLS  bool
    Key  string
    Cert string
}

type Options struct {
    PidFile  string
    LogFile  string
    LogLevel string
    Port     int
    Host     string
    Daemon   bool
    Version  bool
    Security Security
    Storage  Storage
}

type Daemon struct {
    Options *Options
    Server  *server.Server
    Storage storage.Driver
    // jwt secret
    Secret  string
}

type (
    CustomClaims struct {
        Device    string `json:"device"`
        UserId    string `json:"user_id"`
        Timestamp int64  `json:"timestamp"`
        Address   string `json:"address"`
        jwt.StandardClaims
    }
)

func (d *Daemon) storageOptionInject(p2 *storage.Option) {
    p1 := &(d.Options.Storage)
    u1 := reflect.ValueOf(p1).Elem()
    u2 := reflect.ValueOf(p2).Elem()

    for seq := 0; seq < u2.NumField(); seq++ {
        item := u2.Type().Field(seq)
        v1 := u1.FieldByName(item.Name)
        v2 := u2.FieldByName(item.Name)
        if v1.IsValid() {
            if v2.Type() == v1.Type() {
                v2.Set(v1)
            }
        }
    }
}

func (d *Daemon) NewStorage() (*storage.Driver, error) {
    option := &storage.Option{}
    d.storageOptionInject(option)
    driver, err := storage.New(d.Options.Storage.Driver, *option)
    return &driver, err
}

func (d *Daemon) NewServer() {
    d.Server = &server.Server{}
}

func (d *Daemon) Listen() {
    if d.Server == nil {
        d.NewServer()
    }

    options := server.Options{
        Host: d.Options.Host,
        Port: d.Options.Port,
    }

    if d.Options.Security.TLS {
        options.Tls = &server.TLS{
            Cert: d.Options.Security.Cert,
            Key: d.Options.Security.Key,
        }
    }

    d.Server.Accept(options)
}

func (d *Daemon) addRouter(routers... router.Router) {
    if d.Server == nil {
        d.NewServer()
    }
    for _, route := range routers {
        d.Server.AddRouter(route)
    }
}

func (d *Daemon) Generate(userId, device, address string) (string, error) {
    Claims := CustomClaims{
        device,
        userId,
        time.Now().Unix(),
        address,
        jwt.StandardClaims{
            ExpiresAt: time.Now().Add(time.Second * TOKEN_TTL).Unix(),
            Issuer: "shuc324@gmail.com",
        },
    }
    Token := jwt.NewWithClaims(jwt.SigningMethodHS256, Claims)
    if Signed, err := Token.SignedString([]byte(d.Secret)); err != nil {
        return "", err
    } else {
        err := d.Storage.LKeep(userId, Signed, ALLOW_LOGIN_NUM, TOKEN_TTL)
        if err != nil {
            return "", err
        }
        return Signed, err
    }
}

func (d *Daemon) Auth(token string) (string, error) {
    Token, err := jwt.ParseWithClaims(token, &CustomClaims{}, func(token *jwt.Token) (interface{}, error) {
        if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
            return nil, fmt.Errorf("Unexpected signing method %v", token.Header["alg"])
        }
        return []byte(d.Secret), nil
    })
    if Claims, ok := Token.Claims.(*CustomClaims); ok && Token.Valid {
        return Claims.UserId, nil
    }
    return "", err
}

func (d *Daemon) Upgrade(jwt string) (string, error) {
    // todo
    return "", nil
}

func NewStart(args Options) {
    var err error;

    if args.Version == true {
        fmt.Printf("JwtAuth version %s.\n", VERSION)
        os.Exit(0)
    }

    if args.Daemon == true {
        dCtx := daemon.Context{
            PidFileName: args.PidFile,
            PidFilePerm: 0644,
            LogFilePerm: 0640,
            Umask:       027,
            WorkDir:     "/",
            LogFileName: args.LogFile,
        }

        level, err := logrus.ParseLevel(args.LogLevel)
        if err == nil {
            logrus.SetLevel(level)
            logrus.SetFormatter(&logrus.TextFormatter{
                TimestampFormat: "2006-01-02 15:04:05",
            })
        } else {
            logrus.Fatal(err)
        }
        defer dCtx.Release()

        if child, err := dCtx.Reborn(); err != nil {
            logrus.Fatal(err)
        } else if child != nil {
            return
        }
    }

    Daemon := &Daemon{
        Options: &args,
    }

    Storage, err := Daemon.NewStorage()
    if err != nil {
        logrus.Error(err)
        os.Exit(0)
    }
    Daemon.Storage = *Storage

    Daemon.addRouter(token.NewRouter(Daemon))
    Daemon.Listen()
}<|endoftext|>


<commit_before>package daemon

import (
	"errors"
	"fmt"
	"os"
	"path"
	"strconv"
	"strings"

	"github.com/hyperhq/hyper/daemon/daemondb"

	"github.com/Sirupsen/logrus"
	"github.com/Unknwon/goconfig"
	docker "github.com/docker/docker/daemon"
	"github.com/docker/docker/daemon/logger/jsonfilelog"
	"github.com/docker/docker/opts"
	flag "github.com/docker/docker/pkg/mflag"
	"github.com/docker/docker/registry"
	"github.com/golang/glog"
	"github.com/hyperhq/hyper/utils"
	"github.com/hyperhq/runv/factory"
	"github.com/hyperhq/runv/hypervisor"
	"github.com/hyperhq/runv/hypervisor/pod"
	"github.com/hyperhq/runv/hypervisor/types"
)

var (
	DefaultResourcePath string = "/var/run/hyper/Pods"
)

type Daemon struct {
	*docker.Daemon
	ID          string
	db          *daemondb.DaemonDB
	PodList     *PodList
	VmList      map[string]*hypervisor.Vm
	Factory     factory.Factory
	Kernel      string
	Initrd      string
	Bios        string
	Cbfs        string
	VboxImage   string
	BridgeIface string
	BridgeIP    string
	Host        string
	Storage     Storage
	Hypervisor  string
	DefaultLog  *pod.PodLogConfig
}

func (daemon *Daemon) Restore() error {
	if daemon.GetPodNum() == 0 {
		return nil
	}

	ch := daemon.db.GetAllPods()
	if ch == nil {
		estr := "Cannot list pods in leveldb"
		glog.Error(estr)
		return errors.New(estr)
	}

	for {
		item, ok := <-ch
		if !ok {
			break
		}
		if item == nil {
			estr := "error during load pods from leveldb"
			glog.Error(estr)
			return errors.New(estr)
		}

		podId := string(item.K[4:])

		glog.V(1).Infof("reloading pod %s with args %s", podId, string(item.V))

		daemon.db.DeletePod(podId)

		p, err := daemon.createPodInternal(podId, string(item.V), true)
		if err != nil {
			glog.Warningf("Got a unexpected error when creating(load) pod %s, %v", podId, err)
			continue
		}

		if err = daemon.AddPod(p, string(item.V)); err != nil {
			//TODO: remove the created
			glog.Warningf("Got a error duriong insert pod %s, %v", p.id, err)
			continue
		}

		vmId, err := daemon.db.GetP2V(podId)
		if err != nil {
			glog.V(1).Infof("no existing VM for pod %s: %v", podId, err)
			continue
		}
		if err := p.AssociateVm(daemon, string(vmId)); err != nil {
			glog.V(1).Info("Some problem during associate vm %s to pod %s, %v", string(vmId), podId, err)
			// continue to next
		}
	}

	if glog.V(3) {
		glog.Infof("%d pod have been loaded", daemon.PodList.CountAll())
		daemon.PodList.Foreach(func(p *Pod) error {
			glog.Infof("container in pod %s status: %v", p.id, p.Status().Containers)
			glog.Infof("container in pod %s spec: %v", p.id, p.spec.Containers)
			return nil
		})
	}

	return nil
}

func NewDaemon(cfg *goconfig.ConfigFile) (*Daemon, error) {
	daemon, err := NewDaemonFromDirectory(cfg)
	if err != nil {
		return nil, err
	}
	return daemon, nil
}

func NewDaemonFromDirectory(cfg *goconfig.ConfigFile) (*Daemon, error) {
	if os.Geteuid() != 0 {
		return nil, fmt.Errorf("The Hyper daemon needs to be run as root")
	}
	if err := checkKernel(); err != nil {
		return nil, err
	}

	kernel, _ := cfg.GetValue(goconfig.DEFAULT_SECTION, "Kernel")
	initrd, _ := cfg.GetValue(goconfig.DEFAULT_SECTION, "Initrd")
	glog.V(0).Infof("The config: kernel=%s, initrd=%s", kernel, initrd)
	vboxImage, _ := cfg.GetValue(goconfig.DEFAULT_SECTION, "Vbox")
	glog.V(0).Infof("The config: vbox image=%s", vboxImage)
	biface, _ := cfg.GetValue(goconfig.DEFAULT_SECTION, "Bridge")
	bridgeip, _ := cfg.GetValue(goconfig.DEFAULT_SECTION, "BridgeIP")
	glog.V(0).Infof("The config: bridge=%s, ip=%s", biface, bridgeip)
	bios, _ := cfg.GetValue(goconfig.DEFAULT_SECTION, "Bios")
	cbfs, _ := cfg.GetValue(goconfig.DEFAULT_SECTION, "Cbfs")
	glog.V(0).Infof("The config: bios=%s, cbfs=%s", bios, cbfs)
	host, _ := cfg.GetValue(goconfig.DEFAULT_SECTION, "Host")

	var tempdir = path.Join(utils.HYPER_ROOT, "run")
	os.Setenv("TMPDIR", tempdir)
	if err := os.MkdirAll(tempdir, 0755); err != nil && !os.IsExist(err) {
		return nil, err
	}

	var realRoot = path.Join(utils.HYPER_ROOT, "lib")
	// Create the root directory if it doesn't exists
	if err := os.MkdirAll(realRoot, 0755); err != nil && !os.IsExist(err) {
		return nil, err
	}

	var (
		db_file = fmt.Sprintf("%s/hyper.db", realRoot)
	)
	db, err := daemondb.NewDaemonDB(db_file)
	if err != nil {
		return nil, err
	}

	daemon := &Daemon{
		ID:          fmt.Sprintf("%d", os.Getpid()),
		db:          db,
		Kernel:      kernel,
		Initrd:      initrd,
		Bios:        bios,
		Cbfs:        cbfs,
		VboxImage:   vboxImage,
		PodList:     NewPodList(),
		VmList:      make(map[string]*hypervisor.Vm),
		Host:        host,
		BridgeIP:    bridgeip,
		BridgeIface: biface,
	}

	daemon.Daemon, err = docker.NewDaemon(dockerCfg, registryCfg)
	if err != nil {
		return nil, err
	}

	// Get the docker daemon info
	sysinfo, err := daemon.Daemon.SystemInfo()
	if err != nil {
		return nil, err
	}
	stor, err := StorageFactory(sysinfo)
	if err != nil {
		return nil, err
	}
	daemon.Storage = stor
	daemon.Storage.Init()

	return daemon, nil
}

var (
	dockerCfg   = &docker.Config{}
	registryCfg = &registry.Service{}
)

func presentInHelp(usage string) string { return usage }
func absentFromHelp(string) string      { return "" }

func InitDockerCfg(mirrors []string, insecureRegistries []string, graphdriver, root string) {
	if dockerCfg.LogConfig.Config == nil {
		dockerCfg.LogConfig.Config = make(map[string]string)
	}

	dockerCfg.LogConfig.Config = make(map[string]string)
	var errhandler flag.ErrorHandling = flag.ContinueOnError
	flags := flag.NewFlagSet("", errhandler)
	dockerCfg.InstallFlags(flags, presentInHelp)

	dockerCfg.GraphDriver = graphdriver
	dockerCfg.Root = root
	dockerCfg.TrustKeyPath = path.Join(root, "keys")

	// disable docker network
	flags.Set("-bridge", "none")
	flags.Set("-iptables", "false")
	flags.Set("-ipmasq", "false")

	// disable log driver
	dockerCfg.LogConfig.Type = "none"

	// debug mode
	if glog.V(3) {
		logrus.SetLevel(logrus.DebugLevel)
	}

	registryOpts := &registry.Options{
		Mirrors:            opts.NewListOpts(nil),
		InsecureRegistries: opts.NewListOpts(nil),
	}
	registryOpts.InstallFlags(flags, absentFromHelp)

	for _, m := range mirrors {
		registryOpts.Mirrors.Set(m)
	}

	for _, ir := range insecureRegistries {
		registryOpts.InsecureRegistries.Set(ir)
	}

	registryCfg = registry.NewService(registryOpts)
}

func (daemon *Daemon) DefaultLogCfg(driver string, cfg map[string]string) {
	if driver == "" {
		driver = jsonfilelog.Name
	}

	daemon.DefaultLog = &pod.PodLogConfig{
		Type:   driver,
		Config: cfg,
	}
}

func (daemon *Daemon) GetPodNum() int64 {
	pods, err := daemon.db.ListPod()
	if err != nil {
		return 0
	}
	return int64(len(pods))
}

func (daemon *Daemon) GetRunningPodNum() int64 {
	return daemon.PodList.CountRunning()
}

func (daemon *Daemon) GetVolumeId(podId, volName string) (int, error) {
	vols, err := daemon.db.ListPodVolumes(podId)
	if err != nil {
		return -1, err
	}

	dev_id := 0
	for _, vol := range vols {
		fields := strings.Split(string(vol), ":")
		if fields[0] == volName {
			dev_id, _ = strconv.Atoi(fields[1])
		}
	}
	return dev_id, nil
}

func (daemon *Daemon) DeleteVolumeId(podId string) error {
	vols, err := daemon.db.ListPodVolumes(podId)
	if err != nil {
		return err
	}
	for _, vol := range vols {
		daemon.Storage.RemoveVolume(podId, vol)
	}
	return daemon.db.DeletePodVolumes(podId)
}

func (daemon *Daemon) WritePodAndContainers(podId string) error {
	p, ok := daemon.PodList.Get(podId)
	if !ok {
		return fmt.Errorf("Cannot find Pod %s to write", podId)
	}

	containers := []string{}
	for _, c := range p.status.Containers {
		containers = append(containers, c.Id)
	}

	return daemon.db.UpdateP2C(podId, containers)
}

func (daemon *Daemon) GetVmByPodId(podId string) (string, error) {
	pod, ok := daemon.PodList.Get(podId)
	if !ok {
		return "", fmt.Errorf("Not found Pod %s", podId)
	}
	return pod.status.Vm, nil
}

func (daemon *Daemon) GetPodByContainer(containerId string) (string, error) {
	if pod, ok := daemon.PodList.GetByContainerId(containerId); ok {
		return pod.id, nil
	} else {
		return "", fmt.Errorf("Can not find that container!")
	}
}

func (daemon *Daemon) GetPodByContainerIdOrName(name string) (pod *Pod, idx int, err error) {
	if pod, idx, ok := daemon.PodList.GetByContainerIdOrName(name); ok {
		return pod, idx, nil
	} else {
		return nil, -1, fmt.Errorf("cannot find container %s", name)
	}
}

func (daemon *Daemon) AddPod(pod *Pod, podArgs string) (err error) {
	// store the UserPod into the db
	if err = daemon.db.UpdatePod(pod.id, []byte(podArgs)); err != nil {
		glog.V(1).Info("Found an error while saving the POD file")
		return
	}
	defer func() {
		if err != nil {
			daemon.db.DeletePod(pod.id)
		}
	}()

	daemon.PodList.Put(pod)
	defer func() {
		if err != nil {
			daemon.PodList.Delete(pod.id)
		}
	}()

	if err = daemon.WritePodAndContainers(pod.id); err != nil {
		glog.V(1).Info("Found an error while saving the Containers info")
		return
	}

	return nil
}

func (daemon *Daemon) RemovePod(podId string) {
	daemon.PodList.Delete(podId)
}

func (daemon *Daemon) AddVm(vm *hypervisor.Vm) {
	daemon.VmList[vm.Id] = vm
}

func (daemon *Daemon) RemoveVm(vmId string) {
	delete(daemon.VmList, vmId)
}

func (daemon *Daemon) DestroyAllVm() error {
	daemon.PodList.Foreach(func(p *Pod) error {
		if _, _, err := daemon.StopPodWithinLock(p, "yes"); err != nil {
			glog.V(1).Infof("fail to stop %s: %v", p.id, err)
		}
		return nil
	})
	return nil
}

func (daemon *Daemon) DestroyAndKeepVm() error {
	for i := 0; i < 3; i++ {
		code, err := daemon.ReleaseAllVms()
		if err != nil && code == types.E_BUSY {
			continue
		} else {
			return err
		}
	}
	return nil
}

func (daemon *Daemon) Shutdown() error {
	glog.V(0).Info("The daemon will be shutdown")
	glog.V(0).Info("Shutdown all VMs")
	for vm := range daemon.VmList {
		daemon.KillVm(vm)
	}
	daemon.db.Close()
	glog.Flush()
	return nil
}

// Now, the daemon can be ran for any linux kernel
func checkKernel() error {
	return nil
}
<commit_msg>add kernel check in hyper<commit_after>package daemon

import (
	"errors"
	"fmt"
	"os"
	"path"
	"strconv"
	"strings"

	"github.com/hyperhq/hyper/daemon/daemondb"

	"github.com/Sirupsen/logrus"
	"github.com/Unknwon/goconfig"
	docker "github.com/docker/docker/daemon"
	"github.com/docker/docker/daemon/logger/jsonfilelog"
	"github.com/docker/docker/opts"
	flag "github.com/docker/docker/pkg/mflag"
	"github.com/docker/docker/pkg/parsers/kernel"
	"github.com/docker/docker/registry"
	"github.com/golang/glog"
	"github.com/hyperhq/hyper/utils"
	"github.com/hyperhq/runv/factory"
	"github.com/hyperhq/runv/hypervisor"
	"github.com/hyperhq/runv/hypervisor/pod"
	"github.com/hyperhq/runv/hypervisor/types"
)

var (
	DefaultResourcePath string = "/var/run/hyper/Pods"
)

type Daemon struct {
	*docker.Daemon
	ID          string
	db          *daemondb.DaemonDB
	PodList     *PodList
	VmList      map[string]*hypervisor.Vm
	Factory     factory.Factory
	Kernel      string
	Initrd      string
	Bios        string
	Cbfs        string
	VboxImage   string
	BridgeIface string
	BridgeIP    string
	Host        string
	Storage     Storage
	Hypervisor  string
	DefaultLog  *pod.PodLogConfig
}

func (daemon *Daemon) Restore() error {
	if daemon.GetPodNum() == 0 {
		return nil
	}

	ch := daemon.db.GetAllPods()
	if ch == nil {
		estr := "Cannot list pods in leveldb"
		glog.Error(estr)
		return errors.New(estr)
	}

	for {
		item, ok := <-ch
		if !ok {
			break
		}
		if item == nil {
			estr := "error during load pods from leveldb"
			glog.Error(estr)
			return errors.New(estr)
		}

		podId := string(item.K[4:])

		glog.V(1).Infof("reloading pod %s with args %s", podId, string(item.V))

		daemon.db.DeletePod(podId)

		p, err := daemon.createPodInternal(podId, string(item.V), true)
		if err != nil {
			glog.Warningf("Got a unexpected error when creating(load) pod %s, %v", podId, err)
			continue
		}

		if err = daemon.AddPod(p, string(item.V)); err != nil {
			//TODO: remove the created
			glog.Warningf("Got a error duriong insert pod %s, %v", p.id, err)
			continue
		}

		vmId, err := daemon.db.GetP2V(podId)
		if err != nil {
			glog.V(1).Infof("no existing VM for pod %s: %v", podId, err)
			continue
		}
		if err := p.AssociateVm(daemon, string(vmId)); err != nil {
			glog.V(1).Info("Some problem during associate vm %s to pod %s, %v", string(vmId), podId, err)
			// continue to next
		}
	}

	if glog.V(3) {
		glog.Infof("%d pod have been loaded", daemon.PodList.CountAll())
		daemon.PodList.Foreach(func(p *Pod) error {
			glog.Infof("container in pod %s status: %v", p.id, p.Status().Containers)
			glog.Infof("container in pod %s spec: %v", p.id, p.spec.Containers)
			return nil
		})
	}

	return nil
}

func NewDaemon(cfg *goconfig.ConfigFile) (*Daemon, error) {
	daemon, err := NewDaemonFromDirectory(cfg)
	if err != nil {
		return nil, err
	}
	return daemon, nil
}

func NewDaemonFromDirectory(cfg *goconfig.ConfigFile) (*Daemon, error) {
	if os.Geteuid() != 0 {
		return nil, fmt.Errorf("The Hyper daemon needs to be run as root")
	}

	// hyper needs Linux kernel 3.8.0+
	if err := checkKernel(3, 8, 0); err != nil {
		return nil, err
	}

	kernel, _ := cfg.GetValue(goconfig.DEFAULT_SECTION, "Kernel")
	initrd, _ := cfg.GetValue(goconfig.DEFAULT_SECTION, "Initrd")
	glog.V(0).Infof("The config: kernel=%s, initrd=%s", kernel, initrd)
	vboxImage, _ := cfg.GetValue(goconfig.DEFAULT_SECTION, "Vbox")
	glog.V(0).Infof("The config: vbox image=%s", vboxImage)
	biface, _ := cfg.GetValue(goconfig.DEFAULT_SECTION, "Bridge")
	bridgeip, _ := cfg.GetValue(goconfig.DEFAULT_SECTION, "BridgeIP")
	glog.V(0).Infof("The config: bridge=%s, ip=%s", biface, bridgeip)
	bios, _ := cfg.GetValue(goconfig.DEFAULT_SECTION, "Bios")
	cbfs, _ := cfg.GetValue(goconfig.DEFAULT_SECTION, "Cbfs")
	glog.V(0).Infof("The config: bios=%s, cbfs=%s", bios, cbfs)
	host, _ := cfg.GetValue(goconfig.DEFAULT_SECTION, "Host")

	var tempdir = path.Join(utils.HYPER_ROOT, "run")
	os.Setenv("TMPDIR", tempdir)
	if err := os.MkdirAll(tempdir, 0755); err != nil && !os.IsExist(err) {
		return nil, err
	}

	var realRoot = path.Join(utils.HYPER_ROOT, "lib")
	// Create the root directory if it doesn't exists
	if err := os.MkdirAll(realRoot, 0755); err != nil && !os.IsExist(err) {
		return nil, err
	}

	var (
		db_file = fmt.Sprintf("%s/hyper.db", realRoot)
	)
	db, err := daemondb.NewDaemonDB(db_file)
	if err != nil {
		return nil, err
	}

	daemon := &Daemon{
		ID:          fmt.Sprintf("%d", os.Getpid()),
		db:          db,
		Kernel:      kernel,
		Initrd:      initrd,
		Bios:        bios,
		Cbfs:        cbfs,
		VboxImage:   vboxImage,
		PodList:     NewPodList(),
		VmList:      make(map[string]*hypervisor.Vm),
		Host:        host,
		BridgeIP:    bridgeip,
		BridgeIface: biface,
	}

	daemon.Daemon, err = docker.NewDaemon(dockerCfg, registryCfg)
	if err != nil {
		return nil, err
	}

	// Get the docker daemon info
	sysinfo, err := daemon.Daemon.SystemInfo()
	if err != nil {
		return nil, err
	}
	stor, err := StorageFactory(sysinfo)
	if err != nil {
		return nil, err
	}
	daemon.Storage = stor
	daemon.Storage.Init()

	return daemon, nil
}

var (
	dockerCfg   = &docker.Config{}
	registryCfg = &registry.Service{}
)

func presentInHelp(usage string) string { return usage }
func absentFromHelp(string) string      { return "" }

func InitDockerCfg(mirrors []string, insecureRegistries []string, graphdriver, root string) {
	if dockerCfg.LogConfig.Config == nil {
		dockerCfg.LogConfig.Config = make(map[string]string)
	}

	dockerCfg.LogConfig.Config = make(map[string]string)
	var errhandler flag.ErrorHandling = flag.ContinueOnError
	flags := flag.NewFlagSet("", errhandler)
	dockerCfg.InstallFlags(flags, presentInHelp)

	dockerCfg.GraphDriver = graphdriver
	dockerCfg.Root = root
	dockerCfg.TrustKeyPath = path.Join(root, "keys")

	// disable docker network
	flags.Set("-bridge", "none")
	flags.Set("-iptables", "false")
	flags.Set("-ipmasq", "false")

	// disable log driver
	dockerCfg.LogConfig.Type = "none"

	// debug mode
	if glog.V(3) {
		logrus.SetLevel(logrus.DebugLevel)
	}

	registryOpts := &registry.Options{
		Mirrors:            opts.NewListOpts(nil),
		InsecureRegistries: opts.NewListOpts(nil),
	}
	registryOpts.InstallFlags(flags, absentFromHelp)

	for _, m := range mirrors {
		registryOpts.Mirrors.Set(m)
	}

	for _, ir := range insecureRegistries {
		registryOpts.InsecureRegistries.Set(ir)
	}

	registryCfg = registry.NewService(registryOpts)
}

func (daemon *Daemon) DefaultLogCfg(driver string, cfg map[string]string) {
	if driver == "" {
		driver = jsonfilelog.Name
	}

	daemon.DefaultLog = &pod.PodLogConfig{
		Type:   driver,
		Config: cfg,
	}
}

func (daemon *Daemon) GetPodNum() int64 {
	pods, err := daemon.db.ListPod()
	if err != nil {
		return 0
	}
	return int64(len(pods))
}

func (daemon *Daemon) GetRunningPodNum() int64 {
	return daemon.PodList.CountRunning()
}

func (daemon *Daemon) GetVolumeId(podId, volName string) (int, error) {
	vols, err := daemon.db.ListPodVolumes(podId)
	if err != nil {
		return -1, err
	}

	dev_id := 0
	for _, vol := range vols {
		fields := strings.Split(string(vol), ":")
		if fields[0] == volName {
			dev_id, _ = strconv.Atoi(fields[1])
		}
	}
	return dev_id, nil
}

func (daemon *Daemon) DeleteVolumeId(podId string) error {
	vols, err := daemon.db.ListPodVolumes(podId)
	if err != nil {
		return err
	}
	for _, vol := range vols {
		daemon.Storage.RemoveVolume(podId, vol)
	}
	return daemon.db.DeletePodVolumes(podId)
}

func (daemon *Daemon) WritePodAndContainers(podId string) error {
	p, ok := daemon.PodList.Get(podId)
	if !ok {
		return fmt.Errorf("Cannot find Pod %s to write", podId)
	}

	containers := []string{}
	for _, c := range p.status.Containers {
		containers = append(containers, c.Id)
	}

	return daemon.db.UpdateP2C(podId, containers)
}

func (daemon *Daemon) GetVmByPodId(podId string) (string, error) {
	pod, ok := daemon.PodList.Get(podId)
	if !ok {
		return "", fmt.Errorf("Not found Pod %s", podId)
	}
	return pod.status.Vm, nil
}

func (daemon *Daemon) GetPodByContainer(containerId string) (string, error) {
	if pod, ok := daemon.PodList.GetByContainerId(containerId); ok {
		return pod.id, nil
	} else {
		return "", fmt.Errorf("Can not find that container!")
	}
}

func (daemon *Daemon) GetPodByContainerIdOrName(name string) (pod *Pod, idx int, err error) {
	if pod, idx, ok := daemon.PodList.GetByContainerIdOrName(name); ok {
		return pod, idx, nil
	} else {
		return nil, -1, fmt.Errorf("cannot find container %s", name)
	}
}

func (daemon *Daemon) AddPod(pod *Pod, podArgs string) (err error) {
	// store the UserPod into the db
	if err = daemon.db.UpdatePod(pod.id, []byte(podArgs)); err != nil {
		glog.V(1).Info("Found an error while saving the POD file")
		return
	}
	defer func() {
		if err != nil {
			daemon.db.DeletePod(pod.id)
		}
	}()

	daemon.PodList.Put(pod)
	defer func() {
		if err != nil {
			daemon.PodList.Delete(pod.id)
		}
	}()

	if err = daemon.WritePodAndContainers(pod.id); err != nil {
		glog.V(1).Info("Found an error while saving the Containers info")
		return
	}

	return nil
}

func (daemon *Daemon) RemovePod(podId string) {
	daemon.PodList.Delete(podId)
}

func (daemon *Daemon) AddVm(vm *hypervisor.Vm) {
	daemon.VmList[vm.Id] = vm
}

func (daemon *Daemon) RemoveVm(vmId string) {
	delete(daemon.VmList, vmId)
}

func (daemon *Daemon) DestroyAllVm() error {
	daemon.PodList.Foreach(func(p *Pod) error {
		if _, _, err := daemon.StopPodWithinLock(p, "yes"); err != nil {
			glog.V(1).Infof("fail to stop %s: %v", p.id, err)
		}
		return nil
	})
	return nil
}

func (daemon *Daemon) DestroyAndKeepVm() error {
	for i := 0; i < 3; i++ {
		code, err := daemon.ReleaseAllVms()
		if err != nil && code == types.E_BUSY {
			continue
		} else {
			return err
		}
	}
	return nil
}

func (daemon *Daemon) Shutdown() error {
	glog.V(0).Info("The daemon will be shutdown")
	glog.V(0).Info("Shutdown all VMs")
	for vm := range daemon.VmList {
		daemon.KillVm(vm)
	}
	daemon.db.Close()
	glog.Flush()
	return nil
}

func checkKernel(k, major, minor int) error {
	leastVersionInfo := kernel.VersionInfo{
		Kernel: k,
		Major:  major,
		Minor:  minor,
	}

	if v, err := kernel.GetKernelVersion(); err != nil {
		return err
	} else {
		if kernel.CompareKernelVersion(*v, leastVersionInfo) < 0 {
			msg := fmt.Sprintf("Your Linux kernel(%d.%d.%d) is too old to support Hyper daemon(%d.%d.%d+)",
				v.Kernel, v.Major, v.Minor, k, major, minor)
			return fmt.Errorf(msg)
		}
		return nil
	}
}
<|endoftext|>


<commit_before>package daemon

import (
	"fmt"
	"io"
	"net"
	"os"
	"os/exec"
	"os/signal"
	"path/filepath"
	"time"

	log "github.com/Sirupsen/logrus"
	"github.com/disorganizer/brig/daemon/proto"
	"github.com/disorganizer/brig/repo"
	"github.com/disorganizer/brig/util/ipfsutil"
	"github.com/disorganizer/brig/util/tunnel"
	protobuf "github.com/gogo/protobuf/proto"
	"golang.org/x/net/context"
)

// Server is a TCP server that executed all commands
// on a single repository. Once the daemon is started, it
// attempts to open the repository, for which a password is needed.
type Server struct {
	// The repo we're working on
	Repo *repo.Repository

	// Handle to `ipfs daemon`
	ipfsDaemon *exec.Cmd

	signals chan os.Signal

	// Root context for this daemon
	ctx context.Context

	// TCP Listener for incoming connections:
	listener net.Listener

	// buffered channel with N places,
	// every active connection holds one.
	maxConnections chan struct{}
}

// Summon creates a new up and running Server instance
func Summon(pwd, repoFolder string, port int) (*Server, error) {
	// Load the on-disk repository:
	log.Infof("Opening repo: %s", repoFolder)
	repository, err := repo.Open(pwd, repoFolder)
	if err != nil {
		log.Error("Could not load repository: ", err)
		return nil, err
	}

	proc, err := ipfsutil.StartDaemon(&ipfsutil.Context{
		Path: filepath.Join(repoFolder, ".brig", "ipfs"),
	})

	if err != nil {
		log.Error("Unable to start ipfs daemon: ", err)
		return nil, err
	}

	// Listen for incoming connections.
	addr := fmt.Sprintf("localhost:%d", port)
	listener, err := net.Listen("tcp", addr)
	if err != nil {
		log.Error("Error listening:", err.Error())
		return nil, err
	}

	// Close the listener when the application closes.
	log.Info("Listening on ", addr)

	ctx, cancel := context.WithCancel(context.Background())
	daemon := &Server{
		Repo:           repository,
		signals:        make(chan os.Signal, 1),
		listener:       listener,
		ipfsDaemon:     proc,
		maxConnections: make(chan struct{}, 20),
		ctx:            ctx,
	}

	go daemon.loop(cancel)
	return daemon, nil
}

// Serve waits until the Server received a quit reason.
func (d *Server) Serve() {
	<-d.ctx.Done()
	d.listener.Close()
	if err := d.ipfsDaemon.Process.Kill(); err != nil {
		log.Errorf("Unable to kill off ipfs daemon: %v", err)
	}

	if err := d.Repo.Close(); err != nil {
		log.Errorf("Unable to close repository: %v", err)
	}
}

// Handle incoming connections:
func (d *Server) loop(cancel context.CancelFunc) {
	// Forward signals to the signals channel:
	signal.Notify(d.signals, os.Interrupt, os.Kill)

	// Reserve at least cap(d.maxConnections)
	for i := 0; i < cap(d.maxConnections); i++ {
		d.maxConnections <- struct{}{}
	}

	for {
		select {
		case <-d.signals:
			// Break the Serve() loop
			cancel()
			return
		case <-d.maxConnections:
			// Listen for an incoming connection.
			deadline := time.Now().Add(500 * time.Millisecond)
			err := d.listener.(*net.TCPListener).SetDeadline(deadline)
			if err != nil {
				log.Errorf("BUG: SetDeadline failed: %v", err)
				return
			}

			conn, err := d.listener.Accept()
			if err != nil && err.(*net.OpError).Timeout() {
				d.maxConnections <- struct{}{}
				continue
			}

			if err != nil {
				log.Errorf("Error in Accept(): %v", err)
				return
			}

			// Handle connections in a new goroutine.
			go d.handleRequest(d.ctx, conn)
		default:
			log.Infof("Max number of connections hit: %d", cap(d.maxConnections))
			time.Sleep(500 * time.Millisecond)
		}
	}
}

// Handles incoming requests:
func (d *Server) handleRequest(ctx context.Context, conn net.Conn) {
	defer conn.Close()

	// Make sure this connection count gets released
	defer func() { d.maxConnections <- struct{}{} }()

	tnl, err := tunnel.NewEllipticTunnel(conn)
	if err != nil {
		log.Error("Tunnel failed", err)
		return
	}

	// Loop until client disconnect or dies otherwise:
	for {
		msg := &proto.Command{}
		if err := recv(tnl, msg); err != nil {
			if err != io.EOF {
				log.Warning("daemon-recv: ", err)
			}
			return
		}

		log.Infof("recv: %s: %v", conn.RemoteAddr().String(), msg)
		d.handleCommand(ctx, msg, tnl)
	}
}

// Handles the actual incoming commands:
func (d *Server) handleCommand(ctx context.Context, cmd *proto.Command, conn io.ReadWriter) {
	// This might be used to enforce timeouts for operations:
	ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
	defer cancel()

	// Prepare a response template
	resp := &proto.Response{}
	resp.ResponseType = cmd.CommandType

	switch *(cmd.CommandType) {
	case proto.MessageType_ADD:
	case proto.MessageType_CAT:
	case proto.MessageType_QUIT:
		resp.Response = protobuf.String("BYE")
		d.signals <- os.Interrupt
	case proto.MessageType_PING:
		resp.Response = protobuf.String("PONG")
	default:
		fmt.Println("Unknown message type.")
		return
	}

	if err := send(conn, resp); err != nil {
		log.Warning("Unable to send message back to client: ", err)
	}
}
<commit_msg>daemon: make maxConnections a bit qitta-friendlier.<commit_after>package daemon

import (
	"fmt"
	"io"
	"net"
	"os"
	"os/exec"
	"os/signal"
	"path/filepath"
	"time"

	log "github.com/Sirupsen/logrus"
	"github.com/disorganizer/brig/daemon/proto"
	"github.com/disorganizer/brig/repo"
	"github.com/disorganizer/brig/util/ipfsutil"
	"github.com/disorganizer/brig/util/tunnel"
	protobuf "github.com/gogo/protobuf/proto"
	"golang.org/x/net/context"
)

const (
	// MaxConnections is the upper limit of clients that may connect to a daemon
	// at the same time. Other client will wait in Accept().
	MaxConnections = 20
)

// This is just here to make the maxConnections prettier.
type allowOneConn struct{}

// Server is a TCP server that executed all commands
// on a single repository. Once the daemon is started, it
// attempts to open the repository, for which a password is needed.
type Server struct {
	// The repo we're working on
	Repo *repo.Repository

	// Handle to `ipfs daemon`
	ipfsDaemon *exec.Cmd

	// signals (external and self triggered) arrive on this channel.
	signals chan os.Signal

	// Root context for this daemon
	ctx context.Context

	// TCP Listener for incoming connections:
	listener net.Listener

	// buffered channel with N places,
	// every active connection holds one.
	maxConnections chan allowOneConn
}

// Summon creates a new up and running Server instance
func Summon(pwd, repoFolder string, port int) (*Server, error) {
	// Load the on-disk repository:
	log.Infof("Opening repo: %s", repoFolder)
	repository, err := repo.Open(pwd, repoFolder)
	if err != nil {
		log.Error("Could not load repository: ", err)
		return nil, err
	}

	proc, err := ipfsutil.StartDaemon(&ipfsutil.Context{
		Path: filepath.Join(repoFolder, ".brig", "ipfs"),
	})

	if err != nil {
		log.Error("Unable to start ipfs daemon: ", err)
		return nil, err
	}

	// Listen for incoming connections.
	addr := fmt.Sprintf("localhost:%d", port)
	listener, err := net.Listen("tcp", addr)
	if err != nil {
		log.Error("Error listening:", err.Error())
		return nil, err
	}

	// Close the listener when the application closes.
	log.Info("Listening on ", addr)

	ctx, cancel := context.WithCancel(context.Background())
	daemon := &Server{
		Repo:           repository,
		signals:        make(chan os.Signal, 1),
		listener:       listener,
		ipfsDaemon:     proc,
		maxConnections: make(chan allowOneConn, MaxConnections),
		ctx:            ctx,
	}

	go daemon.loop(cancel)
	return daemon, nil
}

// Serve waits until the Server received a quit reason.
func (d *Server) Serve() {
	<-d.ctx.Done()
	d.listener.Close()
	if err := d.ipfsDaemon.Process.Kill(); err != nil {
		log.Errorf("Unable to kill off ipfs daemon: %v", err)
	}

	if err := d.Repo.Close(); err != nil {
		log.Errorf("Unable to close repository: %v", err)
	}
}

// Handle incoming connections:
func (d *Server) loop(cancel context.CancelFunc) {
	// Forward signals to the signals channel:
	signal.Notify(d.signals, os.Interrupt, os.Kill)

	// Reserve at least cap(d.maxConnections)
	for i := 0; i < cap(d.maxConnections); i++ {
		d.maxConnections <- allowOneConn{}
	}

	for {
		select {
		case <-d.signals:
			// Break the Serve() loop
			cancel()
			return
		case <-d.maxConnections:
			// Listen for an incoming connection.
			deadline := time.Now().Add(500 * time.Millisecond)
			err := d.listener.(*net.TCPListener).SetDeadline(deadline)
			if err != nil {
				log.Errorf("BUG: SetDeadline failed: %v", err)
				return
			}

			conn, err := d.listener.Accept()
			if err != nil && err.(*net.OpError).Timeout() {
				d.maxConnections <- allowOneConn{}
				continue
			}

			if err != nil {
				log.Errorf("Error in Accept(): %v", err)
				return
			}

			// Handle connections in a new goroutine.
			go d.handleRequest(d.ctx, conn)
		default:
			log.Infof("Max number of connections hit: %d", cap(d.maxConnections))
			time.Sleep(500 * time.Millisecond)
		}
	}
}

// Handles incoming requests:
func (d *Server) handleRequest(ctx context.Context, conn net.Conn) {
	defer conn.Close()

	// Make sure this connection count gets released
	defer func() {
		d.maxConnections <- allowOneConn{}
	}()

	tnl, err := tunnel.NewEllipticTunnel(conn)
	if err != nil {
		log.Error("Tunnel failed", err)
		return
	}

	// Loop until client disconnect or dies otherwise:
	for {
		msg := &proto.Command{}
		if err := recv(tnl, msg); err != nil {
			if err != io.EOF {
				log.Warning("daemon-recv: ", err)
			}
			return
		}

		log.Infof("recv: %s: %v", conn.RemoteAddr().String(), msg)
		d.handleCommand(ctx, msg, tnl)
	}
}

// Handles the actual incoming commands:
func (d *Server) handleCommand(ctx context.Context, cmd *proto.Command, conn io.ReadWriter) {
	// This might be used to enforce timeouts for operations:
	ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
	defer cancel()

	// Prepare a response template
	resp := &proto.Response{}
	resp.ResponseType = cmd.CommandType

	switch *(cmd.CommandType) {
	case proto.MessageType_ADD:
	case proto.MessageType_CAT:
	case proto.MessageType_QUIT:
		resp.Response = protobuf.String("BYE")
		d.signals <- os.Interrupt
	case proto.MessageType_PING:
		resp.Response = protobuf.String("PONG")
	default:
		fmt.Println("Unknown message type.")
		return
	}

	if err := send(conn, resp); err != nil {
		log.Warning("Unable to send message back to client: ", err)
	}
}
<|endoftext|>


<commit_before>package dag

import (
	"fmt"
	"reflect"
	"sync"
	"testing"
	"time"
)

func TestWalker_basic(t *testing.T) {
	var g AcyclicGraph
	g.Add(1)
	g.Add(2)
	g.Connect(BasicEdge(1, 2))

	// Run it a bunch of times since it is timing dependent
	for i := 0; i < 50; i++ {
		var order []interface{}
		w := &Walker{Callback: walkCbRecord(&order)}
		w.Update(&g)

		// Wait
		if err := w.Wait(); err != nil {
			t.Fatalf("err: %s", err)
		}

		// Check
		expected := []interface{}{1, 2}
		if !reflect.DeepEqual(order, expected) {
			t.Fatalf("bad: %#v", order)
		}
	}
}

func TestWalker_updateNilGraph(t *testing.T) {
	var g AcyclicGraph
	g.Add(1)
	g.Add(2)
	g.Connect(BasicEdge(1, 2))

	// Run it a bunch of times since it is timing dependent
	for i := 0; i < 50; i++ {
		var order []interface{}
		w := &Walker{Callback: walkCbRecord(&order)}
		w.Update(&g)
		w.Update(nil)

		// Wait
		if err := w.Wait(); err != nil {
			t.Fatalf("err: %s", err)
		}
	}
}

func TestWalker_error(t *testing.T) {
	var g AcyclicGraph
	g.Add(1)
	g.Add(2)
	g.Add(3)
	g.Add(4)
	g.Connect(BasicEdge(1, 2))
	g.Connect(BasicEdge(2, 3))
	g.Connect(BasicEdge(3, 4))

	// Record function
	var order []interface{}
	recordF := walkCbRecord(&order)

	// Build a callback that delays until we close a channel
	cb := func(v Vertex) error {
		if v == 2 {
			return fmt.Errorf("error!")
		}

		return recordF(v)
	}

	w := &Walker{Callback: cb}
	w.Update(&g)

	// Wait
	if err := w.Wait(); err == nil {
		t.Fatal("expect error")
	}

	// Check
	expected := []interface{}{1}
	if !reflect.DeepEqual(order, expected) {
		t.Fatalf("bad: %#v", order)
	}
}

func TestWalker_newVertex(t *testing.T) {
	// Run it a bunch of times since it is timing dependent
	for i := 0; i < 50; i++ {
		var g AcyclicGraph
		g.Add(1)
		g.Add(2)
		g.Connect(BasicEdge(1, 2))

		var order []interface{}
		w := &Walker{Callback: walkCbRecord(&order)}
		w.Update(&g)

		// Wait a bit
		time.Sleep(10 * time.Millisecond)

		// Update the graph
		g.Add(3)
		w.Update(&g)

		// Update the graph again but with the same vertex
		g.Add(3)
		w.Update(&g)

		// Wait
		if err := w.Wait(); err != nil {
			t.Fatalf("err: %s", err)
		}

		// Check
		expected := []interface{}{1, 2, 3}
		if !reflect.DeepEqual(order, expected) {
			t.Fatalf("bad: %#v", order)
		}
	}
}

func TestWalker_removeVertex(t *testing.T) {
	// Run it a bunch of times since it is timing dependent
	for i := 0; i < 50; i++ {
		var g AcyclicGraph
		g.Add(1)
		g.Add(2)
		g.Connect(BasicEdge(1, 2))

		// Record function
		var order []interface{}
		recordF := walkCbRecord(&order)

		// Build a callback that delays until we close a channel
		var w *Walker
		cb := func(v Vertex) error {
			if v == 1 {
				g.Remove(2)
				w.Update(&g)
			}

			return recordF(v)
		}

		// Add the initial vertices
		w = &Walker{Callback: cb}
		w.Update(&g)

		// Wait
		if err := w.Wait(); err != nil {
			t.Fatalf("err: %s", err)
		}

		// Check
		expected := []interface{}{1}
		if !reflect.DeepEqual(order, expected) {
			t.Fatalf("bad: %#v", order)
		}
	}
}

func TestWalker_newEdge(t *testing.T) {
	// Run it a bunch of times since it is timing dependent
	for i := 0; i < 50; i++ {
		var g AcyclicGraph
		g.Add(1)
		g.Add(2)
		g.Connect(BasicEdge(1, 2))

		// Record function
		var order []interface{}
		recordF := walkCbRecord(&order)

		// Build a callback that delays until we close a channel
		var w *Walker
		cb := func(v Vertex) error {
			if v == 1 {
				g.Add(3)
				g.Connect(BasicEdge(3, 2))
				w.Update(&g)
			}

			return recordF(v)
		}

		// Add the initial vertices
		w = &Walker{Callback: cb}
		w.Update(&g)

		// Wait
		if err := w.Wait(); err != nil {
			t.Fatalf("err: %s", err)
		}

		// Check
		expected := []interface{}{1, 3, 2}
		if !reflect.DeepEqual(order, expected) {
			t.Fatalf("bad: %#v", order)
		}
	}
}

func TestWalker_removeEdge(t *testing.T) {
	// Run it a bunch of times since it is timing dependent
	for i := 0; i < 50; i++ {
		var g AcyclicGraph
		g.Add(1)
		g.Add(2)
		g.Add(3)
		g.Connect(BasicEdge(1, 2))
		g.Connect(BasicEdge(3, 2))

		// Record function
		var order []interface{}
		recordF := walkCbRecord(&order)

		// The way this works is that our original graph forces
		// the order of 1 => 3 => 2. During the execution of 1, we
		// remove the edge forcing 3 before 2. Then, during the execution
		// of 3, we wait on a channel that is only closed by 2, implicitly
		// forcing 2 before 3 via the callback (and not the graph). If
		// 2 cannot execute before 3 (edge removal is non-functional), then
		// this test will timeout.
		var w *Walker
		gateCh := make(chan struct{})
		cb := func(v Vertex) error {
			if v == 1 {
				g.RemoveEdge(BasicEdge(3, 2))
				w.Update(&g)
			}

			if v == 2 {
				close(gateCh)
			}

			if v == 3 {
				select {
				case <-gateCh:
				case <-time.After(50 * time.Millisecond):
					return fmt.Errorf("timeout 3 waiting for 2")
				}
			}

			return recordF(v)
		}

		// Add the initial vertices
		w = &Walker{Callback: cb}
		w.Update(&g)

		// Wait
		if err := w.Wait(); err != nil {
			t.Fatalf("err: %s", err)
		}

		// Check
		expected := []interface{}{1, 2, 3}
		if !reflect.DeepEqual(order, expected) {
			t.Fatalf("bad: %#v", order)
		}
	}
}

// walkCbRecord is a test helper callback that just records the order called.
func walkCbRecord(order *[]interface{}) WalkFunc {
	var l sync.Mutex
	return func(v Vertex) error {
		l.Lock()
		defer l.Unlock()
		*order = append(*order, v)
		return nil
	}
}
<commit_msg>Remove sleep-based concurrency from newVertex test<commit_after>package dag

import (
	"fmt"
	"reflect"
	"sync"
	"testing"
	"time"
)

func TestWalker_basic(t *testing.T) {
	var g AcyclicGraph
	g.Add(1)
	g.Add(2)
	g.Connect(BasicEdge(1, 2))

	// Run it a bunch of times since it is timing dependent
	for i := 0; i < 50; i++ {
		var order []interface{}
		w := &Walker{Callback: walkCbRecord(&order)}
		w.Update(&g)

		// Wait
		if err := w.Wait(); err != nil {
			t.Fatalf("err: %s", err)
		}

		// Check
		expected := []interface{}{1, 2}
		if !reflect.DeepEqual(order, expected) {
			t.Fatalf("bad: %#v", order)
		}
	}
}

func TestWalker_updateNilGraph(t *testing.T) {
	var g AcyclicGraph
	g.Add(1)
	g.Add(2)
	g.Connect(BasicEdge(1, 2))

	// Run it a bunch of times since it is timing dependent
	for i := 0; i < 50; i++ {
		var order []interface{}
		w := &Walker{Callback: walkCbRecord(&order)}
		w.Update(&g)
		w.Update(nil)

		// Wait
		if err := w.Wait(); err != nil {
			t.Fatalf("err: %s", err)
		}
	}
}

func TestWalker_error(t *testing.T) {
	var g AcyclicGraph
	g.Add(1)
	g.Add(2)
	g.Add(3)
	g.Add(4)
	g.Connect(BasicEdge(1, 2))
	g.Connect(BasicEdge(2, 3))
	g.Connect(BasicEdge(3, 4))

	// Record function
	var order []interface{}
	recordF := walkCbRecord(&order)

	// Build a callback that delays until we close a channel
	cb := func(v Vertex) error {
		if v == 2 {
			return fmt.Errorf("error!")
		}

		return recordF(v)
	}

	w := &Walker{Callback: cb}
	w.Update(&g)

	// Wait
	if err := w.Wait(); err == nil {
		t.Fatal("expect error")
	}

	// Check
	expected := []interface{}{1}
	if !reflect.DeepEqual(order, expected) {
		t.Fatalf("bad: %#v", order)
	}
}

func TestWalker_newVertex(t *testing.T) {
	var g AcyclicGraph
	g.Add(1)
	g.Add(2)
	g.Connect(BasicEdge(1, 2))

	// Record function
	var order []interface{}
	recordF := walkCbRecord(&order)
	done2 := make(chan int)

	// Build a callback that notifies us when 2 has been walked
	var w *Walker
	cb := func(v Vertex) error {
		if v == 2 {
			defer func() {
				close(done2)
			}()
		}
		return recordF(v)
	}

	// Add the initial vertices
	w = &Walker{Callback: cb}
	w.Update(&g)

	// if 2 has been visited, the walk is complete so far
	<-done2

	// Update the graph
	g.Add(3)
	w.Update(&g)

	// Update the graph again but with the same vertex
	g.Add(3)
	w.Update(&g)

	// Wait
	if err := w.Wait(); err != nil {
		t.Fatalf("err: %s", err)
	}

	// Check
	expected := []interface{}{1, 2, 3}
	if !reflect.DeepEqual(order, expected) {
		t.Fatalf("bad: %#v", order)
	}
}

func TestWalker_removeVertex(t *testing.T) {
	// Run it a bunch of times since it is timing dependent
	for i := 0; i < 50; i++ {
		var g AcyclicGraph
		g.Add(1)
		g.Add(2)
		g.Connect(BasicEdge(1, 2))

		// Record function
		var order []interface{}
		recordF := walkCbRecord(&order)

		// Build a callback that delays until we close a channel
		var w *Walker
		cb := func(v Vertex) error {
			if v == 1 {
				g.Remove(2)
				w.Update(&g)
			}

			return recordF(v)
		}

		// Add the initial vertices
		w = &Walker{Callback: cb}
		w.Update(&g)

		// Wait
		if err := w.Wait(); err != nil {
			t.Fatalf("err: %s", err)
		}

		// Check
		expected := []interface{}{1}
		if !reflect.DeepEqual(order, expected) {
			t.Fatalf("bad: %#v", order)
		}
	}
}

func TestWalker_newEdge(t *testing.T) {
	// Run it a bunch of times since it is timing dependent
	for i := 0; i < 50; i++ {
		var g AcyclicGraph
		g.Add(1)
		g.Add(2)
		g.Connect(BasicEdge(1, 2))

		// Record function
		var order []interface{}
		recordF := walkCbRecord(&order)

		// Build a callback that delays until we close a channel
		var w *Walker
		cb := func(v Vertex) error {
			if v == 1 {
				g.Add(3)
				g.Connect(BasicEdge(3, 2))
				w.Update(&g)
			}

			return recordF(v)
		}

		// Add the initial vertices
		w = &Walker{Callback: cb}
		w.Update(&g)

		// Wait
		if err := w.Wait(); err != nil {
			t.Fatalf("err: %s", err)
		}

		// Check
		expected := []interface{}{1, 3, 2}
		if !reflect.DeepEqual(order, expected) {
			t.Fatalf("bad: %#v", order)
		}
	}
}

func TestWalker_removeEdge(t *testing.T) {
	// Run it a bunch of times since it is timing dependent
	for i := 0; i < 50; i++ {
		var g AcyclicGraph
		g.Add(1)
		g.Add(2)
		g.Add(3)
		g.Connect(BasicEdge(1, 2))
		g.Connect(BasicEdge(3, 2))

		// Record function
		var order []interface{}
		recordF := walkCbRecord(&order)

		// The way this works is that our original graph forces
		// the order of 1 => 3 => 2. During the execution of 1, we
		// remove the edge forcing 3 before 2. Then, during the execution
		// of 3, we wait on a channel that is only closed by 2, implicitly
		// forcing 2 before 3 via the callback (and not the graph). If
		// 2 cannot execute before 3 (edge removal is non-functional), then
		// this test will timeout.
		var w *Walker
		gateCh := make(chan struct{})
		cb := func(v Vertex) error {
			if v == 1 {
				g.RemoveEdge(BasicEdge(3, 2))
				w.Update(&g)
			}

			if v == 2 {
				close(gateCh)
			}

			if v == 3 {
				select {
				case <-gateCh:
				case <-time.After(50 * time.Millisecond):
					return fmt.Errorf("timeout 3 waiting for 2")
				}
			}

			return recordF(v)
		}

		// Add the initial vertices
		w = &Walker{Callback: cb}
		w.Update(&g)

		// Wait
		if err := w.Wait(); err != nil {
			t.Fatalf("err: %s", err)
		}

		// Check
		expected := []interface{}{1, 2, 3}
		if !reflect.DeepEqual(order, expected) {
			t.Fatalf("bad: %#v", order)
		}
	}
}

// walkCbRecord is a test helper callback that just records the order called.
func walkCbRecord(order *[]interface{}) WalkFunc {
	var l sync.Mutex
	return func(v Vertex) error {
		l.Lock()
		defer l.Unlock()
		*order = append(*order, v)
		return nil
	}
}
<|endoftext|>


<commit_before>/*
Copyright 2017 The Kubernetes 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 transport provides a round tripper capable of caching HTTP responses.
package discovery

import (
	"net/http"
	"path/filepath"

	"github.com/gregjones/httpcache"
	"github.com/gregjones/httpcache/diskcache"
	"github.com/peterbourgon/diskv"
)

type cacheRoundTripper struct {
	rt *httpcache.Transport
}

// newCacheRoundTripper creates a roundtripper that reads the ETag on
// response headers and send the If-None-Match header on subsequent
// corresponding requests.
func newCacheRoundTripper(cacheDir string, rt http.RoundTripper) http.RoundTripper {
	d := diskv.New(diskv.Options{
		BasePath: cacheDir,
		TempDir:  filepath.Join(cacheDir, ".diskv-temp"),
	})
	t := httpcache.NewTransport(diskcache.NewWithDiskv(d))
	t.Transport = rt

	return &cacheRoundTripper{rt: t}
}

func (rt *cacheRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
	return rt.rt.RoundTrip(req)
}

func (rt *cacheRoundTripper) WrappedRoundTripper() http.RoundTripper { return rt.rt.Transport }
<commit_msg>UPSTREAM: 67024: add CancelRequest to discovery round-tripper<commit_after>/*
Copyright 2017 The Kubernetes 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 transport provides a round tripper capable of caching HTTP responses.
package discovery

import (
	"net/http"
	"path/filepath"

	"github.com/golang/glog"
	"github.com/gregjones/httpcache"
	"github.com/gregjones/httpcache/diskcache"
	"github.com/peterbourgon/diskv"
)

type cacheRoundTripper struct {
	rt *httpcache.Transport
}

// newCacheRoundTripper creates a roundtripper that reads the ETag on
// response headers and send the If-None-Match header on subsequent
// corresponding requests.
func newCacheRoundTripper(cacheDir string, rt http.RoundTripper) http.RoundTripper {
	d := diskv.New(diskv.Options{
		BasePath: cacheDir,
		TempDir:  filepath.Join(cacheDir, ".diskv-temp"),
	})
	t := httpcache.NewTransport(diskcache.NewWithDiskv(d))
	t.Transport = rt

	return &cacheRoundTripper{rt: t}
}

func (rt *cacheRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
	return rt.rt.RoundTrip(req)
}

func (rt *cacheRoundTripper) CancelRequest(req *http.Request) {
	type canceler interface {
		CancelRequest(*http.Request)
	}
	if cr, ok := rt.rt.Transport.(canceler); ok {
		cr.CancelRequest(req)
	} else {
		glog.Errorf("CancelRequest not implemented by %T", rt.rt.Transport)
	}
}

func (rt *cacheRoundTripper) WrappedRoundTripper() http.RoundTripper { return rt.rt.Transport }
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"os"
	"os/exec"
	"os/signal"
	"path/filepath"
	"runtime"
	"strings"
	"syscall"

	"github.com/hyperhq/hyper/daemon"
	"github.com/hyperhq/hyper/docker"
	"github.com/hyperhq/hyper/engine"
	"github.com/hyperhq/hyper/lib/docker/pkg/reexec"
	"github.com/hyperhq/hyper/utils"
	"github.com/hyperhq/runv/driverloader"
	"github.com/hyperhq/runv/hypervisor"
	"github.com/hyperhq/runv/lib/glog"

	"github.com/Unknwon/goconfig"
)

func main() {
	if reexec.Init() {
		return
	}

	fnd := flag.Bool("nondaemon", false, "Not daemonize")
	flDisableIptables := flag.Bool("noniptables", false, "Don't enable iptables rules")
	flConfig := flag.String("config", "", "Config file for hyperd")
	flHost := flag.String("host", "", "Host for hyperd")
	flHelp := flag.Bool("help", false, "Print help message for Hyperd daemon")
	glog.Init()
	flag.Usage = func() { printHelp() }
	flag.Parse()
	if *flHelp == true {
		printHelp()
		return
	}

	if !*fnd {
		cmd, err := exec.LookPath(os.Args[0])
		if err != nil {
			fmt.Println("cannot find path of arg0 ", os.Args[0])
			os.Exit(-1)
		}
		cmd, err = filepath.Abs(cmd)
		if err != nil {
			fmt.Println("cannot find absolute path of arg0 ", os.Args[0])
			os.Exit(-1)
		}

		pid, err := utils.Daemonize()
		if err != nil {
			fmt.Println("faile to daemonize hyperd")
			os.Exit(-1)
		}
		if pid > 0 {
			return
		}

		err = syscall.Exec(cmd, append(os.Args, "--nondaemon"), os.Environ())
		if err != nil {
			fmt.Println("fail to exec in nondaemon mode: ", err.Error())
			os.Exit(-1)
		}

		return
	}

	mainDaemon(*flConfig, *flHost, *flDisableIptables)
}

func printHelp() {
	var helpMessage = `Usage:
  %s [OPTIONS]

Application Options:
  --nondaemon            Not daemonize
  --config=""            Configuration for %s
  --v=0                  Log level fro V logs
  --log_dir              Log directory
  --host                 Host address and port for hyperd(such as --host=tcp://127.0.0.1:12345)
  --logtostderr          Log to standard error instead of files
  --alsologtostderr      Log to standard error as well as files

Help Options:
  -h, --help             Show this help message

`
	fmt.Printf(helpMessage, os.Args[0], os.Args[0])
}

func mainDaemon(config, host string, flDisableIptables bool) {
	glog.V(1).Infof("The config file is %s", config)
	if config == "" {
		config = "/etc/hyper/config"
	}
	if _, err := os.Stat(config); err != nil {
		if os.IsNotExist(err) {
			glog.Errorf("Can not find config file(%s)", config)
			return
		}
		glog.Errorf(err.Error())
		return
	}

	os.Setenv("HYPER_CONFIG", config)
	cfg, err := goconfig.LoadConfigFile(config)
	if err != nil {
		glog.Errorf("Read config file (%s) failed, %s", config, err.Error())
		return
	}
	driver, _ := cfg.GetValue(goconfig.DEFAULT_SECTION, "Hypervisor")
	if runtime.GOOS == "darwin" {
		driver = "vbox"
	} else {
		if driver == "" {
			// We need to provide a defaut exec drvier
			var drivers = []string{"kvm", "xen", "vbox"}
			driver = utils.GetAvailableDriver(drivers)
		}
		driver = strings.ToLower(driver)
	}
	if driver == "" || (driver != "kvm" && driver != "xen" && driver != "vbox") {
		fmt.Printf("Please specify the exec driver, such as 'kvm', 'xen' or 'vbox'\n")
		return
	}
	hyperRoot, _ := cfg.GetValue(goconfig.DEFAULT_SECTION, "Root")
	iso, _ := cfg.GetValue(goconfig.DEFAULT_SECTION, "Vbox")

	if hyperRoot == "" {
		hyperRoot = "/var/lib/hyper"
	}
	if _, err := os.Stat(hyperRoot); err != nil {
		if err := os.MkdirAll(hyperRoot, 0755); err != nil {
			glog.Errorf(err.Error())
			return
		}
	}

	utils.SetHyperEnv(fmt.Sprintf("%s/.hyperconfig", os.Getenv("HOME")), hyperRoot, iso)
	eng := engine.New(config)
	docker.Init()

	d, err := daemon.NewDaemon(eng)
	if err != nil {
		glog.Errorf("The hyperd create failed, %s\n", err.Error())
		return
	}

	if hypervisor.HDriver, err = driverloader.Probe(driver); err != nil {
		glog.Errorf("%s\n", err.Error())
		return
	}
	d.Hypervisor = driver

	disableIptables := cfg.MustBool(goconfig.DEFAULT_SECTION, "DisableIptables", false)
	if err = hypervisor.InitNetwork(d.BridgeIface, d.BridgeIP, disableIptables || flDisableIptables); err != nil {
		glog.Errorf("InitNetwork failed, %s\n", err.Error())
		return
	}

	// Set the daemon object as the global varibal
	// which will be used for puller and builder
	utils.SetDaemon(d)
	if err := d.DockerCli.Setup(); err != nil {
		glog.Error(err.Error())
		return
	}

	stopAll := make(chan os.Signal, 1)
	signal.Notify(stopAll, syscall.SIGINT, syscall.SIGTERM)
	stop := make(chan os.Signal, 1)
	signal.Notify(stop, syscall.SIGHUP)

	// Install the accepted jobs
	if err := d.Install(eng); err != nil {
		glog.Errorf("The hyperd install failed, %s\n", err.Error())
		return
	}

	glog.V(0).Infof("Hyper daemon: %s %s\n",
		utils.VERSION,
		utils.GITCOMMIT,
	)

	// after the daemon is done setting up we can tell the api to start
	// accepting connections
	if err := eng.Job("acceptconnections").Run(); err != nil {
		glog.Error("the acceptconnections job run failed!\n")
		return
	}
	defaultHost := []string{}
	if host != "" {
		defaultHost = append(defaultHost, host)
	}
	defaultHost = append(defaultHost, "unix:///var/run/hyper.sock")
	if d.Host != "" {
		defaultHost = append(defaultHost, d.Host)
	}

	job := eng.Job("serveapi", defaultHost...)

	// The serve API job never exits unless an error occurs
	// We need to start it as a goroutine and wait on it so
	// daemon doesn't exit
	serveAPIWait := make(chan error)
	go func() {
		if err := job.Run(); err != nil {
			glog.Errorf("ServeAPI error: %v\n", err)
			serveAPIWait <- err
			return
		}
		serveAPIWait <- nil
	}()

	glog.V(0).Info("Daemon has completed initialization\n")

	if err := d.Restore(); err != nil {
		glog.Warningf("Fail to restore the previous VM")
		return
	}

	// Daemon is fully initialized and handling API traffic
	// Wait for serve API job to complete
	select {
	case errAPI := <-serveAPIWait:
		// If we have an error here it is unique to API (as daemonErr would have
		// exited the daemon process above)
		eng.Shutdown()
		if errAPI != nil {
			glog.Warningf("Shutting down due to ServeAPI error: %v\n", errAPI)
		}
		break
	case <-stop:
		d.DestroyAndKeepVm()
		eng.Shutdown()
		break
	case <-stopAll:
		d.DestroyAllVm()
		eng.Shutdown()
		break
	}
}
<commit_msg>probe the hypervisor's driver to get default driver<commit_after>package main

import (
	"flag"
	"fmt"
	"os"
	"os/exec"
	"os/signal"
	"path/filepath"
	"runtime"
	"strings"
	"syscall"

	"github.com/hyperhq/hyper/daemon"
	"github.com/hyperhq/hyper/docker"
	"github.com/hyperhq/hyper/engine"
	"github.com/hyperhq/hyper/lib/docker/pkg/reexec"
	"github.com/hyperhq/hyper/utils"
	"github.com/hyperhq/runv/driverloader"
	"github.com/hyperhq/runv/hypervisor"
	"github.com/hyperhq/runv/lib/glog"

	"github.com/Unknwon/goconfig"
)

func main() {
	if reexec.Init() {
		return
	}

	fnd := flag.Bool("nondaemon", false, "Not daemonize")
	flDisableIptables := flag.Bool("noniptables", false, "Don't enable iptables rules")
	flConfig := flag.String("config", "", "Config file for hyperd")
	flHost := flag.String("host", "", "Host for hyperd")
	flHelp := flag.Bool("help", false, "Print help message for Hyperd daemon")
	glog.Init()
	flag.Usage = func() { printHelp() }
	flag.Parse()
	if *flHelp == true {
		printHelp()
		return
	}

	if !*fnd {
		cmd, err := exec.LookPath(os.Args[0])
		if err != nil {
			fmt.Println("cannot find path of arg0 ", os.Args[0])
			os.Exit(-1)
		}
		cmd, err = filepath.Abs(cmd)
		if err != nil {
			fmt.Println("cannot find absolute path of arg0 ", os.Args[0])
			os.Exit(-1)
		}

		pid, err := utils.Daemonize()
		if err != nil {
			fmt.Println("faile to daemonize hyperd")
			os.Exit(-1)
		}
		if pid > 0 {
			return
		}

		err = syscall.Exec(cmd, append(os.Args, "--nondaemon"), os.Environ())
		if err != nil {
			fmt.Println("fail to exec in nondaemon mode: ", err.Error())
			os.Exit(-1)
		}

		return
	}

	mainDaemon(*flConfig, *flHost, *flDisableIptables)
}

func printHelp() {
	var helpMessage = `Usage:
  %s [OPTIONS]

Application Options:
  --nondaemon            Not daemonize
  --config=""            Configuration for %s
  --v=0                  Log level fro V logs
  --log_dir              Log directory
  --host                 Host address and port for hyperd(such as --host=tcp://127.0.0.1:12345)
  --logtostderr          Log to standard error instead of files
  --alsologtostderr      Log to standard error as well as files

Help Options:
  -h, --help             Show this help message

`
	fmt.Printf(helpMessage, os.Args[0], os.Args[0])
}

func mainDaemon(config, host string, flDisableIptables bool) {
	glog.V(1).Infof("The config file is %s", config)
	if config == "" {
		config = "/etc/hyper/config"
	}
	if _, err := os.Stat(config); err != nil {
		if os.IsNotExist(err) {
			glog.Errorf("Can not find config file(%s)", config)
			return
		}
		glog.Errorf(err.Error())
		return
	}

	os.Setenv("HYPER_CONFIG", config)
	cfg, err := goconfig.LoadConfigFile(config)
	if err != nil {
		glog.Errorf("Read config file (%s) failed, %s", config, err.Error())
		return
	}

	hyperRoot, _ := cfg.GetValue(goconfig.DEFAULT_SECTION, "Root")
	iso, _ := cfg.GetValue(goconfig.DEFAULT_SECTION, "Vbox")

	if hyperRoot == "" {
		hyperRoot = "/var/lib/hyper"
	}
	if _, err := os.Stat(hyperRoot); err != nil {
		if err := os.MkdirAll(hyperRoot, 0755); err != nil {
			glog.Errorf(err.Error())
			return
		}
	}

	utils.SetHyperEnv(fmt.Sprintf("%s/.hyperconfig", os.Getenv("HOME")), hyperRoot, iso)
	eng := engine.New(config)
	docker.Init()

	d, err := daemon.NewDaemon(eng)
	if err != nil {
		glog.Errorf("The hyperd create failed, %s\n", err.Error())
		return
	}

	driver, _ := cfg.GetValue(goconfig.DEFAULT_SECTION, "Hypervisor")
	if runtime.GOOS == "darwin" {
		driver = "vbox"
		if hypervisor.HDriver, err = driverloader.Probe(driver); err != nil {
			glog.Errorf("%s\n", err.Error())
			return
		}
	} else {
		if driver == "" {
			// We need to provide a defaut exec drvier
			var drivers = []string{"xen", "kvm", "vbox"}
			for _, dri := range drivers {
				driver = strings.ToLower(dri)
				if hypervisor.HDriver, err = driverloader.Probe(driver); err != nil {
					glog.Warningf("%s\n", err.Error())
					continue
				} else {
					break
				}
			}
		}
		if driver == "" || (driver != "kvm" && driver != "xen" && driver != "vbox") {
			glog.Errorf("Please specify the exec driver, such as 'kvm', 'xen' or 'vbox'\n")
			return
		}
	}
	d.Hypervisor = driver
	glog.Infof("The hypervisor's driver is %s", driver)

	disableIptables := cfg.MustBool(goconfig.DEFAULT_SECTION, "DisableIptables", false)
	if err = hypervisor.InitNetwork(d.BridgeIface, d.BridgeIP, disableIptables || flDisableIptables); err != nil {
		glog.Errorf("InitNetwork failed, %s\n", err.Error())
		return
	}

	// Set the daemon object as the global varibal
	// which will be used for puller and builder
	utils.SetDaemon(d)
	if err := d.DockerCli.Setup(); err != nil {
		glog.Error(err.Error())
		return
	}

	stopAll := make(chan os.Signal, 1)
	signal.Notify(stopAll, syscall.SIGINT, syscall.SIGTERM)
	stop := make(chan os.Signal, 1)
	signal.Notify(stop, syscall.SIGHUP)

	// Install the accepted jobs
	if err := d.Install(eng); err != nil {
		glog.Errorf("The hyperd install failed, %s\n", err.Error())
		return
	}

	glog.V(0).Infof("Hyper daemon: %s %s\n",
		utils.VERSION,
		utils.GITCOMMIT,
	)

	// after the daemon is done setting up we can tell the api to start
	// accepting connections
	if err := eng.Job("acceptconnections").Run(); err != nil {
		glog.Error("the acceptconnections job run failed!\n")
		return
	}
	defaultHost := []string{}
	if host != "" {
		defaultHost = append(defaultHost, host)
	}
	defaultHost = append(defaultHost, "unix:///var/run/hyper.sock")
	if d.Host != "" {
		defaultHost = append(defaultHost, d.Host)
	}

	job := eng.Job("serveapi", defaultHost...)

	// The serve API job never exits unless an error occurs
	// We need to start it as a goroutine and wait on it so
	// daemon doesn't exit
	serveAPIWait := make(chan error)
	go func() {
		if err := job.Run(); err != nil {
			glog.Errorf("ServeAPI error: %v\n", err)
			serveAPIWait <- err
			return
		}
		serveAPIWait <- nil
	}()

	glog.V(0).Info("Daemon has completed initialization\n")

	if err := d.Restore(); err != nil {
		glog.Warningf("Fail to restore the previous VM")
		return
	}

	// Daemon is fully initialized and handling API traffic
	// Wait for serve API job to complete
	select {
	case errAPI := <-serveAPIWait:
		// If we have an error here it is unique to API (as daemonErr would have
		// exited the daemon process above)
		eng.Shutdown()
		if errAPI != nil {
			glog.Warningf("Shutting down due to ServeAPI error: %v\n", errAPI)
		}
		break
	case <-stop:
		d.DestroyAndKeepVm()
		eng.Shutdown()
		break
	case <-stopAll:
		d.DestroyAllVm()
		eng.Shutdown()
		break
	}
}
<|endoftext|>