Control GPIO of Rasberry PI using chaincode - Hyperledger Fabric V1.0 - iot

I'm trying to control LED using rpi that is a peer in hyperledger fabric network. My network (PC and RPI) is as follow:
A Certificate Authority (CA) — PC1
An Orderer — PC1
1 PEER (peer0) on — PC1
1 PEER (peer1) on — RP
CLI on —  RPI
I setup the above network successfully, and i'm able to run the chaincode example 2 that is provided by hyperledger fabric (install, query,invoke).
i have developed my own chaincode that can be used to turn on and off a LED connected to the rpi from the blockchain. The problem is that i'm getting the below error (Timeout):
Error: Error endorsing chaincode: rpc error: code = Unknown desc =
timeout expired while starting chaincode mychaincode:1.0
This is my chaincode:
package main
import (
"fmt"
"strconv"
"os"
"github.com/stianeikeland/go-rpio" //To Map GPIO of RPI
"github.com/hyperledger/fabric/core/chaincode/shim"
pb "github.com/hyperledger/fabric/protos/peer"
)
var (
pin = rpio.Pin(3)
)
// SimpleChaincode example simple Chaincode implementation
type SimpleChaincode struct {
}
func (t *SimpleChaincode) Init(stub shim.ChaincodeStubInterface) pb.Response {
fmt.Println("LED ON")
_, args := stub.GetFunctionAndParameters()
var A string // Entities
var Aval int // Asset holdings
var err error
if len(args) != 2 {
return shim.Error("Incorrect number of arguments. Expecting 2")
}
if err := rpio.Open(); err != nil {
fmt.Println(err)
os.Exit(1)
}
A = args[0]
Aval, err = strconv.Atoi(args[1])
if err != nil {
return shim.Error("Expecting integer value for asset holding")
}
fmt.Printf("Aval = %d", Aval)
if Aval == 1{
pin.High() //turn on
} else {
pin.Low() //turn off
}
// Write the state to the ledger
err = stub.PutState(A, []byte(strconv.Itoa(Aval)))
if err != nil {
return shim.Error(err.Error())
}
return shim.Success(nil)
}
func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface) pb.Response {
fmt.Println("ex02 Invoke")
function, args := stub.GetFunctionAndParameters()
if function == "invoke" {
// Make payment of X units from A to B
return t.invoke(stub, args)
} else if function == "delete" {
// Deletes an entity from its state
return t.delete(stub, args)
} else if function == "query" {
// the old "Query" is now implemtned in invoke
return t.query(stub, args)
}
return shim.Error("Invalid invoke function name. Expecting \"invoke\" \"delete\" \"query\"")
}
// Transaction makes payment of X units from A to B
func (t *SimpleChaincode) invoke(stub shim.ChaincodeStubInterface, args []string) pb.Response {
var A string // Entities
var Aval int // Asset holdings
var X int // Transaction value
var err error
if len(args) != 2 {
return shim.Error("Incorrect number of arguments. Expecting 2")
}
A = args[0]
// Get the state from the ledger
// TODO: will be nice to have a GetAllState call to ledger
Avalbytes, err := stub.GetState(A)
if err != nil {
return shim.Error("Failed to get state")
}
if Avalbytes == nil {
return shim.Error("Entity not found")
}
Aval, _ = strconv.Atoi(string(Avalbytes))
// Perform the execution
X, err = strconv.Atoi(args[1])
if err != nil {
return shim.Error("Invalid transaction amount, expecting a integer value")
}
Aval = X
fmt.Printf("Aval = %d", Aval)
if Aval == 1{
pin.High()
} else {
pin.Low()
}
// Write the state back to the ledger
err = stub.PutState(A, []byte(strconv.Itoa(Aval)))
if err != nil {
return shim.Error(err.Error())
}
return shim.Success(nil)
}
// Deletes an entity from state
func (t *SimpleChaincode) delete(stub shim.ChaincodeStubInterface, args []string) pb.Response {
if len(args) != 1 {
return shim.Error("Incorrect number of arguments. Expecting 1")
}
A := args[0]
// Delete the key from the state in ledger
err := stub.DelState(A)
if err != nil {
return shim.Error("Failed to delete state")
}
return shim.Success(nil)
}
// query callback representing the query of a chaincode
func (t *SimpleChaincode) query(stub shim.ChaincodeStubInterface, args []string) pb.Response {
var A string // Entities
var err error
if len(args) != 1 {
return shim.Error("Incorrect number of arguments. Expecting name of the person to query")
}
A = args[0]
// Get the state from the ledger
Avalbytes, err := stub.GetState(A)
if err != nil {
jsonResp := "{\"Error\":\"Failed to get state for " + A + "\"}"
return shim.Error(jsonResp)
}
if Avalbytes == nil {
jsonResp := "{\"Error\":\"Nil amount for " + A + "\"}"
return shim.Error(jsonResp)
}
jsonResp := "{\"Name\":\"" + A + "\",\"Amount\":\"" + string(Avalbytes) + "\"}"
fmt.Printf("Query Response:%s\n", jsonResp)
return shim.Success(Avalbytes)
}
func main() {
err := shim.Start(new(SimpleChaincode))
if err != nil {
fmt.Printf("Error starting Simple chaincode: %s", err)
}
}
How can i solve this issue as there is no syntax errors at all ?

Related

Is there any way to run my containers periodically?

I'm trying to write a program that from the main "server", calls for 2 "agents" that each one of them creates containers. Each container should run periodically and every 10 seconds print the time. The create command is taken from the Std.in as <command> <PATH>.
For example, I pass 4 containers to create, so agent1 creates 2, and agent2 creates 2.
My problem is that when I run this program I only see the second container from agent1 when I type docker ps I get only mycontainer2.
And only after I stop/remove mycontainer2, only then agent2 creates mycontainer4. (mycontainer1 and mycontainer3 wasn't created at all).
Probably the way I created them was wrong. Is there any way I can create all of them and let them run separately?
Main "server":
package main
import (
"fmt"
"gopkg.in/yaml.v2"
"io/ioutil"
"log"
"bufio"
"os"
"bytes"
"os/exec"
"strings"
"strconv"
)
type conf struct {
Name string `yaml:"Name"`
Amount int `yaml:"Amount"`
Image string `yaml:"Image"`
}
func (c *conf) getConf() *conf {
yamlFile, err := ioutil.ReadFile("conf.yaml")
if err != nil {
log.Printf("yamlFile.Get err #%v ", err)
}
err = yaml.Unmarshal(yamlFile, c)
if err != nil {
log.Fatalf("Unmarshal: %v", err)
}
return c
}
func isError(err error) bool {
if err != nil {
fmt.Println(err.Error())
}
return (err != nil)
}
func showEnvStatus() {
cmd := exec.Command("echo", "Hello from ShowEnv")
// cmd.Stdin = strings.NewReader("some input")
var out bytes.Buffer
cmd.Stdout = &out
err := cmd.Run()
if err != nil {
log.Fatal(err)
}
fmt.Printf("The out put is: %q\n", out.String())
return
}
func createAgents(c conf){
var workload = c.Amount/2
var rightBroderAgent1 = strconv.Itoa(workload)
var leftBorderAgent2 = strconv.Itoa(c.Amount- workload + 1)
//invoke agent1. Args are the range of the containers numbers for names. (0 : workload)
cmd1 := exec.Command("./agent","1", rightBroderAgent1, c.Name, c.Image)
var out bytes.Buffer
cmd1.Stdout = &out
err1 := cmd1.Run()
if err1 != nil {
fmt.Println(err1)
}
fmt.Println("%q\n",out.String())
//invoke agent2. Args are the range of the containers numbers for names.(workload+1 : Amount)
cmd2 := exec.Command("./agent",leftBorderAgent2, strconv.Itoa(c.Amount),c.Name, c.Image)
err2 := cmd2.Run()
if err2 != nil {
log.Fatal(err2)
}
return
}
func parseCommand(text string) ([]string){
res := strings.Split(text, " ")
return res
}
func main() {
i := 0
for i < 1{
var args []string
reader := bufio.NewReader(os.Stdin)
text, _ := reader.ReadString('\n')
args = parseCommand(text)
switch args[0] {
case "create":
var c conf
c.getConf()
createAgents(c)
default:
fmt.Println("Unknown command, try again")
}
}
}
############################# Agent file ##################
func main(){
// Args[] structure : {FILE, left border, right border, container's name, image}
left,_ := strconv.Atoi(os.Args[1])
right,_ := strconv.Atoi(os.Args[2])
for i := left; i <= right; i++ {
fmt.Println(left, right)
var name string = os.Args[3] + strconv.Itoa(i+1)
cmd1 := exec.Command("docker", "run", "--name", name, "-it", "-d", os.Args[4])
cmd2 := exec.Command("docker", "cp", "showtime" ,name + ":/showtime")
cmd3 := exec.Command("docker", "exec" ,name , "./showtime")
// cmds := []*exec.Cmd{cmd1,cmd2,cmd3}
err1 := cmd1.Run()
if err1 != nil {
fmt.Println(err1)
os.Exit(2)
}
err2 := cmd2.Run()
if err2 != nil {
fmt.Println(err2)
os.Exit(2)
}
err3 := cmd3.Run()
if err3 != nil {
fmt.Println(err3)
os.Exit(2)
}
}
}

How to retrieve stdout when piping several commands in Go

I'm writing a Go function to upload local Docker images to an instance that has SSH access. I'm using the following method for this:
cmdSave := exec.Command("docker", "save", image)
cmdLoad := exec.Command("ssh", fmt.Sprintf("%s#%s", user, externalIP), "docker load")
read, write := io.Pipe()
cmdSave.Stdout = write
cmdLoad.Stdin = read
var buffer bytes.Buffer
cmdLoad.Stdout = &buffer
var stderrSave bytes.Buffer
cmdSave.Stderr = &stderrSave
var stderrLoad bytes.Buffer
cmdLoad.Stderr = &stderrLoad
err = cmdSave.Start()
if err != nil {
return errors.Wrap(err, stderrSave.String())
}
err = cmdLoad.Start()
if err != nil {
return errors.Wrap(err, stderrLoad.String())
}
err = cmdSave.Wait()
if err != nil {
return errors.Wrap(err, stderrSave.String())
}
err = write.Close()
if err != nil {
return err
}
err = cmdLoad.Wait()
if err != nil {
return errors.Wrap(err, stderrLoad.String())
}
_, err = io.Copy(os.Stdout, &buffer)
if err != nil {
return err
}
However because of the way the commands are piped, if there is a problem with e.g. the SSH key or WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! error presents itself when SSHing to the instance, the functions just hangs endlessly on the cmdSave.Wait() and no output is displayed, leaving the user unaware of what the problem is.
Is there a way to do this so that the output isn't swallowed and the function isn't left hanging?

kubernetes attach pod use websocket

I want make a web terminal by kubernetes client-go api, and now i meet some problem.
main:
func main() {
flag.Parse()
log.SetFlags(0)
http.HandleFunc("/ws", echo)
log.Fatal(http.ListenAndServe(*addr, nil))
}
struct&handleFunc:
type Cmd struct {
Conn *websocket.Conn
Stdin io.Reader
Stdout io.Writer
Stderr io.Writer
}
func echo(w http.ResponseWriter, r *http.Request) {
cmd := Cmd{}
cmd.Stderr = ioutil.Discard
c, err := upgrader.Upgrade(w, r, nil)
if err != nil {
log.Print("upgrade:", err)
return
}
cmd.Conn = c
cmd.handleClient()
}
func (c *Cmd) handleClient() {
//c.Stdout = os.Stdout
//c.Stdin = os.Stdin
var read io.Reader
var write io.Writer
c.Stdin = read
c.Stdout = write
go func(rd io.Reader) {
for {
_, r, err := c.Conn.NextReader()
if err != nil {
fmt.Println("ReadErr:", err)
c.Conn.Close()
return
}
rd = r
}
}(read)
go func(wr io.Writer) {
w, err := c.Conn.NextWriter(1)
if err != nil {
fmt.Println("WriteErr:", err)
c.Conn.Close()
return
}
wr = w
}(write)
err := api.ExecOperator{}.ExecConsoleInContainer("1", "nginx-65899c769f-mkswf", c.Stdin, c.Stdout, c.Stderr)
if err != nil {
fmt.Println("ExecErr:", err)
return
}
}
api.ExecOperator{}.ExecConsoleInContainer() is a func invoke kubernetes exec api like kubernetes exec_util.go
When i use the code below,i can operate at the console,but i dont know how to use websocket(gorilla/websocket) input and output to replace os.stdin and os.stdout,i tried to write some of the code above ,but it cant work.
c.Stdout = os.Stdout
c.Stdin = os.Stdin

How the docker container id is generated

I wanted to know how the container id is generated so please provide the source code that provides the container id when the docker run is executed?
Here is a code snippet from docker daemon's function for creating Containers:
func (daemon *Daemon) newContainer(name string, config *runconfig.Config, imgID string) (*Container, error) {
var (
id string
err error
)
id, name, err = daemon.generateIDAndName(name)
if err != nil {
return nil, err
}
…
base := daemon.newBaseContainer(id)
…
base.ExecDriver = daemon.execDriver.Name()
return &base, err
}
So, the logic of creating ID and Name is in generateIDAndName function:
func (daemon *Daemon) generateIDAndName(name string) (string, string, error) {
var (
err error
id = stringid.GenerateNonCryptoID()
)
if name == "" {
if name, err = daemon.generateNewName(id); err != nil {
return "", "", err
}
return id, name, nil
}
if name, err = daemon.reserveName(id, name); err != nil {
return "", "", err
}
return id, name, nil
}
Here is stringid sources and the concrete method is generateID with false as input parameter:
func generateID(crypto bool) string {
b := make([]byte, 32)
var r io.Reader = random.Reader
if crypto {
r = rand.Reader
}
for {
if _, err := io.ReadFull(r, b); err != nil {
panic(err) // This shouldn't happen
}
id := hex.EncodeToString(b)
// if we try to parse the truncated for as an int and we don't have
// an error then the value is all numberic and causes issues when
// used as a hostname. ref #3869
if _, err := strconv.ParseInt(TruncateID(id), 10, 64); err == nil {
continue
}
return id
}
}
As you can see, the value is randomly generated with this random
// Reader is a global, shared instance of a pseudorandom bytes generator.
// It doesn't consume entropy.
var Reader io.Reader = &reader{rnd: Rand}

How can I compare two source code files/ ast trees?

I'm generating some source code using the templates package( is there a better method? )and part of the testing I need to check if the output matches the expected source code.
I tried a string comparison but it fails due the extra spaces / new lines generated by the templates package. I've also tried format.Source with not success. ( FAIL)
I tried to parse the ast of the both sources (see bellow) but the ast doesn't match either even if the code is basically same except the new lines / spaces. (FAIL)
package main
import (
"fmt"
"go/parser"
"go/token"
"reflect"
)
func main() {
stub1 := `package main
func myfunc(s string) error {
return nil
}`
stub2 := `package main
func myfunc(s string) error {
return nil
}`
fset := token.NewFileSet()
r1, err := parser.ParseFile(fset, "", stub1, parser.AllErrors)
if err != nil {
panic(err)
}
fset = token.NewFileSet()
r2, err := parser.ParseFile(fset, "", stub2, parser.AllErrors)
if err != nil {
panic(err)
}
if !reflect.DeepEqual(r1, r2) {
fmt.Printf("e %v, r %s, ", r1, r2)
}
}
Playground
Well, one simple way to achieve this is to use the go/printer library, that gives you better control of output formatting, and is basically like running gofmt on the source, normalizing both trees:
package main
import (
"fmt"
"go/parser"
"go/token"
"go/printer"
//"reflect"
"bytes"
)
func main() {
stub1 := `package main
func myfunc(s string) error {
return nil
}`
stub2 := `package main
func myfunc(s string) error {
return nil
}`
fset1 := token.NewFileSet()
r1, err := parser.ParseFile(fset1, "", stub1, parser.AllErrors)
if err != nil {
panic(err)
}
fset2 := token.NewFileSet()
r2, err := parser.ParseFile(fset1, "", stub2, parser.AllErrors)
if err != nil {
panic(err)
}
// we create two output buffers for each source tree
out1 := bytes.NewBuffer(nil)
out2 := bytes.NewBuffer(nil)
// we use the same printer config for both
conf := &printer.Config{Mode: printer.TabIndent | printer.UseSpaces, Tabwidth: 8}
// print to both outputs
if err := conf.Fprint(out1, fset1, r1); err != nil {
panic(err)
}
if err := conf.Fprint(out2, fset2, r2); err != nil {
panic(err)
}
// they should be identical!
if string(out1.Bytes()) != string(out2.Bytes()) {
panic(string(out1.Bytes()) +"\n" + string(out2.Bytes()))
} else {
fmt.Println("A-OKAY!")
}
}
Of course this code needs to be refactored to not look as stupid. Another approach is instead of using DeepEqual, create a tree comparison function yourself, that skips irrelevant nodes.
This was easier than I thought. All I had to do was to remove the empty new lines(after formatting). Below is the code.
package main
import (
"fmt"
"go/format"
"strings"
)
func main() {
a, err := fmtSource(stub1)
if err != nil {
panic(err)
}
b, err := fmtSource(stub2)
if err != nil {
panic(err)
}
if a != b {
fmt.Printf("a %v, \n b %v", a, b)
}
}
func fmtSource(source string) (string, error) {
if !strings.Contains(source, "package") {
source = "package main\n" + source
}
b, err := format.Source([]byte(source))
if err != nil {
return "", err
}
// cleanLine replaces double space with one space
cleanLine := func(s string)string{
sa := strings.Fields(s)
return strings.Join(sa, " ")
}
lines := strings.Split(string(b), "\n")
n := 0
var startLn *int
for _, line := range lines {
if line != "" {
line = cleanLine(line)
lines[n] = line
if startLn == nil {
x := n
startLn = &x
}
n++
}
}
lines = lines[*startLn:n]
// Add final "" entry to get trailing newline from Join.
if n > 0 && lines[n-1] != "" {
lines = append(lines, "")
}
// Make it pretty
b, err = format.Source([]byte(strings.Join(lines, "\n")))
if err != nil {
return "", err
}
return string(b), nil
}

Resources