func initializeDbObject(d *Daemon) (*db.Dump, error) {
	logger.Info("Initializing local database")
	// Rename the old database name if needed.
	if shared.PathExists(d.os.LegacyLocalDatabasePath()) {
		if shared.PathExists(d.os.LocalDatabasePath()) {
			return nil, fmt.Errorf("Both legacy and new local database files exists")
		}
		logger.Info("Renaming local database file from lxd.db to database/local.db")
		err := os.Rename(d.os.LegacyLocalDatabasePath(), d.os.LocalDatabasePath())
		if err != nil {
			return nil, errors.Wrap(err, "Failed to rename legacy local database file")
		}
	}

	// NOTE: we use the legacyPatches parameter to run a few
	// legacy non-db updates that were in place before the
	// patches mechanism was introduced in lxd/patches.go. The
	// rest of non-db patches will be applied separately via
	// patchesApplyAll. See PR #3322 for more details.
	legacy := map[int]*db.LegacyPatch{}
	for i, patch := range legacyPatches {
		legacy[i] = &db.LegacyPatch{
			Hook: func(node *sql.DB) error {
				// FIXME: Use the low-level *node* SQL db as backend for both the
				//        db.Node and db.Cluster objects, since at this point we
				//        haven't migrated the data to the cluster database yet.
				cluster := d.cluster
				defer func() {
					d.cluster = cluster
				}()
				d.db = db.ForLegacyPatches(node)
				d.cluster = db.ForLocalInspection(node)
				return patch(d)
			},
		}
	}
	for _, i := range legacyPatchesNeedingDB {
		legacy[i].NeedsDB = true
	}

	// Hook to run when the local database is created from scratch. It will
	// create the default profile and mark all patches as applied.
	freshHook := func(db *db.Node) error {
		for _, patchName := range patchesGetNames() {
			err := db.PatchesMarkApplied(patchName)
			if err != nil {
				return err
			}
		}
		return nil
	}
	var err error
	var dump *db.Dump
	d.db, dump, err = db.OpenNode(filepath.Join(d.os.VarDir, "database"), freshHook, legacy)
	if err != nil {
		return nil, fmt.Errorf("Error creating database: %s", err)
	}

	return dump, nil
}

// Create a database connection and perform any updates needed.

Create a database connection and perform any updates needed .


func WriteJSON(w http.ResponseWriter, body interface{}, debug bool) error {
	var output io.Writer
	var captured *bytes.Buffer

	output = w
	if debug {
		captured = &bytes.Buffer{}
		output = io.MultiWriter(w, captured)
	}

	err := json.NewEncoder(output).Encode(body)

	if captured != nil {
		shared.DebugJson(captured)
	}

	return err
}

func WriteJSON ( w http . ResponseWriter , body interface { } , debug bool ) error { var output io . Writer var captured * bytes . Buffer output = w if debug { captured = & bytes . Buffer { } output = io . MultiWriter ( w , captured ) } err := json . NewEncoder ( output ) . Encode ( body ) if captured != nil { shared . DebugJson ( captured ) } return err }

// WriteJSON encodes the body as JSON and sends it back to the client


func EtagHash(data interface{}) (string, error) {
	etag := sha256.New()
	err := json.NewEncoder(etag).Encode(data)
	if err != nil {
		return "", err
	}

	return fmt.Sprintf("%x", etag.Sum(nil)), nil
}

func EtagHash ( data interface { } ) ( string , error ) { etag := sha256 . New ( ) err := json . NewEncoder ( etag ) . Encode ( data ) if err != nil { return " " , err } return fmt . Sprintf ( " " , etag . Sum ( nil ) ) , nil }

// EtagHash hashes the provided data and returns the sha256


func EtagCheck(r *http.Request, data interface{}) error {
	match := r.Header.Get("If-Match")
	if match == "" {
		return nil
	}

	hash, err := EtagHash(data)
	if err != nil {
		return err
	}

	if hash != match {
		return fmt.Errorf("ETag doesn't match: %s vs %s", hash, match)
	}

	return nil
}

func EtagCheck ( r * http . Request , data interface { } ) error { match := r . Header . Get ( " " ) if match == " " { return nil } hash , err := EtagHash ( data ) if err != nil { return err } if hash != match { return fmt . Errorf ( " " , hash , match ) } return nil }

// EtagCheck validates the hash of the current state with the hash
// provided by the client

EtagCheck validates the hash of the current state with the hash provided by the client


func HTTPClient(certificate string, proxy proxyFunc) (*http.Client, error) {
	var err error
	var cert *x509.Certificate

	if certificate != "" {
		certBlock, _ := pem.Decode([]byte(certificate))
		if certBlock == nil {
			return nil, fmt.Errorf("Invalid certificate")
		}

		cert, err = x509.ParseCertificate(certBlock.Bytes)
		if err != nil {
			return nil, err
		}
	}

	tlsConfig, err := shared.GetTLSConfig("", "", "", cert)
	if err != nil {
		return nil, err
	}

	tr := &http.Transport{
		TLSClientConfig:   tlsConfig,
		Dial:              shared.RFC3493Dialer,
		Proxy:             proxy,
		DisableKeepAlives: true,
	}

	myhttp := http.Client{
		Transport: tr,
	}

	// Setup redirect policy
	myhttp.CheckRedirect = func(req *http.Request, via []*http.Request) error {
		// Replicate the headers
		req.Header = via[len(via)-1].Header

		return nil
	}

	return &myhttp, nil
}

func
HTTPClient
(
certificate
string
,
proxy
proxyFunc
)
(
*
http
.
Client
,
error
)
{
var
err
error
var
cert
*
x509
.
Certificate
if
certificate
!=
"
"
{
certBlock
,
_
:=
pem
.
Decode
(
[
]
byte
(
certificate
)
)
if
certBlock
==
{
return
,
fmt
.
Errorf
(
"
"
)
}
cert
,
err
=
x509
.
ParseCertificate
(
certBlock
.
Bytes
)
if
err
!=
{
return
,
err
}
}
tlsConfig
,
err
:=
shared
.
GetTLSConfig
(
"
"
,
"
"
,
"
"
,
cert
)
if
err
!=
{
return
,
err
}
tr
:=
&
http
.
Transport
{
TLSClientConfig
:
tlsConfig
,
Dial
:
shared
.
RFC3493Dialer
,
Proxy
:
proxy
,
DisableKeepAlives
:
true
,
}
myhttp
:=
http
.
Client
{
Transport
:
tr
,
}
// Setup redirect policy
myhttp
.
CheckRedirect
=
func
(
req
*
http
.
Request
,
via
[
]
*
http
.
Request
)
error
{
// Replicate the headers
req
.
Header
=
via
[
len
(
via
)
1
]
.
Header
return
}
return
&
myhttp
,
}

// HTTPClient returns an http.Client using the given certificate and proxy.

HTTPClient returns an http . Client using the given certificate and proxy .


func IsRecursionRequest(r *http.Request) bool {
	recursionStr := r.FormValue("recursion")

	recursion, err := strconv.Atoi(recursionStr)
	if err != nil {
		return false
	}

	return recursion != 0
}

func IsRecursionRequest ( r * http . Request ) bool { recursionStr := r . FormValue ( " " ) recursion , err := strconv . Atoi ( recursionStr ) if err != nil { return false } return recursion != 0 }

// IsRecursionRequest checks whether the given HTTP request is marked with the
// "recursion" flag in its form values.

IsRecursionRequest checks whether the given HTTP request is marked with the recursion flag in its form values .


func GetListeners(start int) []net.Listener {
	defer func() {
		os.Unsetenv("LISTEN_PID")
		os.Unsetenv("LISTEN_FDS")
	}()

	pid, err := strconv.Atoi(os.Getenv("LISTEN_PID"))
	if err != nil {
		return nil
	}

	if pid != os.Getpid() {
		return nil
	}

	fds, err := strconv.Atoi(os.Getenv("LISTEN_FDS"))
	if err != nil {
		return nil
	}

	listeners := []net.Listener{}

	for i := start; i < start+fds; i++ {
		syscall.CloseOnExec(i)

		file := os.NewFile(uintptr(i), fmt.Sprintf("inherited-fd%d", i))
		listener, err := net.FileListener(file)
		if err != nil {
			continue
		}

		listeners = append(listeners, listener)
	}

	return listeners
}

func GetListeners ( start int ) [ ] net . Listener { defer func ( ) { os . Unsetenv ( " " ) os . Unsetenv ( " " ) } ( ) pid , err := strconv . Atoi ( os . Getenv ( " " ) ) if err != nil { return nil } if pid != os . Getpid ( ) { return nil } fds , err := strconv . Atoi ( os . Getenv ( " " ) ) if err != nil { return nil } listeners := [ ] net . Listener { } for i := start ; i < start + fds ; i ++ { syscall . CloseOnExec ( i ) file := os . NewFile ( uintptr ( i ) , fmt . Sprintf ( " " , i ) ) listener , err := net . FileListener ( file ) if err != nil { continue } listeners = append ( listeners , listener ) } return listeners }

// GetListeners returns the socket-activated network listeners, if any.
//
// The 'start' parameter must be SystemdListenFDsStart, except in unit tests,
// see the docstring of SystemdListenFDsStart below.

GetListeners returns the socket - activated network listeners if any . The start parameter must be SystemdListenFDsStart except in unit tests see the docstring of SystemdListenFDsStart below .


func internalSQLGet(d *Daemon, r *http.Request) Response {
	database := r.FormValue("database")

	if !shared.StringInSlice(database, []string{"local", "global"}) {
		return BadRequest(fmt.Errorf("Invalid database"))
	}

	schemaFormValue := r.FormValue("schema")
	schemaOnly, err := strconv.Atoi(schemaFormValue)
	if err != nil {
		schemaOnly = 0
	}

	var schema string
	var db *sql.DB
	if database == "global" {
		db = d.cluster.DB()
		schema = cluster.FreshSchema()
	} else {
		db = d.db.DB()
		schema = node.FreshSchema()
	}

	tx, err := db.Begin()
	if err != nil {
		return SmartError(errors.Wrap(err, "failed to start transaction"))
	}
	defer tx.Rollback()
	dump, err := query.Dump(tx, schema, schemaOnly == 1)
	if err != nil {
		return SmartError(errors.Wrapf(err, "failed dump database %s", database))
	}
	return SyncResponse(true, internalSQLDump{Text: dump})
}

func internalSQLGet ( d * Daemon , r * http . Request ) Response { database := r . FormValue ( " " ) if ! shared . StringInSlice ( database , [ ] string { " " , " " } ) { return BadRequest ( fmt . Errorf ( " " ) ) } schemaFormValue := r . FormValue ( " " ) schemaOnly , err := strconv . Atoi ( schemaFormValue ) if err != nil { schemaOnly = 0 } var schema string var db * sql . DB if database == " " { db = d . cluster . DB ( ) schema = cluster . FreshSchema ( ) } else { db = d . db . DB ( ) schema = node . FreshSchema ( ) } tx , err := db . Begin ( ) if err != nil { return SmartError ( errors . Wrap ( err , " " ) ) } defer tx . Rollback ( ) dump , err := query . Dump ( tx , schema , schemaOnly == 1 ) if err != nil { return SmartError ( errors . Wrapf ( err , " " , database ) ) } return SyncResponse ( true , internalSQLDump { Text : dump } ) }


func internalSQLPost(d *Daemon, r *http.Request) Response {
	req := &internalSQLQuery{}
	// Parse the request.
	err := json.NewDecoder(r.Body).Decode(&req)
	if err != nil {
		return BadRequest(err)
	}

	if !shared.StringInSlice(req.Database, []string{"local", "global"}) {
		return BadRequest(fmt.Errorf("Invalid database"))
	}

	if req.Query == "" {
		return BadRequest(fmt.Errorf("No query provided"))
	}

	var db *sql.DB
	if req.Database == "global" {
		db = d.cluster.DB()
	} else {
		db = d.db.DB()
	}

	batch := internalSQLBatch{}

	if req.Query == ".sync" {
		d.gateway.Sync()
		return SyncResponse(true, batch)
	}

	for _, query := range strings.Split(req.Query, ";") {
		query = strings.TrimLeft(query, " ")

		if query == "" {
			continue
		}

		result := internalSQLResult{}

		tx, err := db.Begin()
		if err != nil {
			return SmartError(err)
		}

		if strings.HasPrefix(strings.ToUpper(query), "SELECT") {
			err = internalSQLSelect(tx, query, &result)
			tx.Rollback()
		} else {
			err = internalSQLExec(tx, query, &result)
			if err != nil {
				tx.Rollback()
			} else {
				err = tx.Commit()
			}
		}
		if err != nil {
			return SmartError(err)
		}

		batch.Results = append(batch.Results, result)
	}

	return SyncResponse(true, batch)
}

func
internalSQLPost
(
d
*
Daemon
,
r
*
http
.
Request
)
Response
{
req
:=
&
internalSQLQuery
{
}
// Parse the request.
err
:=
json
.
NewDecoder
(
r
.
Body
)
.
Decode
(
&
req
)
if
err
!=
{
return
BadRequest
(
err
)
}
if
!
shared
.
StringInSlice
(
req
.
Database
,
[
]
string
{
"
"
,
"
"
}
)
{
return
BadRequest
(
fmt
.
Errorf
(
"
"
)
)
}
if
req
.
Query
==
"
"
{
return
BadRequest
(
fmt
.
Errorf
(
"
"
)
)
}
var
db
*
sql
.
DB
if
req
.
Database
==
"
"
{
db
=
d
.
cluster
.
DB
(
)
}
else
{
db
=
d
.
db
.
DB
(
)
}
batch
:=
internalSQLBatch
{
}
if
req
.
Query
==
"
"
{
d
.
gateway
.
Sync
(
)
return
SyncResponse
(
true
,
batch
)
}
for
_
,
query
:=
range
strings
.
Split
(
req
.
Query
,
"
"
)
{
query
=
strings
.
TrimLeft
(
query
,
"
"
)
if
query
==
"
"
{
continue
}
result
:=
internalSQLResult
{
}
tx
,
err
:=
db
.
Begin
(
)
if
err
!=
{
return
SmartError
(
err
)
}
if
strings
.
HasPrefix
(
strings
.
ToUpper
(
query
)
,
"
"
)
{
err
=
internalSQLSelect
(
tx
,
query
,
&
result
)
tx
.
Rollback
(
)
}
else
{
err
=
internalSQLExec
(
tx
,
query
,
&
result
)
if
err
!=
{
tx
.
Rollback
(
)
}
else
{
err
=
tx
.
Commit
(
)
}
}
if
err
!=
{
return
SmartError
(
err
)
}
batch
.
Results
=
append
(
batch
.
Results
,
result
)
}
return
SyncResponse
(
true
,
batch
)
}


func (c *CertInfo) PublicKey() []byte {
	data := c.KeyPair().Certificate[0]
	return pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: data})
}

func ( c * CertInfo ) PublicKey ( ) [ ] byte { data := c . KeyPair ( ) . Certificate [ 0 ] return pem . EncodeToMemory ( & pem . Block { Type : " " , Bytes : data } ) }

// PublicKey is a convenience to encode the underlying public key to ASCII.

PublicKey is a convenience to encode the underlying public key to ASCII .


func (c *CertInfo) PrivateKey() []byte {
	ecKey, ok := c.KeyPair().PrivateKey.(*ecdsa.PrivateKey)
	if ok {
		data, err := x509.MarshalECPrivateKey(ecKey)
		if err != nil {
			return nil
		}

		return pem.EncodeToMemory(&pem.Block{Type: "EC PRIVATE KEY", Bytes: data})
	}

	rsaKey, ok := c.KeyPair().PrivateKey.(*rsa.PrivateKey)
	if ok {
		data := x509.MarshalPKCS1PrivateKey(rsaKey)
		return pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: data})
	}

	return nil
}

func ( c * CertInfo ) PrivateKey ( ) [ ] byte { ecKey , ok := c . KeyPair ( ) . PrivateKey . ( * ecdsa . PrivateKey ) if ok { data , err := x509 . MarshalECPrivateKey ( ecKey ) if err != nil { return nil } return pem . EncodeToMemory ( & pem . Block { Type : " " , Bytes : data } ) } rsaKey , ok := c . KeyPair ( ) . PrivateKey . ( * rsa . PrivateKey ) if ok { data := x509 . MarshalPKCS1PrivateKey ( rsaKey ) return pem . EncodeToMemory ( & pem . Block { Type : " " , Bytes : data } ) } return nil }

// PrivateKey is a convenience to encode the underlying private key.

PrivateKey is a convenience to encode the underlying private key .


func (c *CertInfo) Fingerprint() string {
	fingerprint, err := CertFingerprintStr(string(c.PublicKey()))
	// Parsing should never fail, since we generated the cert ourselves,
	// but let's check the error for good measure.
	if err != nil {
		panic("invalid public key material")
	}
	return fingerprint
}

// Fingerprint returns the fingerprint of the public key.

Fingerprint returns the fingerprint of the public key .


func GenCert(certf string, keyf string, certtype bool) error {
	/* Create the basenames if needed */
	dir := path.Dir(certf)
	err := os.MkdirAll(dir, 0750)
	if err != nil {
		return err
	}
	dir = path.Dir(keyf)
	err = os.MkdirAll(dir, 0750)
	if err != nil {
		return err
	}

	certBytes, keyBytes, err := GenerateMemCert(certtype)
	if err != nil {
		return err
	}

	certOut, err := os.Create(certf)
	if err != nil {
		return fmt.Errorf("Failed to open %s for writing: %v", certf, err)
	}
	certOut.Write(certBytes)
	certOut.Close()

	keyOut, err := os.OpenFile(keyf, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
	if err != nil {
		return fmt.Errorf("Failed to open %s for writing: %v", keyf, err)
	}
	keyOut.Write(keyBytes)
	keyOut.Close()
	return nil
}

func
GenCert
(
certf
string
,
keyf
string
,
certtype
bool
)
error
{
/* Create the basenames if needed */
dir
:=
path
.
Dir
(
certf
)
err
:=
os
.
MkdirAll
(
dir
,
0750
)
if
err
!=
{
return
err
}
dir
=
path
.
Dir
(
keyf
)
err
=
os
.
MkdirAll
(
dir
,
0750
)
if
err
!=
{
return
err
}
certBytes
,
keyBytes
,
err
:=
GenerateMemCert
(
certtype
)
if
err
!=
{
return
err
}
certOut
,
err
:=
os
.
Create
(
certf
)
if
err
!=
{
return
fmt
.
Errorf
(
"
"
,
certf
,
err
)
}
certOut
.
Write
(
certBytes
)
certOut
.
Close
(
)
keyOut
,
err
:=
os
.
OpenFile
(
keyf
,
os
.
O_WRONLY
|
os
.
O_CREATE
|
os
.
O_TRUNC
,
0600
)
if
err
!=
{
return
fmt
.
Errorf
(
"
"
,
keyf
,
err
)
}
keyOut
.
Write
(
keyBytes
)
keyOut
.
Close
(
)
return
}

// GenCert will create and populate a certificate file and a key file


func PrintServerInfo(c lxd.ContainerServer) error {
	server, _, err := c.GetServer()
	if err != nil {
		return err
	}
	env := server.Environment
	fmt.Printf("Test environment:\n")
	fmt.Printf("  Server backend: %s\n", env.Server)
	fmt.Printf("  Server version: %s\n", env.ServerVersion)
	fmt.Printf("  Kernel: %s\n", env.Kernel)
	fmt.Printf("  Kernel architecture: %s\n", env.KernelArchitecture)
	fmt.Printf("  Kernel version: %s\n", env.KernelVersion)
	fmt.Printf("  Storage backend: %s\n", env.Storage)
	fmt.Printf("  Storage version: %s\n", env.StorageVersion)
	fmt.Printf("  Container backend: %s\n", env.Driver)
	fmt.Printf("  Container version: %s\n", env.DriverVersion)
	fmt.Printf("\n")
	return nil
}

func PrintServerInfo ( c lxd . ContainerServer ) error { server , _ , err := c . GetServer ( ) if err != nil { return err } env := server . Environment fmt . Printf ( " \n " ) fmt . Printf ( " \n " , env . Server ) fmt . Printf ( " \n " , env . ServerVersion ) fmt . Printf ( " \n " , env . Kernel ) fmt . Printf ( " \n " , env . KernelArchitecture ) fmt . Printf ( " \n " , env . KernelVersion ) fmt . Printf ( " \n " , env . Storage ) fmt . Printf ( " \n " , env . StorageVersion ) fmt . Printf ( " \n " , env . Driver ) fmt . Printf ( " \n " , env . DriverVersion ) fmt . Printf ( " \n " ) return nil }

// PrintServerInfo prints out information about the server.

PrintServerInfo prints out information about the server .


func LaunchContainers(c lxd.ContainerServer, count int, parallel int, image string, privileged bool, start bool, freeze bool) (time.Duration, error) {
	var duration time.Duration

	batchSize, err := getBatchSize(parallel)
	if err != nil {
		return duration, err
	}

	printTestConfig(count, batchSize, image, privileged, freeze)

	fingerprint, err := ensureImage(c, image)
	if err != nil {
		return duration, err
	}

	batchStart := func(index int, wg *sync.WaitGroup) {
		defer wg.Done()

		name := getContainerName(count, index)

		err := createContainer(c, fingerprint, name, privileged)
		if err != nil {
			logf("Failed to launch container '%s': %s", name, err)
			return
		}

		if start {
			err := startContainer(c, name)
			if err != nil {
				logf("Failed to start container '%s': %s", name, err)
				return
			}

			if freeze {
				err := freezeContainer(c, name)
				if err != nil {
					logf("Failed to freeze container '%s': %s", name, err)
					return
				}
			}
		}
	}

	duration = processBatch(count, batchSize, batchStart)
	return duration, nil
}

func LaunchContainers ( c lxd . ContainerServer , count int , parallel int , image string , privileged bool , start bool , freeze bool ) ( time . Duration , error ) { var duration time . Duration batchSize , err := getBatchSize ( parallel ) if err != nil { return duration , err } printTestConfig ( count , batchSize , image , privileged , freeze ) fingerprint , err := ensureImage ( c , image ) if err != nil { return duration , err } batchStart := func ( index int , wg * sync . WaitGroup ) { defer wg . Done ( ) name := getContainerName ( count , index ) err := createContainer ( c , fingerprint , name , privileged ) if err != nil { logf ( " " , name , err ) return } if start { err := startContainer ( c , name ) if err != nil { logf ( " " , name , err ) return } if freeze { err := freezeContainer ( c , name ) if err != nil { logf ( " " , name , err ) return } } } } duration = processBatch ( count , batchSize , batchStart ) return duration , nil }

// LaunchContainers launches a set of containers.

LaunchContainers launches a set of containers .


func CreateContainers(c lxd.ContainerServer, count int, parallel int, fingerprint string, privileged bool) (time.Duration, error) {
	var duration time.Duration

	batchSize, err := getBatchSize(parallel)
	if err != nil {
		return duration, err
	}

	batchCreate := func(index int, wg *sync.WaitGroup) {
		defer wg.Done()

		name := getContainerName(count, index)

		err := createContainer(c, fingerprint, name, privileged)
		if err != nil {
			logf("Failed to launch container '%s': %s", name, err)
			return
		}
	}

	duration = processBatch(count, batchSize, batchCreate)

	return duration, nil
}

func CreateContainers ( c lxd . ContainerServer , count int , parallel int , fingerprint string , privileged bool ) ( time . Duration , error ) { var duration time . Duration batchSize , err := getBatchSize ( parallel ) if err != nil { return duration , err } batchCreate := func ( index int , wg * sync . WaitGroup ) { defer wg . Done ( ) name := getContainerName ( count , index ) err := createContainer ( c , fingerprint , name , privileged ) if err != nil { logf ( " " , name , err ) return } } duration = processBatch ( count , batchSize , batchCreate ) return duration , nil }

// CreateContainers create the specified number of containers.

CreateContainers create the specified number of containers .


func GetContainers(c lxd.ContainerServer) ([]api.Container, error) {
	containers := []api.Container{}

	allContainers, err := c.GetContainers()
	if err != nil {
		return containers, err
	}

	for _, container := range allContainers {
		if container.Config[userConfigKey] == "true" {
			containers = append(containers, container)
		}
	}

	return containers, nil
}

func GetContainers ( c lxd . ContainerServer ) ( [ ] api . Container , error ) { containers := [ ] api . Container { } allContainers , err := c . GetContainers ( ) if err != nil { return containers , err } for _ , container := range allContainers { if container . Config [ userConfigKey ] == " " { containers = append ( containers , container ) } } return containers , nil }

// GetContainers returns containers created by the benchmark.

GetContainers returns containers created by the benchmark .


func StartContainers(c lxd.ContainerServer, containers []api.Container, parallel int) (time.Duration, error) {
	var duration time.Duration

	batchSize, err := getBatchSize(parallel)
	if err != nil {
		return duration, err
	}

	count := len(containers)
	logf("Starting %d containers", count)

	batchStart := func(index int, wg *sync.WaitGroup) {
		defer wg.Done()

		container := containers[index]
		if !container.IsActive() {
			err := startContainer(c, container.Name)
			if err != nil {
				logf("Failed to start container '%s': %s", container.Name, err)
				return
			}
		}
	}

	duration = processBatch(count, batchSize, batchStart)
	return duration, nil
}

func StartContainers ( c lxd . ContainerServer , containers [ ] api . Container , parallel int ) ( time . Duration , error ) { var duration time . Duration batchSize , err := getBatchSize ( parallel ) if err != nil { return duration , err } count := len ( containers ) logf ( " " , count ) batchStart := func ( index int , wg * sync . WaitGroup ) { defer wg . Done ( ) container := containers [ index ] if ! container . IsActive ( ) { err := startContainer ( c , container . Name ) if err != nil { logf ( " " , container . Name , err ) return } } } duration = processBatch ( count , batchSize , batchStart ) return duration , nil }

// StartContainers starts containers created by the benchmark.

StartContainers starts containers created by the benchmark .


func setQueryParam(uri, param, value string) (string, error) {
	fields, err := url.Parse(uri)
	if err != nil {
		return "", err
	}

	values := fields.Query()
	values.Set(param, url.QueryEscape(value))

	fields.RawQuery = values.Encode()

	return fields.String(), nil
}

func setQueryParam ( uri , param , value string ) ( string , error ) { fields , err := url . Parse ( uri ) if err != nil { return " " , err } values := fields . Query ( ) values . Set ( param , url . QueryEscape ( value ) ) fields . RawQuery = values . Encode ( ) return fields . String ( ) , nil }

// Set the value of a query parameter in the given URI.

Set the value of a query parameter in the given URI .


func (r *ProtocolLXD) GetImages() ([]api.Image, error) {
	images := []api.Image{}

	_, err := r.queryStruct("GET", "/images?recursion=1", nil, "", &images)
	if err != nil {
		return nil, err
	}

	return images, nil
}

func ( r * ProtocolLXD ) GetImages ( ) ( [ ] api . Image , error ) { images := [ ] api . Image { } _ , err := r . queryStruct ( " " , " " , nil , " " , & images ) if err != nil { return nil , err } return images , nil }

// Image handling functions
// GetImages returns a list of available images as Image structs

Image handling functions GetImages returns a list of available images as Image structs


func (r *ProtocolLXD) GetImageFile(fingerprint string, req ImageFileRequest) (*ImageFileResponse, error) {
	return r.GetPrivateImageFile(fingerprint, "", req)
}

func ( r * ProtocolLXD ) GetImageFile ( fingerprint string , req ImageFileRequest ) ( * ImageFileResponse , error ) { return r . GetPrivateImageFile ( fingerprint , " " , req ) }

// GetImageFile downloads an image from the server, returning an ImageFileRequest struct

GetImageFile downloads an image from the server returning an ImageFileRequest struct


func (r *ProtocolLXD) GetImageSecret(fingerprint string) (string, error) {
	op, err := r.CreateImageSecret(fingerprint)
	if err != nil {
		return "", err
	}
	opAPI := op.Get()

	return opAPI.Metadata["secret"].(string), nil
}

func ( r * ProtocolLXD ) GetImageSecret ( fingerprint string ) ( string , error ) { op , err := r . CreateImageSecret ( fingerprint ) if err != nil { return " " , err } opAPI := op . Get ( ) return opAPI . Metadata [ " " ] . ( string ) , nil }

// GetImageSecret is a helper around CreateImageSecret that returns a secret for the image


func (r *ProtocolLXD) GetPrivateImage(fingerprint string, secret string) (*api.Image, string, error) {
	image := api.Image{}

	// Build the API path
	path := fmt.Sprintf("/images/%s", url.QueryEscape(fingerprint))
	var err error
	path, err = r.setQueryAttributes(path)
	if err != nil {
		return nil, "", err
	}

	if secret != "" {
		path, err = setQueryParam(path, "secret", secret)
		if err != nil {
			return nil, "", err
		}
	}

	// Fetch the raw value
	etag, err := r.queryStruct("GET", path, nil, "", &image)
	if err != nil {
		return nil, "", err
	}

	return &image, etag, nil
}

func
(
r
*
ProtocolLXD
)
GetPrivateImage
(
fingerprint
string
,
secret
string
)
(
*
api
.
Image
,
string
,
error
)
{
image
:=
api
.
Image
{
}
// Build the API path
path
:=
fmt
.
Sprintf
(
"
"
,
url
.
QueryEscape
(
fingerprint
)
)
var
err
error
path
,
err
=
r
.
setQueryAttributes
(
path
)
if
err
!=
{
return
,
"
"
,
err
}
if
secret
!=
"
"
{
path
,
err
=
setQueryParam
(
path
,
"
"
,
secret
)
if
err
!=
{
return
,
"
"
,
err
}
}
// Fetch the raw value
etag
,
err
:=
r
.
queryStruct
(
"
"
,
path
,
,
"
"
,
&
image
)
if
err
!=
{
return
,
"
"
,
err
}
return
&
image
,
etag
,
}

// GetPrivateImage is similar to GetImage but allows passing a secret download token


func (r *ProtocolLXD) GetPrivateImageFile(fingerprint string, secret string, req ImageFileRequest) (*ImageFileResponse, error) {
	// Sanity checks
	if req.MetaFile == nil && req.RootfsFile == nil {
		return nil, fmt.Errorf("No file requested")
	}

	uri := fmt.Sprintf("/1.0/images/%s/export", url.QueryEscape(fingerprint))

	var err error
	uri, err = r.setQueryAttributes(uri)
	if err != nil {
		return nil, err
	}

	// Attempt to download from host
	if secret == "" && shared.PathExists("/dev/lxd/sock") && os.Geteuid() == 0 {
		unixURI := fmt.Sprintf("http://unix.socket%s", uri)

		// Setup the HTTP client
		devlxdHTTP, err := unixHTTPClient(nil, "/dev/lxd/sock")
		if err == nil {
			resp, err := lxdDownloadImage(fingerprint, unixURI, r.httpUserAgent, devlxdHTTP, req)
			if err == nil {
				return resp, nil
			}
		}
	}

	// Build the URL
	uri = fmt.Sprintf("%s%s", r.httpHost, uri)
	if secret != "" {
		uri, err = setQueryParam(uri, "secret", secret)
		if err != nil {
			return nil, err
		}
	}

	return lxdDownloadImage(fingerprint, uri, r.httpUserAgent, r.http, req)
}

func
(
r
*
ProtocolLXD
)
GetPrivateImageFile
(
fingerprint
string
,
secret
string
,
req
ImageFileRequest
)
(
*
ImageFileResponse
,
error
)
{
// Sanity checks
if
req
.
MetaFile
==
&&
req
.
RootfsFile
==
{
return
,
fmt
.
Errorf
(
"
"
)
}
uri
:=
fmt
.
Sprintf
(
"
"
,
url
.
QueryEscape
(
fingerprint
)
)
var
err
error
uri
,
err
=
r
.
setQueryAttributes
(
uri
)
if
err
!=
{
return
,
err
}
// Attempt to download from host
if
secret
==
"
"
&&
shared
.
PathExists
(
"
"
)
&&
os
.
Geteuid
(
)
==
0
{
unixURI
:=
fmt
.
Sprintf
(
"
"
,
uri
)
// Setup the HTTP client
devlxdHTTP
,
err
:=
unixHTTPClient
(
,
"
"
)
if
err
==
{
resp
,
err
:=
lxdDownloadImage
(
fingerprint
,
unixURI
,
r
.
httpUserAgent
,
devlxdHTTP
,
req
)
if
err
==
{
return
resp
,
}
}
}
// Build the URL
uri
=
fmt
.
Sprintf
(
"
"
,
r
.
httpHost
,
uri
)
if
secret
!=
"
"
{
uri
,
err
=
setQueryParam
(
uri
,
"
"
,
secret
)
if
err
!=
{
return
,
err
}
}
return
lxdDownloadImage
(
fingerprint
,
uri
,
r
.
httpUserAgent
,
r
.
http
,
req
)
}

// GetPrivateImageFile is similar to GetImageFile but allows passing a secret download token


func (r *ProtocolLXD) GetImageAliases() ([]api.ImageAliasesEntry, error) {
	aliases := []api.ImageAliasesEntry{}

	// Fetch the raw value
	_, err := r.queryStruct("GET", "/images/aliases?recursion=1", nil, "", &aliases)
	if err != nil {
		return nil, err
	}

	return aliases, nil
}

func
(
r
*
ProtocolLXD
)
GetImageAliases
(
)
(
[
]
api
.
ImageAliasesEntry
,
error
)
{
aliases
:=
[
]
api
.
ImageAliasesEntry
{
}
// Fetch the raw value
_
,
err
:=
r
.
queryStruct
(
"
"
,
"
"
,
,
"
"
,
&
aliases
)
if
err
!=
{
return
,
err
}
return
aliases
,
}

// GetImageAliases returns the list of available aliases as ImageAliasesEntry structs


func (r *ProtocolLXD) tryCopyImage(req api.ImagesPost, urls []string) (RemoteOperation, error) {
	if len(urls) == 0 {
		return nil, fmt.Errorf("The source server isn't listening on the network")
	}

	rop := remoteOperation{
		chDone: make(chan bool),
	}

	// For older servers, apply the aliases after copy
	if !r.HasExtension("image_create_aliases") && req.Aliases != nil {
		rop.chPost = make(chan bool)

		go func() {
			defer close(rop.chPost)

			// Wait for the main operation to finish
			<-rop.chDone
			if rop.err != nil {
				return
			}

			// Get the operation data
			op, err := rop.GetTarget()
			if err != nil {
				return
			}

			// Extract the fingerprint
			fingerprint := op.Metadata["fingerprint"].(string)

			// Add the aliases
			for _, entry := range req.Aliases {
				alias := api.ImageAliasesPost{}
				alias.Name = entry.Name
				alias.Target = fingerprint

				r.CreateImageAlias(alias)
			}
		}()
	}

	// Forward targetOp to remote op
	go func() {
		success := false
		errors := map[string]error{}
		for _, serverURL := range urls {
			req.Source.Server = serverURL

			op, err := r.CreateImage(req, nil)
			if err != nil {
				errors[serverURL] = err
				continue
			}

			rop.targetOp = op

			for _, handler := range rop.handlers {
				rop.targetOp.AddHandler(handler)
			}

			err = rop.targetOp.Wait()
			if err != nil {
				errors[serverURL] = err
				continue
			}

			success = true
			break
		}

		if !success {
			rop.err = remoteOperationError("Failed remote image download", errors)
		}

		close(rop.chDone)
	}()

	return &rop, nil
}

// tryCopyImage iterates through the source server URLs until one lets it download the image


func (r *ProtocolLXD) CopyImage(source ImageServer, image api.Image, args *ImageCopyArgs) (RemoteOperation, error) {
	// Sanity checks
	if r == source {
		return nil, fmt.Errorf("The source and target servers must be different")
	}

	// Get source server connection information
	info, err := source.GetConnectionInfo()
	if err != nil {
		return nil, err
	}

	// Prepare the copy request
	req := api.ImagesPost{
		Source: &api.ImagesPostSource{
			ImageSource: api.ImageSource{
				Certificate: info.Certificate,
				Protocol:    info.Protocol,
			},
			Fingerprint: image.Fingerprint,
			Mode:        "pull",
			Type:        "image",
		},
	}

	// Generate secret token if needed
	if !image.Public {
		secret, err := source.GetImageSecret(image.Fingerprint)
		if err != nil {
			return nil, err
		}

		req.Source.Secret = secret
	}

	// Process the arguments
	if args != nil {
		req.Aliases = args.Aliases
		req.AutoUpdate = args.AutoUpdate
		req.Public = args.Public

		if args.CopyAliases {
			req.Aliases = image.Aliases
			if args.Aliases != nil {
				req.Aliases = append(req.Aliases, args.Aliases...)
			}
		}
	}

	return r.tryCopyImage(req, info.Addresses)
}

// CopyImage copies an image from a remote server. Additional options can be passed using ImageCopyArgs

CopyImage copies an image from a remote server . Additional options can be passed using ImageCopyArgs


func (r *ProtocolLXD) UpdateImage(fingerprint string, image api.ImagePut, ETag string) error {
	// Send the request
	_, _, err := r.query("PUT", fmt.Sprintf("/images/%s", url.QueryEscape(fingerprint)), image, ETag)
	if err != nil {
		return err
	}

	return nil
}

func
(
r
*
ProtocolLXD
)
UpdateImage
(
fingerprint
string
,
image
api
.
ImagePut
,
ETag
string
)
error
{
// Send the request
_
,
_
,
err
:=
r
.
query
(
"
"
,
fmt
.
Sprintf
(
"
"
,
url
.
QueryEscape
(
fingerprint
)
)
,
image
,
ETag
)
if
err
!=
{
return
err
}
return
}

// UpdateImage updates the image definition


func (r *ProtocolLXD) DeleteImage(fingerprint string) (Operation, error) {
	// Send the request
	op, _, err := r.queryOperation("DELETE", fmt.Sprintf("/images/%s", url.QueryEscape(fingerprint)), nil, "")
	if err != nil {
		return nil, err
	}

	return op, nil
}

func
(
r
*
ProtocolLXD
)
DeleteImage
(
fingerprint
string
)
(
Operation
,
error
)
{
// Send the request
op
,
_
,
err
:=
r
.
queryOperation
(
"
"
,
fmt
.
Sprintf
(
"
"
,
url
.
QueryEscape
(
fingerprint
)
)
,
,
"
"
)
if
err
!=
{
return
,
err
}
return
op
,
}

// DeleteImage requests that LXD removes an image from the store


func (r *ProtocolLXD) RefreshImage(fingerprint string) (Operation, error) {
	if !r.HasExtension("image_force_refresh") {
		return nil, fmt.Errorf("The server is missing the required \"image_force_refresh\" API extension")
	}

	// Send the request
	op, _, err := r.queryOperation("POST", fmt.Sprintf("/images/%s/refresh", url.QueryEscape(fingerprint)), nil, "")
	if err != nil {
		return nil, err
	}

	return op, nil
}

func
(
r
*
ProtocolLXD
)
RefreshImage
(
fingerprint
string
)
(
Operation
,
error
)
{
if
!
r
.
HasExtension
(
"
"
)
{
return
,
fmt
.
Errorf
(
"
\"
\"
"
)
}
// Send the request
op
,
_
,
err
:=
r
.
queryOperation
(
"
"
,
fmt
.
Sprintf
(
"
"
,
url
.
QueryEscape
(
fingerprint
)
)
,
,
"
"
)
if
err
!=
{
return
,
err
}
return
op
,
}

// RefreshImage requests that LXD issues an image refresh


func (r *ProtocolLXD) CreateImageAlias(alias api.ImageAliasesPost) error {
	// Send the request
	_, _, err := r.query("POST", "/images/aliases", alias, "")
	if err != nil {
		return err
	}

	return nil
}

func
(
r
*
ProtocolLXD
)
CreateImageAlias
(
alias
api
.
ImageAliasesPost
)
error
{
// Send the request
_
,
_
,
err
:=
r
.
query
(
"
"
,
"
"
,
alias
,
"
"
)
if
err
!=
{
return
err
}
return
}

// CreateImageAlias sets up a new image alias


func (r *ProtocolLXD) UpdateImageAlias(name string, alias api.ImageAliasesEntryPut, ETag string) error {
	// Send the request
	_, _, err := r.query("PUT", fmt.Sprintf("/images/aliases/%s", url.QueryEscape(name)), alias, ETag)
	if err != nil {
		return err
	}

	return nil
}

func
(
r
*
ProtocolLXD
)
UpdateImageAlias
(
name
string
,
alias
api
.
ImageAliasesEntryPut
,
ETag
string
)
error
{
// Send the request
_
,
_
,
err
:=
r
.
query
(
"
"
,
fmt
.
Sprintf
(
"
"
,
url
.
QueryEscape
(
name
)
)
,
alias
,
ETag
)
if
err
!=
{
return
err
}
return
}

// UpdateImageAlias updates the image alias definition


func (r *ProtocolLXD) RenameImageAlias(name string, alias api.ImageAliasesEntryPost) error {
	// Send the request
	_, _, err := r.query("POST", fmt.Sprintf("/images/aliases/%s", url.QueryEscape(name)), alias, "")
	if err != nil {
		return err
	}

	return nil
}

func
(
r
*
ProtocolLXD
)
RenameImageAlias
(
name
string
,
alias
api
.
ImageAliasesEntryPost
)
error
{
// Send the request
_
,
_
,
err
:=
r
.
query
(
"
"
,
fmt
.
Sprintf
(
"
"
,
url
.
QueryEscape
(
name
)
)
,
alias
,
"
"
)
if
err
!=
{
return
err
}
return
}

// RenameImageAlias renames an existing image alias


func (r *ProtocolLXD) DeleteImageAlias(name string) error {
	// Send the request
	_, _, err := r.query("DELETE", fmt.Sprintf("/images/aliases/%s", url.QueryEscape(name)), nil, "")
	if err != nil {
		return err
	}

	return nil
}

func
(
r
*
ProtocolLXD
)
DeleteImageAlias
(
name
string
)
error
{
// Send the request
_
,
_
,
err
:=
r
.
query
(
"
"
,
fmt
.
Sprintf
(
"
"
,
url
.
QueryEscape
(
name
)
)
,
,
"
"
)
if
err
!=
{
return
err
}
return
}

// DeleteImageAlias removes an alias from the LXD image store


func Open(dir string) (*sql.DB, error) {
	path := filepath.Join(dir, "local.db")
	db, err := sqliteOpen(path)
	if err != nil {
		return nil, fmt.Errorf("cannot open node database: %v", err)
	}

	return db, nil
}

func Open ( dir string ) ( * sql . DB , error ) { path := filepath . Join ( dir , " " ) db , err := sqliteOpen ( path ) if err != nil { return nil , fmt . Errorf ( " " , err ) } return db , nil }


func EnsureSchema(db *sql.DB, dir string, hook schema.Hook) (int, error) {
	backupDone := false

	schema := Schema()
	schema.File(filepath.Join(dir, "patch.local.sql")) // Optional custom queries
	schema.Hook(func(version int, tx *sql.Tx) error {
		if !backupDone {
			logger.Infof("Updating the LXD database schema. Backup made as \"local.db.bak\"")
			path := filepath.Join(dir, "local.db")
			err := shared.FileCopy(path, path+".bak")
			if err != nil {
				return err
			}

			backupDone = true
		}

		if version == -1 {
			logger.Debugf("Running pre-update queries from file for local DB schema")
		} else {
			logger.Debugf("Updating DB schema from %d to %d", version, version+1)
		}

		// Run the given hook only against actual update versions, not
		// when a custom query file is passed (signaled by version == -1).
		if hook != nil && version != -1 {
			err := hook(version, tx)
			if err != nil {
			}
		}

		return nil
	})
	return schema.Ensure(db)
}

// EnsureSchema applies all relevant schema updates to the node-local
// database.
//
// Return the initial schema version found before starting the update, along
// with any error occurred.

EnsureSchema applies all relevant schema updates to the node - local database . Return the initial schema version found before starting the update along with any error occurred .


func FilesystemDetect(path string) (string, error) {
	fs := syscall.Statfs_t{}

	err := syscall.Statfs(path, &fs)
	if err != nil {
		return "", err
	}

	switch fs.Type {
	case FilesystemSuperMagicBtrfs:
		return "btrfs", nil
	case FilesystemSuperMagicZfs:
		return "zfs", nil
	case FilesystemSuperMagicTmpfs:
		return "tmpfs", nil
	case FilesystemSuperMagicExt4:
		return "ext4", nil
	case FilesystemSuperMagicXfs:
		return "xfs", nil
	case FilesystemSuperMagicNfs:
		return "nfs", nil
	default:
		logger.Debugf("Unknown backing filesystem type: 0x%x", fs.Type)
		return string(fs.Type), nil
	}
}

func FilesystemDetect ( path string ) ( string , error ) { fs := syscall . Statfs_t { } err := syscall . Statfs ( path , & fs ) if err != nil { return " " , err } switch fs . Type { case FilesystemSuperMagicBtrfs : return " " , nil case FilesystemSuperMagicZfs : return " " , nil case FilesystemSuperMagicTmpfs : return " " , nil case FilesystemSuperMagicExt4 : return " " , nil case FilesystemSuperMagicXfs : return " " , nil case FilesystemSuperMagicNfs : return " " , nil default : logger . Debugf ( " " , fs . Type ) return string ( fs . Type ) , nil } }

// FilesystemDetect returns the filesystem on which the passed-in path sits.

FilesystemDetect returns the filesystem on which the passed - in path sits .


func Schema() *schema.Schema {
	schema := schema.NewFromMap(updates)
	schema.Fresh(freshSchema)
	return schema
}

func Schema ( ) * schema . Schema { schema := schema . NewFromMap ( updates ) schema . Fresh ( freshSchema ) return schema }


func updateFromV37(tx *sql.Tx) error {
	count, err := query.Count(tx, "raft_nodes", "")
	if err != nil {
		return errors.Wrap(err, "Fetch count of Raft nodes")
	}

	if count == 0 {
		// This node is not clustered, nothing to do.
		return nil
	}

	// Copy the core.https_address config.
	_, err = tx.Exec(`
INSERT INTO config (key, value)
  SELECT 'cluster.https_address', value FROM config WHERE key = 'core.https_address'
`)
	if err != nil {
		return errors.Wrap(err, "Insert cluster.https_address config")
	}

	return nil
}

// Schema updates begin here
// Copy core.https_address to cluster.https_address in case this node is
// clustered.

Schema updates begin here Copy core . https_address to cluster . https_address in case this node is clustered .


func ArchitectureGetLocal() (string, error) {
	uname, err := shared.Uname()
	if err != nil {
		return ArchitectureDefault, err
	}

	return uname.Machine, nil
}

func ArchitectureGetLocal ( ) ( string , error ) { uname , err := shared . Uname ( ) if err != nil { return ArchitectureDefault , err } return uname . Machine , nil }

// ArchitectureGetLocal returns the local hardware architecture


func NewController(url string, key string, machine string) (*Controller, error) {
	baseURL := fmt.Sprintf("%s/api/2.0/", url)

	// Connect to MAAS
	srv, err := gomaasapi.NewController(gomaasapi.ControllerArgs{
		BaseURL: baseURL,
		APIKey:  key,
	})
	if err != nil {
		// Juju errors aren't user-friendly, try to extract what actually happened
		if !strings.Contains(err.Error(), "unsupported version") {
			return nil, err
		}

		return nil, fmt.Errorf("Unable to connect MAAS at '%s': %v", baseURL,
			strings.Split(strings.Split(err.Error(), "unsupported version: ")[1], " (")[0])
	}

	srvRaw, err := gomaasapi.NewAuthenticatedClient(baseURL, key)
	if err != nil {
		return nil, err
	}

	// Find the right machine
	machines, err := srv.Machines(gomaasapi.MachinesArgs{Hostnames: []string{machine}})
	if err != nil {
		return nil, err
	}

	if len(machines) != 1 {
		return nil, fmt.Errorf("Couldn't find the specified machine: %s", machine)
	}

	// Setup the struct
	c := Controller{}
	c.srv = srv
	c.srvRaw = *srvRaw
	c.machine = machines[0]
	c.url = baseURL

	return &c, err
}

// NewController returns a new Controller using the specific MAAS server and machine


func (c *Controller) CreateContainer(name string, interfaces []ContainerInterface) error {
	// Parse the provided interfaces
	macInterfaces, err := parseInterfaces(interfaces)
	if err != nil {
		return err
	}

	// Get all the subnets
	subnets, err := c.getSubnets()
	if err != nil {
		return err
	}

	// Create the device and first interface
	device, err := c.machine.CreateDevice(gomaasapi.CreateMachineDeviceArgs{
		Hostname:      name,
		InterfaceName: interfaces[0].Name,
		MACAddress:    interfaces[0].MACAddress,
		VLAN:          subnets[interfaces[0].Subnets[0].Name].VLAN(),
	})
	if err != nil {
		return err
	}

	// Wipe the container entry if anything fails
	success := false
	defer func() {
		if success == true {
			return
		}

		c.DeleteContainer(name)
	}()

	// Create the rest of the interfaces
	for _, iface := range interfaces[1:] {
		_, err := device.CreateInterface(gomaasapi.CreateInterfaceArgs{
			Name:       iface.Name,
			MACAddress: iface.MACAddress,
			VLAN:       subnets[iface.Subnets[0].Name].VLAN(),
		})
		if err != nil {
			return err
		}
	}

	// Get a fresh copy of the device
	device, err = c.getDevice(name)
	if err != nil {
		return err
	}

	// Setup the interfaces
	for _, entry := range device.InterfaceSet() {
		// Get our record
		iface, ok := macInterfaces[entry.MACAddress()]
		if !ok {
			return fmt.Errorf("MAAS created an interface with a bad MAC: %s", entry.MACAddress())
		}

		// Add the subnets
		for _, subnet := range iface.Subnets {
			err := entry.LinkSubnet(gomaasapi.LinkSubnetArgs{
				Mode:      gomaasapi.LinkModeStatic,
				Subnet:    subnets[subnet.Name],
				IPAddress: subnet.Address,
			})
			if err != nil {
				return err
			}
		}
	}

	success = true
	return nil
}

// CreateContainer defines a new MAAS device for the controller


func (c *Controller) DefinedContainer(name string) (bool, error) {
	devs, err := c.machine.Devices(gomaasapi.DevicesArgs{Hostname: []string{name}})
	if err != nil {
		return false, err
	}

	if len(devs) == 1 {
		return true, nil
	}

	return false, nil
}

func ( c * Controller ) DefinedContainer ( name string ) ( bool , error ) { devs , err := c . machine . Devices ( gomaasapi . DevicesArgs { Hostname : [ ] string { name } } ) if err != nil { return false , err } if len ( devs ) == 1 { return true , nil } return false , nil }

// DefinedContainer returns true if the container is defined in MAAS


func (c *Controller) UpdateContainer(name string, interfaces []ContainerInterface) error {
	// Parse the provided interfaces
	macInterfaces, err := parseInterfaces(interfaces)
	if err != nil {
		return err
	}

	// Get all the subnets
	subnets, err := c.getSubnets()
	if err != nil {
		return err
	}

	device, err := c.getDevice(name)
	if err != nil {
		return err
	}

	// Iterate over existing interfaces, drop all removed ones and update existing ones
	existingInterfaces := map[string]gomaasapi.Interface{}
	for _, entry := range device.InterfaceSet() {
		// Check if the interface has been removed from the container
		iface, ok := macInterfaces[entry.MACAddress()]
		if !ok {
			// Delete the interface in MAAS
			err = entry.Delete()
			if err != nil {
				return err
			}

			continue
		}

		// Update the subnets
		existingSubnets := map[string]gomaasapi.Subnet{}
		for _, link := range entry.Links() {
			// Check if the MAAS subnet matches any of the container's
			found := false
			for _, subnet := range iface.Subnets {
				if subnet.Name == link.Subnet().Name() {
					if subnet.Address == "" || subnet.Address == link.IPAddress() {
						found = true
					}
					break
				}
			}

			// If no exact match could be found, remove it from MAAS
			if !found {
				err = entry.UnlinkSubnet(link.Subnet())
				if err != nil {
					return err
				}

				continue
			}

			// Record the existing up to date subnet
			existingSubnets[link.Subnet().Name()] = link.Subnet()
		}

		// Add any missing (or updated) subnet to MAAS
		for _, subnet := range iface.Subnets {
			// Check that it's not configured yet
			_, ok := existingSubnets[subnet.Name]
			if ok {
				continue
			}

			// Add the link
			err := entry.LinkSubnet(gomaasapi.LinkSubnetArgs{
				Mode:      gomaasapi.LinkModeStatic,
				Subnet:    subnets[subnet.Name],
				IPAddress: subnet.Address,
			})
			if err != nil {
				return err
			}
		}

		// Record the interface has being configured
		existingInterfaces[entry.MACAddress()] = entry
	}

	// Iterate over expected interfaces, add any missing one
	for _, iface := range macInterfaces {
		_, ok := existingInterfaces[iface.MACAddress]
		if ok {
			// We already have it so just move on
			continue
		}

		// Create the new interface
		entry, err := device.CreateInterface(gomaasapi.CreateInterfaceArgs{
			Name:       iface.Name,
			MACAddress: iface.MACAddress,
			VLAN:       subnets[iface.Subnets[0].Name].VLAN(),
		})
		if err != nil {
			return err
		}

		// Add the subnets
		for _, subnet := range iface.Subnets {
			err := entry.LinkSubnet(gomaasapi.LinkSubnetArgs{
				Mode:      gomaasapi.LinkModeStatic,
				Subnet:    subnets[subnet.Name],
				IPAddress: subnet.Address,
			})
			if err != nil {
				return err
			}
		}
	}

	return nil
}

// UpdateContainer updates the MAAS device's interfaces with the new provided state

UpdateContainer updates the MAAS device s interfaces with the new provided state


func (c *Controller) RenameContainer(name string, newName string) error {
	device, err := c.getDevice(name)
	if err != nil {
		return err
	}

	// FIXME: We should convince the Juju folks to implement an Update() method on Device
	uri, err := url.Parse(fmt.Sprintf("%s/devices/%s/", c.url, device.SystemID()))
	if err != nil {
		return err
	}

	values := url.Values{}
	values.Set("hostname", newName)

	_, err = c.srvRaw.Put(uri, values)
	if err != nil {
		return err
	}

	return nil
}

// RenameContainer renames the MAAS device for the container without releasing any allocation


func (c *Controller) DeleteContainer(name string) error {
	device, err := c.getDevice(name)
	if err != nil {
		return err
	}

	err = device.Delete()
	if err != nil {
		return err
	}

	return nil
}

func ( c * Controller ) DeleteContainer ( name string ) error { device , err := c . getDevice ( name ) if err != nil { return err } err = device . Delete ( ) if err != nil { return err } return nil }

// DeleteContainer removes the MAAS device for the container


func (s *Schema) Add(update Update) {
	s.updates = append(s.updates, update)
}

func ( s * Schema ) Add ( update Update ) { s . updates = append ( s . updates , update ) }

// Add a new update to the schema. It will be appended at the end of the
// existing series.

Add a new update to the schema . It will be appended at the end of the existing series .


func ensureSchemaTableExists(tx *sql.Tx) error {
	exists, err := DoesSchemaTableExist(tx)
	if err != nil {
		return fmt.Errorf("failed to check if schema table is there: %v", err)
	}
	if !exists {
		err := createSchemaTable(tx)
		if err != nil {
			return fmt.Errorf("failed to create schema table: %v", err)
		}
	}
	return nil
}

func ensureSchemaTableExists ( tx * sql . Tx ) error { exists , err := DoesSchemaTableExist ( tx ) if err != nil { return fmt . Errorf ( " " , err ) } if ! exists { err := createSchemaTable ( tx ) if err != nil { return fmt . Errorf ( " " , err ) } } return nil }


func queryCurrentVersion(tx *sql.Tx) (int, error) {
	versions, err := selectSchemaVersions(tx)
	if err != nil {
		return -1, fmt.Errorf("failed to fetch update versions: %v", err)
	}

	// Fix bad upgrade code between 30 and 32
	hasVersion := func(v int) bool { return shared.IntInSlice(v, versions) }
	if hasVersion(30) && hasVersion(32) && !hasVersion(31) {
		err = insertSchemaVersion(tx, 31)
		if err != nil {
			return -1, fmt.Errorf("failed to insert missing schema version 31")
		}

		versions, err = selectSchemaVersions(tx)
		if err != nil {
			return -1, fmt.Errorf("failed to fetch update versions: %v", err)
		}
	}

	// Fix broken schema version between 37 and 38
	if hasVersion(37) && !hasVersion(38) {
		count, err := query.Count(tx, "config", "key = 'cluster.https_address'")
		if err != nil {
			return -1, fmt.Errorf("Failed to check if cluster.https_address is set: %v", err)
		}
		if count == 1 {
			// Insert the missing version.
			err := insertSchemaVersion(tx, 38)
			if err != nil {
				return -1, fmt.Errorf("Failed to insert missing schema version 38")
			}
			versions = append(versions, 38)
		}
	}

	current := 0
	if len(versions) > 0 {
		err = checkSchemaVersionsHaveNoHoles(versions)
		if err != nil {
			return -1, err
		}
		current = versions[len(versions)-1] // Highest recorded version
	}

	return current, nil
}

// Return the highest update version currently applied. Zero means that no
// updates have been applied yet.

Return the highest update version currently applied . Zero means that no updates have been applied yet .


func ensureUpdatesAreApplied(tx *sql.Tx, current int, updates []Update, hook Hook) error {
	if current > len(updates) {
		return fmt.Errorf(
			"schema version '%d' is more recent than expected '%d'",
			current, len(updates))
	}

	// If there are no updates, there's nothing to do.
	if len(updates) == 0 {
		return nil
	}

	// Apply missing updates.
	for _, update := range updates[current:] {
		if hook != nil {
			err := hook(current, tx)
			if err != nil {
				return fmt.Errorf(
					"failed to execute hook (version %d): %v", current, err)
			}
		}
		err := update(tx)
		if err != nil {
			return fmt.Errorf("failed to apply update %d: %v", current, err)
		}
		current++

		err = insertSchemaVersion(tx, current)
		if err != nil {
			return fmt.Errorf("failed to insert version %d", current)
		}
	}

	return nil
}

// Apply any pending update that was not yet applied.

Apply any pending update that was not yet applied .


func checkSchemaVersionsHaveNoHoles(versions []int) error {
	// Sanity check that there are no "holes" in the recorded
	// versions.
	for i := range versions[:len(versions)-1] {
		if versions[i+1] != versions[i]+1 {
			return fmt.Errorf("Missing updates: %d to %d", versions[i], versions[i+1])
		}
	}
	return nil
}

// Check that the given list of update version numbers doesn't have "holes",
// that is each version equal the preceding version plus 1.

Check that the given list of update version numbers doesn t have holes that is each version equal the preceding version plus 1 .


func checkAllUpdatesAreApplied(tx *sql.Tx, updates []Update) error {
	versions, err := selectSchemaVersions(tx)
	if err != nil {
		return fmt.Errorf("failed to fetch update versions: %v", err)
	}

	if len(versions) == 0 {
		return fmt.Errorf("expected schema table to contain at least one row")
	}

	err = checkSchemaVersionsHaveNoHoles(versions)
	if err != nil {
		return err
	}

	current := versions[len(versions)-1]
	if current != len(updates) {
		return fmt.Errorf("update level is %d, expected %d", current, len(updates))
	}
	return nil
}

func checkAllUpdatesAreApplied ( tx * sql . Tx , updates [ ] Update ) error { versions , err := selectSchemaVersions ( tx ) if err != nil { return fmt . Errorf ( " " , err ) } if len ( versions ) == 0 { return fmt . Errorf ( " " ) } err = checkSchemaVersionsHaveNoHoles ( versions ) if err != nil { return err } current := versions [ len ( versions ) - 1 ] if current != len ( updates ) { return fmt . Errorf ( " " , current , len ( updates ) ) } return nil }

// Check that all the given updates are applied.

Check that all the given updates are applied .


func formatSQL(statement string) string {
	lines := strings.Split(statement, "\n")
	for i, line := range lines {
		if strings.Contains(line, "UNIQUE") {
			// Let UNIQUE(x, y) constraints alone.
			continue
		}
		lines[i] = strings.Replace(line, ", ", ",\n    ", -1)
	}
	return strings.Join(lines, "\n")
}

func
formatSQL
(
statement
string
)
string
{
lines
:=
strings
.
Split
(
statement
,
"
\n
"
)
for
i
,
line
:=
range
lines
{
if
strings
.
Contains
(
line
,
"
"
)
{
// Let UNIQUE(x, y) constraints alone.
continue
}
lines
[
i
]
=
strings
.
Replace
(
line
,
"
"
,
"
\n
"
,
1
)
}
return
strings
.
Join
(
lines
,
"
\n
"
)
}

// Format the given SQL statement in a human-readable way.
//
// In particular make sure that each column definition in a CREATE TABLE clause
// is in its own row, since SQLite dumps occasionally stuff more than one
// column in the same line.

Format the given SQL statement in a human - readable way . In particular make sure that each column definition in a CREATE TABLE clause is in its own row since SQLite dumps occasionally stuff more than one column in the same line .


func GetAllXattr(path string) (xattrs map[string]string, err error) {
	e1 := fmt.Errorf("Extended attributes changed during retrieval")

	// Call llistxattr() twice: First, to determine the size of the buffer
	// we need to allocate to store the extended attributes, second, to
	// actually store the extended attributes in the buffer. Also, check if
	// the size/number of extended attributes hasn't changed between the two
	// calls.
	pre, err := llistxattr(path, nil)
	if err != nil || pre < 0 {
		return nil, err
	}
	if pre == 0 {
		return nil, nil
	}

	dest := make([]byte, pre)

	post, err := llistxattr(path, dest)
	if err != nil || post < 0 {
		return nil, err
	}
	if post != pre {
		return nil, e1
	}

	split := strings.Split(string(dest), "\x00")
	if split == nil {
		return nil, fmt.Errorf("No valid extended attribute key found")
	}
	// *listxattr functions return a list of  names  as  an unordered array
	// of null-terminated character strings (attribute names are separated
	// by null bytes ('\0')), like this: user.name1\0system.name1\0user.name2\0
	// Since we split at the '\0'-byte the last element of the slice will be
	// the empty string. We remove it:
	if split[len(split)-1] == "" {
		split = split[:len(split)-1]
	}

	xattrs = make(map[string]string, len(split))

	for _, x := range split {
		xattr := string(x)
		// Call Getxattr() twice: First, to determine the size of the
		// buffer we need to allocate to store the extended attributes,
		// second, to actually store the extended attributes in the
		// buffer. Also, check if the size of the extended attribute
		// hasn't changed between the two calls.
		pre, err = syscall.Getxattr(path, xattr, nil)
		if err != nil || pre < 0 {
			return nil, err
		}

		dest = make([]byte, pre)
		post := 0
		if pre > 0 {
			post, err = syscall.Getxattr(path, xattr, dest)
			if err != nil || post < 0 {
				return nil, err
			}
		}

		if post != pre {
			return nil, e1
		}

		xattrs[xattr] = string(dest)
	}

	return xattrs, nil
}

// GetAllXattr retrieves all extended attributes associated with a file,
// directory or symbolic link.

GetAllXattr retrieves all extended attributes associated with a file directory or symbolic link .


func GetErrno(err error) (errno error, iserrno bool) {
	sysErr, ok := err.(*os.SyscallError)
	if ok {
		return sysErr.Err, true
	}

	pathErr, ok := err.(*os.PathError)
	if ok {
		return pathErr.Err, true
	}

	tmpErrno, ok := err.(syscall.Errno)
	if ok {
		return tmpErrno, true
	}

	return nil, false
}

func GetErrno ( err error ) ( errno error , iserrno bool ) { sysErr , ok := err . ( * os . SyscallError ) if ok { return sysErr . Err , true } pathErr , ok := err . ( * os . PathError ) if ok { return pathErr . Err , true } tmpErrno , ok := err . ( syscall . Errno ) if ok { return tmpErrno , true } return nil , false }


func Uname() (*Utsname, error) {
	/*
	 * Based on: https://groups.google.com/forum/#!topic/golang-nuts/Jel8Bb-YwX8
	 * there is really no better way to do this, which is
	 * unfortunate. Also, we ditch the more accepted CharsToString
	 * version in that thread, since it doesn't seem as portable,
	 * viz. github issue #206.
	 */

	uname := syscall.Utsname{}
	err := syscall.Uname(&uname)
	if err != nil {
		return nil, err
	}

	return &Utsname{
		Sysname:    intArrayToString(uname.Sysname),
		Nodename:   intArrayToString(uname.Nodename),
		Release:    intArrayToString(uname.Release),
		Version:    intArrayToString(uname.Version),
		Machine:    intArrayToString(uname.Machine),
		Domainname: intArrayToString(uname.Domainname),
	}, nil
}


func RegisterStmt(sql string) int {
	code := len(stmts)
	stmts[code] = sql
	return code
}

func RegisterStmt ( sql string ) int { code := len ( stmts ) stmts [ code ] = sql return code }

// RegisterStmt register a SQL statement.
//
// Registered statements will be prepared upfront and re-used, to speed up
// execution.
//
// Return a unique registration code.

RegisterStmt register a SQL statement . Registered statements will be prepared upfront and re - used to speed up execution . Return a unique registration code .


func PrepareStmts(db *sql.DB) (map[int]*sql.Stmt, error) {
	index := map[int]*sql.Stmt{}

	for code, sql := range stmts {
		stmt, err := db.Prepare(sql)
		if err != nil {
			return nil, errors.Wrapf(err, "%q", sql)
		}
		index[code] = stmt
	}

	return index, nil
}

func PrepareStmts ( db * sql . DB ) ( map [ int ] * sql . Stmt , error ) { index := map [ int ] * sql . Stmt { } for code , sql := range stmts { stmt , err := db . Prepare ( sql ) if err != nil { return nil , errors . Wrapf ( err , " " , sql ) } index [ code ] = stmt } return index , nil }

// PrepareStmts prepares all registered statements and returns an index from
// statement code to prepared statement object.

PrepareStmts prepares all registered statements and returns an index from statement code to prepared statement object .


func NewGateway(db *db.Node, cert *shared.CertInfo, options ...Option) (*Gateway, error) {
	ctx, cancel := context.WithCancel(context.Background())

	o := newOptions()
	for _, option := range options {
		option(o)

	}

	gateway := &Gateway{
		db:        db,
		cert:      cert,
		options:   o,
		ctx:       ctx,
		cancel:    cancel,
		upgradeCh: make(chan struct{}, 16),
		acceptCh:  make(chan net.Conn),
		store:     &dqliteServerStore{},
	}

	err := gateway.init()
	if err != nil {
		return nil, err
	}

	return gateway, nil
}

func NewGateway ( db * db . Node , cert * shared . CertInfo , options ... Option ) ( * Gateway , error ) { ctx , cancel := context . WithCancel ( context . Background ( ) ) o := newOptions ( ) for _ , option := range options { option ( o ) } gateway := & Gateway { db : db , cert : cert , options : o , ctx : ctx , cancel : cancel , upgradeCh : make ( chan struct { } , 16 ) , acceptCh : make ( chan net . Conn ) , store : & dqliteServerStore { } , } err := gateway . init ( ) if err != nil { return nil , err } return gateway , nil }

// NewGateway creates a new Gateway for managing access to the dqlite cluster.
//
// When a new gateway is created, the node-level database is queried to check
// what kind of role this node plays and if it's exposed over the network. It
// will initialize internal data structures accordingly, for example starting a
// dqlite driver if this node is a database node.
//
// After creation, the Daemon is expected to expose whatever http handlers the
// HandlerFuncs method returns and to access the dqlite cluster using the gRPC
// dialer returned by the Dialer method.

NewGateway creates a new Gateway for managing access to the dqlite cluster . When a new gateway is created the node - level database is queried to check what kind of role this node plays and if it s exposed over the network . It will initialize internal data structures accordingly for example starting a dqlite driver if this node is a database node . After creation the Daemon is expected to expose whatever http handlers the HandlerFuncs method returns and to access the dqlite cluster using the gRPC dialer returned by the Dialer method .


func (g *Gateway) DialFunc() dqlite.DialFunc {
	return func(ctx context.Context, address string) (net.Conn, error) {
		// Memory connection.
		if g.memoryDial != nil {
			return g.memoryDial(ctx, address)
		}

		return dqliteNetworkDial(ctx, address, g.cert)
	}
}

func
(
g
*
Gateway
)
DialFunc
(
)
dqlite
.
DialFunc
{
return
func
(
ctx
context
.
Context
,
address
string
)
(
net
.
Conn
,
error
)
{
// Memory connection.
if
g
.
memoryDial
!=
{
return
g
.
memoryDial
(
ctx
,
address
)
}
return
dqliteNetworkDial
(
ctx
,
address
,
g
.
cert
)
}
}

// DialFunc returns a dial function that can be used to connect to one of the
// dqlite nodes.

DialFunc returns a dial function that can be used to connect to one of the dqlite nodes .


func (g *Gateway) Shutdown() error {
	logger.Debugf("Stop database gateway")

	if g.raft != nil {
		err := g.raft.Shutdown()
		if err != nil {
			return errors.Wrap(err, "Failed to shutdown raft")
		}
	}

	if g.server != nil {
		g.Sync()
		g.server.Close()

		// Unset the memory dial, since Shutdown() is also called for
		// switching between in-memory and network mode.
		g.memoryDial = nil
	}

	return nil
}

// Shutdown this gateway, stopping the gRPC server and possibly the raft factory.

Shutdown this gateway stopping the gRPC server and possibly the raft factory .


func (g *Gateway) Sync() {
	if g.server == nil {
		return
	}

	dir := filepath.Join(g.db.Dir(), "global")
	err := g.server.Dump("db.bin", dir)
	if err != nil {
		// Just log a warning, since this is not fatal.
		logger.Warnf("Failed to dump database to disk: %v", err)
	}
}

// Sync dumps the content of the database to disk. This is useful for
// inspection purposes, and it's also needed by the activateifneeded command so
// it can inspect the database in order to decide whether to activate the
// daemon or not.

Sync dumps the content of the database to disk . This is useful for inspection purposes and it s also needed by the activateifneeded command so it can inspect the database in order to decide whether to activate the daemon or not .


func (g *Gateway) Reset(cert *shared.CertInfo) error {
	err := g.Shutdown()
	if err != nil {
		return err
	}
	err = os.RemoveAll(filepath.Join(g.db.Dir(), "global"))
	if err != nil {
		return err
	}
	err = g.db.Transaction(func(tx *db.NodeTx) error {
		return tx.RaftNodesReplace(nil)
	})
	if err != nil {
		return err
	}
	g.cert = cert
	return g.init()
}

func ( g * Gateway ) Reset ( cert * shared . CertInfo ) error { err := g . Shutdown ( ) if err != nil { return err } err = os . RemoveAll ( filepath . Join ( g . db . Dir ( ) , " " ) ) if err != nil { return err } err = g . db . Transaction ( func ( tx * db . NodeTx ) error { return tx . RaftNodesReplace ( nil ) } ) if err != nil { return err } g . cert = cert return g . init ( ) }

// Reset the gateway, shutting it down and starting against from scratch using
// the given certificate.
//
// This is used when disabling clustering on a node.

Reset the gateway shutting it down and starting against from scratch using the given certificate . This is used when disabling clustering on a node .


func (g *Gateway) LeaderAddress() (string, error) {
	// If we aren't clustered, return an error.
	if g.memoryDial != nil {
		return "", fmt.Errorf("Node is not clustered")
	}

	ctx, cancel := context.WithTimeout(g.ctx, 5*time.Second)
	defer cancel()

	// If this is a raft node, return the address of the current leader, or
	// wait a bit until one is elected.
	if g.raft != nil {
		for ctx.Err() == nil {
			address := string(g.raft.Raft().Leader())
			if address != "" {
				return address, nil
			}
			time.Sleep(time.Second)
		}
		return "", ctx.Err()

	}

	// If this isn't a raft node, contact a raft node and ask for the
	// address of the current leader.
	config, err := tlsClientConfig(g.cert)
	if err != nil {
		return "", err
	}
	addresses := []string{}
	err = g.db.Transaction(func(tx *db.NodeTx) error {
		nodes, err := tx.RaftNodes()
		if err != nil {
			return err
		}
		for _, node := range nodes {
			addresses = append(addresses, node.Address)
		}
		return nil
	})
	if err != nil {
		return "", errors.Wrap(err, "Failed to fetch raft nodes addresses")
	}

	if len(addresses) == 0 {
		// This should never happen because the raft_nodes table should
		// be never empty for a clustered node, but check it for good
		// measure.
		return "", fmt.Errorf("No raft node known")
	}

	for _, address := range addresses {
		url := fmt.Sprintf("https://%s%s", address, databaseEndpoint)
		request, err := http.NewRequest("GET", url, nil)
		if err != nil {
			return "", err
		}
		request = request.WithContext(ctx)
		client := &http.Client{Transport: &http.Transport{TLSClientConfig: config}}
		response, err := client.Do(request)
		if err != nil {
			logger.Debugf("Failed to fetch leader address from %s", address)
			continue
		}
		if response.StatusCode != http.StatusOK {
			logger.Debugf("Request for leader address from %s failed", address)
			continue
		}
		info := map[string]string{}
		err = shared.ReadToJSON(response.Body, &info)
		if err != nil {
			logger.Debugf("Failed to parse leader address from %s", address)
			continue
		}
		leader := info["leader"]
		if leader == "" {
			logger.Debugf("Raft node %s returned no leader address", address)
			continue
		}
		return leader, nil
	}

	return "", fmt.Errorf("RAFT cluster is unavailable")
}

// LeaderAddress returns the address of the current raft leader.

LeaderAddress returns the address of the current raft leader .


func (g *Gateway) waitLeadership() error {
	n := 80
	sleep := 250 * time.Millisecond
	for i := 0; i < n; i++ {
		if g.raft.raft.State() == raft.Leader {
			return nil
		}
		time.Sleep(sleep)
	}
	return fmt.Errorf("RAFT node did not self-elect within %s", time.Duration(n)*sleep)
}

func ( g * Gateway ) waitLeadership ( ) error { n := 80 sleep := 250 * time . Millisecond for i := 0 ; i < n ; i ++ { if g . raft . raft . State ( ) == raft . Leader { return nil } time . Sleep ( sleep ) } return fmt . Errorf ( " " , time . Duration ( n ) * sleep ) }

// Wait for the raft node to become leader. Should only be used by Bootstrap,
// since we know that we'll self elect.

Wait for the raft node to become leader . Should only be used by Bootstrap since we know that we ll self elect .


func (g *Gateway) currentRaftNodes() ([]db.RaftNode, error) {
	if g.raft == nil {
		return nil, raft.ErrNotLeader
	}
	servers, err := g.raft.Servers()
	if err != nil {
		return nil, err
	}
	provider := raftAddressProvider{db: g.db}
	nodes := make([]db.RaftNode, len(servers))
	for i, server := range servers {
		address, err := provider.ServerAddr(server.ID)
		if err != nil {
			if err != db.ErrNoSuchObject {
				return nil, errors.Wrap(err, "Failed to fetch raft server address")
			}
			// Use the initial address as fallback. This is an edge
			// case that happens when a new leader is elected and
			// its raft_nodes table is not fully up-to-date yet.
			address = server.Address
		}
		id, err := strconv.Atoi(string(server.ID))
		if err != nil {
			return nil, errors.Wrap(err, "Non-numeric server ID")
		}
		nodes[i].ID = int64(id)
		nodes[i].Address = string(address)
	}
	return nodes, nil
}

// Return information about the LXD nodes that a currently part of the raft
// cluster, as configured in the raft log. It returns an error if this node is
// not the leader.

Return information about the LXD nodes that a currently part of the raft cluster as configured in the raft log . It returns an error if this node is not the leader .


func (g *Gateway) cachedRaftNodes() ([]string, error) {
	var addresses []string
	err := g.db.Transaction(func(tx *db.NodeTx) error {
		var err error
		addresses, err = tx.RaftNodeAddresses()
		return err
	})
	if err != nil {
		return nil, errors.Wrap(err, "Failed to fetch raft nodes")
	}
	return addresses, nil
}

func ( g * Gateway ) cachedRaftNodes ( ) ( [ ] string , error ) { var addresses [ ] string err := g . db . Transaction ( func ( tx * db . NodeTx ) error { var err error addresses , err = tx . RaftNodeAddresses ( ) return err } ) if err != nil { return nil , errors . Wrap ( err , " " ) } return addresses , nil }

// Return the addresses of the raft nodes as stored in the node-level
// database.
//
// These values might leg behind the actual values, and are refreshed
// periodically during heartbeats.

Return the addresses of the raft nodes as stored in the node - level database . These values might leg behind the actual values and are refreshed periodically during heartbeats .


func dqliteMemoryDial(listener net.Listener) dqlite.DialFunc {
	return func(ctx context.Context, address string) (net.Conn, error) {
		return net.Dial("unix", listener.Addr().String())
	}
}

func dqliteMemoryDial ( listener net . Listener ) dqlite . DialFunc { return func ( ctx context . Context , address string ) ( net . Conn , error ) { return net . Dial ( " " , listener . Addr ( ) . String ( ) ) } }

// Create a dial function that connects to the given listener.

Create a dial function that connects to the given listener .


func DqliteLog(l dqlite.LogLevel, format string, a ...interface{}) {
	format = fmt.Sprintf("Dqlite: %s", format)
	switch l {
	case dqlite.LogDebug:
		logger.Debugf(format, a...)
	case dqlite.LogInfo:
		logger.Debugf(format, a...)
	case dqlite.LogWarn:
		logger.Warnf(format, a...)
	case dqlite.LogError:
		logger.Errorf(format, a...)
	}
}

func DqliteLog ( l dqlite . LogLevel , format string , a ... interface { } ) { format = fmt . Sprintf ( " " , format ) switch l { case dqlite . LogDebug : logger . Debugf ( format , a ... ) case dqlite . LogInfo : logger . Debugf ( format , a ... ) case dqlite . LogWarn : logger . Warnf ( format , a ... ) case dqlite . LogError : logger . Errorf ( format , a ... ) } }

// DqliteLog redirects dqlite's logs to our own logger

DqliteLog redirects dqlite s logs to our own logger


func (r *Response) MetadataAsMap() (map[string]interface{}, error) {
	ret := map[string]interface{}{}
	err := r.MetadataAsStruct(&ret)
	if err != nil {
		return nil, err
	}

	return ret, nil
}

func ( r * Response ) MetadataAsMap ( ) ( map [ string ] interface { } , error ) { ret := map [ string ] interface { } { } err := r . MetadataAsStruct ( & ret ) if err != nil { return nil , err } return ret , nil }

// MetadataAsMap parses the Response metadata into a map


func (r *Response) MetadataAsOperation() (*Operation, error) {
	op := Operation{}
	err := r.MetadataAsStruct(&op)
	if err != nil {
		return nil, err
	}

	return &op, nil
}

func ( r * Response ) MetadataAsOperation ( ) ( * Operation , error ) { op := Operation { } err := r . MetadataAsStruct ( & op ) if err != nil { return nil , err } return & op , nil }

// MetadataAsOperation turns the Response metadata into an Operation


func (r *Response) MetadataAsStringSlice() ([]string, error) {
	sl := []string{}
	err := r.MetadataAsStruct(&sl)
	if err != nil {
		return nil, err
	}

	return sl, nil
}

func ( r * Response ) MetadataAsStringSlice ( ) ( [ ] string , error ) { sl := [ ] string { } err := r . MetadataAsStruct ( & sl ) if err != nil { return nil , err } return sl , nil }

// MetadataAsStringSlice parses the Response metadata into a slice of string


func (r *Response) MetadataAsStruct(target interface{}) error {
	return json.Unmarshal(r.Metadata, &target)
}

func ( r * Response ) MetadataAsStruct ( target interface { } ) error { return json . Unmarshal ( r . Metadata , & target ) }

// MetadataAsStruct parses the Response metadata into a provided struct


func (r *CSVReport) Load() error {
	file, err := os.Open(r.Filename)
	if err != nil {
		return err
	}
	defer file.Close()

	reader := csv.NewReader(file)
	for line := 1; err != io.EOF; line++ {
		record, err := reader.Read()
		if err == io.EOF {
			break
		} else if err != nil {
			return err
		}

		err = r.addRecord(record)
		if err != nil {
			return err
		}
	}
	logf("Loaded report file %s", r.Filename)
	return nil
}

func ( r * CSVReport ) Load ( ) error { file , err := os . Open ( r . Filename ) if err != nil { return err } defer file . Close ( ) reader := csv . NewReader ( file ) for line := 1 ; err != io . EOF ; line ++ { record , err := reader . Read ( ) if err == io . EOF { break } else if err != nil { return err } err = r . addRecord ( record ) if err != nil { return err } } logf ( " " , r . Filename ) return nil }

// Load reads current content of the filename and loads records.

Load reads current content of the filename and loads records .


func (r *CSVReport) Write() error {
	file, err := os.OpenFile(r.Filename, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0640)
	if err != nil {
		return err
	}
	defer file.Close()

	writer := csv.NewWriter(file)
	err = writer.WriteAll(r.records)
	if err != nil {
		return err
	}

	logf("Written report file %s", r.Filename)
	return nil
}

func ( r * CSVReport ) Write ( ) error { file , err := os . OpenFile ( r . Filename , os . O_WRONLY | os . O_CREATE | os . O_TRUNC , 0640 ) if err != nil { return err } defer file . Close ( ) writer := csv . NewWriter ( file ) err = writer . WriteAll ( r . records ) if err != nil { return err } logf ( " " , r . Filename ) return nil }

// Write writes current records to file.


func (r *CSVReport) AddRecord(label string, elapsed time.Duration) error {
	if len(r.records) == 0 {
		r.addRecord(csvFields)
	}

	record := []string{
		fmt.Sprintf("%d", time.Now().UnixNano()/int64(time.Millisecond)), // timestamp
		fmt.Sprintf("%d", elapsed/time.Millisecond),
		label,
		"",     // responseCode is not used
		"true", // success"
	}
	return r.addRecord(record)
}

func
(
r
*
CSVReport
)
AddRecord
(
label
string
,
elapsed
time
.
Duration
)
error
{
if
len
(
r
.
records
)
==
0
{
r
.
addRecord
(
csvFields
)
}
record
:=
[
]
string
{
fmt
.
Sprintf
(
"
"
,
time
.
Now
(
)
.
UnixNano
(
)
/
int64
(
time
.
Millisecond
)
)
,
// timestamp
fmt
.
Sprintf
(
"
"
,
elapsed
/
time
.
Millisecond
)
,
label
,
"
"
,
// responseCode is not used
"
"
,
// success"
}
return
r
.
addRecord
(
record
)
}

// AddRecord adds a record to the report.


func LoadConfig(path string) (*Config, error) {
	// Open the config file
	content, err := ioutil.ReadFile(path)
	if err != nil {
		return nil, fmt.Errorf("Unable to read the configuration file: %v", err)
	}

	// Decode the yaml document
	c := NewConfig(filepath.Dir(path), false)
	err = yaml.Unmarshal(content, &c)
	if err != nil {
		return nil, fmt.Errorf("Unable to decode the configuration: %v", err)
	}

	for k, r := range c.Remotes {
		if !r.Public && r.AuthType == "" {
			r.AuthType = "tls"
			c.Remotes[k] = r
		}
	}

	// Set default values
	if c.Remotes == nil {
		c.Remotes = make(map[string]Remote)
	}

	// Apply the static remotes
	for k, v := range StaticRemotes {
		if c.Remotes[k].Project != "" {
			v.Project = c.Remotes[k].Project
		}

		c.Remotes[k] = v
	}

	// NOTE: Remove this once we only see a small fraction of non-simplestreams users
	// Upgrade users to the "simplestreams" protocol
	images, ok := c.Remotes["images"]
	if ok && images.Protocol != ImagesRemote.Protocol && images.Addr == ImagesRemote.Addr {
		c.Remotes["images"] = ImagesRemote
		c.SaveConfig(path)
	}

	return c, nil
}

// LoadConfig reads the configuration from the config path; if the path does
// not exist, it returns a default configuration.

LoadConfig reads the configuration from the config path ; if the path does not exist it returns a default configuration .


func (c *Config) SaveConfig(path string) error {
	// Create a new copy for the config file
	conf := Config{}
	err := shared.DeepCopy(c, &conf)
	if err != nil {
		return fmt.Errorf("Unable to copy the configuration: %v", err)
	}

	// Remove the static remotes
	for k := range StaticRemotes {
		if k == "local" {
			continue
		}

		delete(conf.Remotes, k)
	}

	// Create the config file (or truncate an existing one)
	f, err := os.Create(path)
	if err != nil {
		return fmt.Errorf("Unable to create the configuration file: %v", err)
	}
	defer f.Close()

	// Write the new config
	data, err := yaml.Marshal(conf)
	if err != nil {
		return fmt.Errorf("Unable to marshal the configuration: %v", err)
	}

	_, err = f.Write(data)
	if err != nil {
		return fmt.Errorf("Unable to write the configuration: %v", err)
	}

	return nil
}

// SaveConfig writes the provided configuration to the config file.

SaveConfig writes the provided configuration to the config file .


func (l ChrootLoader) Get(path string) (io.Reader, error) {
	// Get the full path
	path, err := filepath.EvalSymlinks(path)
	if err != nil {
		return nil, err
	}

	basePath, err := filepath.EvalSymlinks(l.Path)
	if err != nil {
		return nil, err
	}

	// Validate that we're under the expected prefix
	if !strings.HasPrefix(path, basePath) {
		return nil, fmt.Errorf("Attempting to access a file outside the container")
	}

	// Open and read the file
	buf, err := ioutil.ReadFile(path)
	if err != nil {
		return nil, err
	}

	return bytes.NewReader(buf), nil
}

// Get reads the path's content from your local filesystem.

Get reads the path s content from your local filesystem .


func (c *Config) ConfigPath(paths ...string) string {
	path := []string{c.ConfigDir}
	path = append(path, paths...)

	return filepath.Join(path...)
}

func ( c * Config ) ConfigPath ( paths ... string ) string { path := [ ] string { c . ConfigDir } path = append ( path , paths ... ) return filepath . Join ( path ... ) }

// ConfigPath returns a joined path of the configuration directory and passed arguments


func (c *Config) ServerCertPath(remote string) string {
	return c.ConfigPath("servercerts", fmt.Sprintf("%s.crt", remote))
}

func ( c * Config ) ServerCertPath ( remote string ) string { return c . ConfigPath ( " " , fmt . Sprintf ( " " , remote ) ) }

// ServerCertPath returns the path for the remote's server certificate

ServerCertPath returns the path for the remote s server certificate


func NewConfig(configDir string, defaults bool) *Config {
	config := &Config{ConfigDir: configDir}
	if defaults {
		config.Remotes = DefaultRemotes
		config.DefaultRemote = "local"
	}

	return config
}

func NewConfig ( configDir string , defaults bool ) * Config { config := & Config { ConfigDir : configDir } if defaults { config . Remotes = DefaultRemotes config . DefaultRemote = " " } return config }

// NewConfig returns a Config, optionally using default remotes.

NewConfig returns a Config optionally using default remotes .


func (s *migrationSourceWs) checkForPreDumpSupport() (bool, int) {
	// Ask CRIU if this architecture/kernel/criu combination
	// supports pre-copy (dirty memory tracking)
	criuMigrationArgs := CriuMigrationArgs{
		cmd:          lxc.MIGRATE_FEATURE_CHECK,
		stateDir:     "",
		function:     "feature-check",
		stop:         false,
		actionScript: false,
		dumpDir:      "",
		preDumpDir:   "",
		features:     lxc.FEATURE_MEM_TRACK,
	}
	err := s.container.Migrate(&criuMigrationArgs)

	if err != nil {
		// CRIU says it does not know about dirty memory tracking.
		// This means the rest of this function is irrelevant.
		return false, 0
	}

	// CRIU says it can actually do pre-dump. Let's set it to true
	// unless the user wants something else.
	use_pre_dumps := true

	// What does the configuration say about pre-copy
	tmp := s.container.ExpandedConfig()["migration.incremental.memory"]

	if tmp != "" {
		use_pre_dumps = shared.IsTrue(tmp)
	}

	var max_iterations int

	// migration.incremental.memory.iterations is the value after which the
	// container will be definitely migrated, even if the remaining number
	// of memory pages is below the defined threshold.
	tmp = s.container.ExpandedConfig()["migration.incremental.memory.iterations"]
	if tmp != "" {
		max_iterations, _ = strconv.Atoi(tmp)
	} else {
		// default to 10
		max_iterations = 10
	}
	if max_iterations > 999 {
		// the pre-dump directory is hardcoded to a string
		// with maximal 3 digits. 999 pre-dumps makes no
		// sense at all, but let's make sure the number
		// is not higher than this.
		max_iterations = 999
	}
	logger.Debugf("Using maximal %d iterations for pre-dumping", max_iterations)

	return use_pre_dumps, max_iterations
}

// Check if CRIU supports pre-dumping and number of
// pre-dump iterations

Check if CRIU supports pre - dumping and number of pre - dump iterations


func (s *migrationSourceWs) preDumpLoop(args *preDumpLoopArgs) (bool, error) {
	// Do a CRIU pre-dump
	criuMigrationArgs := CriuMigrationArgs{
		cmd:          lxc.MIGRATE_PRE_DUMP,
		stop:         false,
		actionScript: false,
		preDumpDir:   args.preDumpDir,
		dumpDir:      args.dumpDir,
		stateDir:     args.checkpointDir,
		function:     "migration",
	}

	logger.Debugf("Doing another pre-dump in %s", args.preDumpDir)

	final := args.final

	err := s.container.Migrate(&criuMigrationArgs)
	if err != nil {
		return final, err
	}

	// Send the pre-dump.
	ctName, _, _ := containerGetParentAndSnapshotName(s.container.Name())
	state := s.container.DaemonState()
	err = RsyncSend(ctName, shared.AddSlash(args.checkpointDir), s.criuConn, nil, args.rsyncFeatures, args.bwlimit, state.OS.ExecPath)
	if err != nil {
		return final, err
	}

	// Read the CRIU's 'stats-dump' file
	dumpPath := shared.AddSlash(args.checkpointDir)
	dumpPath += shared.AddSlash(args.dumpDir)
	written, skipped_parent, err := readCriuStatsDump(dumpPath)
	if err != nil {
		return final, err
	}

	logger.Debugf("CRIU pages written %d", written)
	logger.Debugf("CRIU pages skipped %d", skipped_parent)

	total_pages := written + skipped_parent

	percentage_skipped := int(100 - ((100 * written) / total_pages))

	logger.Debugf("CRIU pages skipped percentage %d%%", percentage_skipped)

	// threshold is the percentage of memory pages that needs
	// to be pre-copied for the pre-copy migration to stop.
	var threshold int
	tmp := s.container.ExpandedConfig()["migration.incremental.memory.goal"]
	if tmp != "" {
		threshold, _ = strconv.Atoi(tmp)
	} else {
		// defaults to 70%
		threshold = 70
	}

	if percentage_skipped > threshold {
		logger.Debugf("Memory pages skipped (%d%%) due to pre-copy is larger than threshold (%d%%)", percentage_skipped, threshold)
		logger.Debugf("This was the last pre-dump; next dump is the final dump")
		final = true
	}

	// If in pre-dump mode, the receiving side
	// expects a message to know if this was the
	// last pre-dump
	logger.Debugf("Sending another header")
	sync := migration.MigrationSync{
		FinalPreDump: proto.Bool(final),
	}

	data, err := proto.Marshal(&sync)

	if err != nil {
		return final, err
	}

	err = s.criuConn.WriteMessage(websocket.BinaryMessage, data)
	if err != nil {
		s.sendControl(err)
		return final, err
	}
	logger.Debugf("Sending another header done")

	return final, nil
}

// The function preDumpLoop is the main logic behind the pre-copy migration.
// This function contains the actual pre-dump, the corresponding rsync
// transfer and it tells the outer loop to abort if the threshold
// of memory pages transferred by pre-dumping has been reached.

The function preDumpLoop is the main logic behind the pre - copy migration . This function contains the actual pre - dump the corresponding rsync transfer and it tells the outer loop to abort if the threshold of memory pages transferred by pre - dumping has been reached .


func newRoot() *cobra.Command {
	cmd := &cobra.Command{
		Use:   "lxd-generate",
		Short: "Code generation tool for LXD development",
		Long: `This is the entry point for all "go:generate" directives
used in LXD's source code.`,
		RunE: func(cmd *cobra.Command, args []string) error {
			return fmt.Errorf("Not implemented")
		},
	}
	cmd.AddCommand(newDb())

	return cmd
}


func APIExtensionsCount() int {
	count := len(APIExtensions)

	// This environment variable is an internal one to force the code
	// to believe that we an API extensions version greater than we
	// actually have. It's used by integration tests to exercise the
	// cluster upgrade process.
	artificialBump := os.Getenv("LXD_ARTIFICIALLY_BUMP_API_EXTENSIONS")
	if artificialBump != "" {
		n, err := strconv.Atoi(artificialBump)
		if err == nil {
			count += n
		}
	}

	return count
}

// APIExtensionsCount returns the number of available API extensions.

APIExtensionsCount returns the number of available API extensions .


func SelectURIs(stmt *sql.Stmt, f func(a ...interface{}) string, args ...interface{}) ([]string, error) {
	rows, err := stmt.Query(args...)
	if err != nil {
		return nil, errors.Wrapf(err, "Failed to query URIs")
	}
	defer rows.Close()

	columns, err := rows.Columns()
	if err != nil {
		return nil, errors.Wrap(err, "Rows columns")
	}

	params := make([]interface{}, len(columns))

	dest := make([]interface{}, len(params))
	for i := range params {
		params[i] = ""
		dest[i] = &params[i]
	}

	uris := []string{}

	for rows.Next() {
		err := rows.Scan(dest...)
		if err != nil {
			return nil, errors.Wrapf(err, "Failed to scan URI params")
		}

		uri := f(params...)
		uris = append(uris, uri)
	}

	err = rows.Err()
	if err != nil {
		return nil, errors.Wrapf(err, "Failed to close URI result set")
	}

	return uris, nil
}

func SelectURIs ( stmt * sql . Stmt , f func ( a ... interface { } ) string , args ... interface { } ) ( [ ] string , error ) { rows , err := stmt . Query ( args ... ) if err != nil { return nil , errors . Wrapf ( err , " " ) } defer rows . Close ( ) columns , err := rows . Columns ( ) if err != nil { return nil , errors . Wrap ( err , " " ) } params := make ( [ ] interface { } , len ( columns ) ) dest := make ( [ ] interface { } , len ( params ) ) for i := range params { params [ i ] = " " dest [ i ] = & params [ i ] } uris := [ ] string { } for rows . Next ( ) { err := rows . Scan ( dest ... ) if err != nil { return nil , errors . Wrapf ( err , " " ) } uri := f ( params ... ) uris = append ( uris , uri ) } err = rows . Err ( ) if err != nil { return nil , errors . Wrapf ( err , " " ) } return uris , nil }

// SelectURIs returns a list of LXD API URI strings for the resource yielded by
// the given query.
//
// The f argument must be a function that formats the entity URI using the
// columns yielded by the query.

SelectURIs returns a list of LXD API URI strings for the resource yielded by the given query . The f argument must be a function that formats the entity URI using the columns yielded by the query .


func SelectStrings(tx *sql.Tx, query string, args ...interface{}) ([]string, error) {
	values := []string{}
	scan := func(rows *sql.Rows) error {
		var value string
		err := rows.Scan(&value)
		if err != nil {
			return err
		}
		values = append(values, value)
		return nil
	}

	err := scanSingleColumn(tx, query, args, "TEXT", scan)
	if err != nil {
		return nil, err
	}

	return values, nil
}

func SelectStrings ( tx * sql . Tx , query string , args ... interface { } ) ( [ ] string , error ) { values := [ ] string { } scan := func ( rows * sql . Rows ) error { var value string err := rows . Scan ( & value ) if err != nil { return err } values = append ( values , value ) return nil } err := scanSingleColumn ( tx , query , args , " " , scan ) if err != nil { return nil , err } return values , nil }

// SelectStrings executes a statement which must yield rows with a single string
// column. It returns the list of column values.

SelectStrings executes a statement which must yield rows with a single string column . It returns the list of column values .


func scanSingleColumn(tx *sql.Tx, query string, args []interface{}, typeName string, scan scanFunc) error {
	rows, err := tx.Query(query, args...)
	if err != nil {
		return err
	}
	defer rows.Close()

	for rows.Next() {
		err := scan(rows)
		if err != nil {
			return err
		}
	}

	err = rows.Err()
	if err != nil {
		return err
	}
	return nil
}

func scanSingleColumn ( tx * sql . Tx , query string , args [ ] interface { } , typeName string , scan scanFunc ) error { rows , err := tx . Query ( query , args ... ) if err != nil { return err } defer rows . Close ( ) for rows . Next ( ) { err := scan ( rows ) if err != nil { return err } } err = rows . Err ( ) if err != nil { return err } return nil }

// Execute the given query and ensure that it yields rows with a single column
// of the given database type. For every row yielded, execute the given
// scanner.

Execute the given query and ensure that it yields rows with a single column of the given database type . For every row yielded execute the given scanner .


func LazyHandler(h Handler) Handler {
	return FuncHandler(func(r *Record) error {
		// go through the values (odd indices) and reassign
		// the values of any lazy fn to the result of its execution
		hadErr := false
		for i := 1; i < len(r.Ctx); i += 2 {
			lz, ok := r.Ctx[i].(Lazy)
			if ok {
				v, err := evaluateLazy(lz)
				if err != nil {
					hadErr = true
					r.Ctx[i] = err
				} else {
					if cs, ok := v.(stack.Trace); ok {
						v = cs.TrimBelow(stack.Call(r.CallPC[0])).
							TrimRuntime()
					}
					r.Ctx[i] = v
				}
			}
		}

		if hadErr {
			r.Ctx = append(r.Ctx, errorKey, "bad lazy")
		}

		return h.Log(r)
	})
}

// LazyHandler writes all values to the wrapped handler after evaluating
// any lazy functions in the record's context. It is already wrapped
// around StreamHandler and SyslogHandler in this library, you'll only need
// it if you write your own Handler.

LazyHandler writes all values to the wrapped handler after evaluating any lazy functions in the record s context . It is already wrapped around StreamHandler and SyslogHandler in this library you ll only need it if you write your own Handler .


func Callers() Trace {
	pcs := poolBuf()
	pcs = pcs[:cap(pcs)]
	n := runtime.Callers(2, pcs)
	cs := make([]Call, n)
	for i, pc := range pcs[:n] {
		cs[i] = Call(pc)
	}
	putPoolBuf(pcs)
	return cs
}

func Callers ( ) Trace { pcs := poolBuf ( ) pcs = pcs [ : cap ( pcs ) ] n := runtime . Callers ( 2 , pcs ) cs := make ( [ ] Call , n ) for i , pc := range pcs [ : n ] { cs [ i ] = Call ( pc ) } putPoolBuf ( pcs ) return cs }

// Callers returns a Trace for the current goroutine with element 0
// identifying the calling function.

Callers returns a Trace for the current goroutine with element 0 identifying the calling function .


func (pc Call) name() string {
	pcFix := uintptr(pc) - 1 // work around for go issue #7690
	fn := runtime.FuncForPC(pcFix)
	if fn == nil {
		return "???"
	}
	return fn.Name()
}

func
(
pc
Call
)
name
(
)
string
{
pcFix
:=
uintptr
(
pc
)
1
// work around for go issue #7690
fn
:=
runtime
.
FuncForPC
(
pcFix
)
if
fn
==
{
return
"
"
}
return
fn
.
Name
(
)
}

// name returns the import path qualified name of the function containing the
// call.

name returns the import path qualified name of the function containing the call .


func (pcs Trace) TrimBelow(pc Call) Trace {
	for len(pcs) > 0 && pcs[0] != pc {
		pcs = pcs[1:]
	}
	return pcs
}

func ( pcs Trace ) TrimBelow ( pc Call ) Trace { for len ( pcs ) > 0 && pcs [ 0 ] != pc { pcs = pcs [ 1 : ] } return pcs }

// TrimBelow returns a slice of the Trace with all entries below pc removed.

TrimBelow returns a slice of the Trace with all entries below pc removed .


func (pcs Trace) TrimAbove(pc Call) Trace {
	for len(pcs) > 0 && pcs[len(pcs)-1] != pc {
		pcs = pcs[:len(pcs)-1]
	}
	return pcs
}

func ( pcs Trace ) TrimAbove ( pc Call ) Trace { for len ( pcs ) > 0 && pcs [ len ( pcs ) - 1 ] != pc { pcs = pcs [ : len ( pcs ) - 1 ] } return pcs }

// TrimAbove returns a slice of the Trace with all entries above pc removed.

TrimAbove returns a slice of the Trace with all entries above pc removed .


func (pcs Trace) TrimBelowName(name string) Trace {
	for len(pcs) > 0 && pcs[0].name() != name {
		pcs = pcs[1:]
	}
	return pcs
}

func ( pcs Trace ) TrimBelowName ( name string ) Trace { for len ( pcs ) > 0 && pcs [ 0 ] . name ( ) != name { pcs = pcs [ 1 : ] } return pcs }

// TrimBelowName returns a slice of the Trace with all entries below the
// lowest with function name name removed.

TrimBelowName returns a slice of the Trace with all entries below the lowest with function name name removed .


func (pcs Trace) TrimAboveName(name string) Trace {
	for len(pcs) > 0 && pcs[len(pcs)-1].name() != name {
		pcs = pcs[:len(pcs)-1]
	}
	return pcs
}

func ( pcs Trace ) TrimAboveName ( name string ) Trace { for len ( pcs ) > 0 && pcs [ len ( pcs ) - 1 ] . name ( ) != name { pcs = pcs [ : len ( pcs ) - 1 ] } return pcs }

// TrimAboveName returns a slice of the Trace with all entries above the
// highest with function name name removed.

TrimAboveName returns a slice of the Trace with all entries above the highest with function name name removed .


func (pcs Trace) TrimRuntime() Trace {
	for len(pcs) > 0 && inGoroot(pcs[len(pcs)-1].file()) {
		pcs = pcs[:len(pcs)-1]
	}
	return pcs
}

func ( pcs Trace ) TrimRuntime ( ) Trace { for len ( pcs ) > 0 && inGoroot ( pcs [ len ( pcs ) - 1 ] . file ( ) ) { pcs = pcs [ : len ( pcs ) - 1 ] } return pcs }

// TrimRuntime returns a slice of the Trace with the topmost entries from the
// go runtime removed. It considers any calls originating from files under
// GOROOT as part of the runtime.

TrimRuntime returns a slice of the Trace with the topmost entries from the go runtime removed . It considers any calls originating from files under GOROOT as part of the runtime .


func GetCaps(path string) ([]byte, error) {
	xattrs, err := shared.GetAllXattr(path)
	if err != nil {
		return nil, err
	}

	valueStr, ok := xattrs["security.capability"]
	if !ok {
		return nil, nil
	}

	return []byte(valueStr), nil
}

func GetCaps ( path string ) ( [ ] byte , error ) { xattrs , err := shared . GetAllXattr ( path ) if err != nil { return nil , err } valueStr , ok := xattrs [ " " ] if ! ok { return nil , nil } return [ ] byte ( valueStr ) , nil }

// GetCaps extracts the list of capabilities effective on the file


func SetCaps(path string, caps []byte, uid int64) error {
	cpath := C.CString(path)
	defer C.free(unsafe.Pointer(cpath))

	ccaps := C.CString(string(caps))
	defer C.free(unsafe.Pointer(ccaps))

	r := C.set_vfs_ns_caps(cpath, ccaps, C.ssize_t(len(caps)), C.uint32_t(uid))
	if r != 0 {
		return fmt.Errorf("Failed to apply capabilities to: %s", path)
	}

	return nil
}

func SetCaps ( path string , caps [ ] byte , uid int64 ) error { cpath := C . CString ( path ) defer C . free ( unsafe . Pointer ( cpath ) ) ccaps := C . CString ( string ( caps ) ) defer C . free ( unsafe . Pointer ( ccaps ) ) r := C . set_vfs_ns_caps ( cpath , ccaps , C . ssize_t ( len ( caps ) ) , C . uint32_t ( uid ) ) if r != 0 { return fmt . Errorf ( " " , path ) } return nil }

// SetCaps applies the caps for a particular root uid


func (pt *ProgressReader) Read(p []byte) (int, error) {
	// Do normal reader tasks
	n, err := pt.ReadCloser.Read(p)

	// Do the actual progress tracking
	if pt.Tracker != nil {
		pt.Tracker.total += int64(n)
		pt.Tracker.update(n)
	}

	return n, err
}

func
(
pt
*
ProgressReader
)
Read
(
p
[
]
byte
)
(
int
,
error
)
{
// Do normal reader tasks
n
,
err
:=
pt
.
ReadCloser
.
Read
(
p
)
// Do the actual progress tracking
if
pt
.
Tracker
!=
{
pt
.
Tracker
.
total
+=
int64
(
n
)
pt
.
Tracker
.
update
(
n
)
}
return
n
,
err
}

// Read in ProgressReader is the same as io.Read

Read in ProgressReader is the same as io . Read


func Supported(path string) (bool, error) {
	// Get the backing device
	devPath, err := devForPath(path)
	if err != nil {
		return false, err
	}

	// Call quotactl through CGo
	cDevPath := C.CString(devPath)
	defer C.free(unsafe.Pointer(cDevPath))

	return C.quota_supported(cDevPath) == 0, nil
}

func
Supported
(
path
string
)
(
bool
,
error
)
{
// Get the backing device
devPath
,
err
:=
devForPath
(
path
)
if
err
!=
{
return
false
,
err
}
// Call quotactl through CGo
cDevPath
:=
C
.
CString
(
devPath
)
defer
C
.
free
(
unsafe
.
Pointer
(
cDevPath
)
)
return
C
.
quota_supported
(
cDevPath
)
==
0
,
}

// Supported check if the given path supports project quotas


func GetProject(path string) (uint32, error) {
	// Call ioctl through CGo
	cPath := C.CString(path)
	defer C.free(unsafe.Pointer(cPath))

	id := C.quota_get_path(cPath)
	if id < 0 {
		return 0, fmt.Errorf("Failed to get project from '%s'", path)
	}

	return uint32(id), nil
}

func
GetProject
(
path
string
)
(
uint32
,
error
)
{
// Call ioctl through CGo
cPath
:=
C
.
CString
(
path
)
defer
C
.
free
(
unsafe
.
Pointer
(
cPath
)
)
id
:=
C
.
quota_get_path
(
cPath
)
if
id
<
0
{
return
0
,
fmt
.
Errorf
(
"
"
,
path
)
}
return
uint32
(
id
)
,
}

// GetProject returns the project quota ID for the given path


func SetProject(path string, id uint32) error {
	// Call ioctl through CGo
	cPath := C.CString(path)
	defer C.free(unsafe.Pointer(cPath))

	if C.quota_set_path(cPath, C.uint32_t(id)) != 0 {
		return fmt.Errorf("Failed to set project id '%d' on '%s'", id, path)
	}

	return nil
}

func
SetProject
(
path
string
,
id
uint32
)
error
{
// Call ioctl through CGo
cPath
:=
C
.
CString
(
path
)
defer
C
.
free
(
unsafe
.
Pointer
(
cPath
)
)
if
C
.
quota_set_path
(
cPath
,
C
.
uint32_t
(
id
)
)
!=
0
{
return
fmt
.
Errorf
(
"
"
,
id
,
path
)
}
return
}

// SetProject sets the project quota ID for the given path