Split off cli into separate binaries (#37)

* 🎨 Split off cli into separate binaries

This commit splits off the cli into 3 binaries:
- agent
- cli
- provider

The provider now is a separate component that can be tested by itself
and have its own lifecycle. This paves the way to a ligher c3os variant,
HA support and other features that can be provided on runtime.

This is working, but still there are low hanging fruit to care about.

Fixes #14

* 🤖 Add provider bin to releases

* ⚙️ Handle signals

* ⚙️ Reduce buildsize footprint

* 🎨 Scan for providers also in /system/providers

* 🤖 Run goreleaser

* 🎨 Refactoring
This commit is contained in:
Ettore Di Giacinto 2022-07-04 22:39:34 +02:00 committed by Itxaka
commit b2e49776a3
17 changed files with 2199 additions and 0 deletions

57
cmd/agent/agent.go Normal file
View File

@ -0,0 +1,57 @@
package main
import (
"fmt"
"io/ioutil"
"os"
"syscall"
"github.com/c3os-io/c3os/internal/bus"
"github.com/c3os-io/c3os/internal/utils"
events "github.com/c3os-io/c3os/pkg/bus"
config "github.com/c3os-io/c3os/pkg/config"
"github.com/nxadm/tail"
)
// setup needs edgevpn and k3s installed locally
// (both k3s and k3s-agent systemd services)
func agent(apiAddress string, dir []string, force bool) error {
os.MkdirAll("/usr/local/.c3os", 0600)
// Reads config
c, err := config.Scan(dir...)
if err != nil {
return err
}
f, err := ioutil.TempFile(os.TempDir(), "c3os")
if err != nil {
return err
}
err = ioutil.WriteFile(f.Name(), []byte{}, os.ModePerm)
if err != nil {
return err
}
t, err := tail.TailFile(f.Name(), tail.Config{Follow: true})
if err != nil {
return err
}
defer os.RemoveAll(f.Name())
utils.OnSignal(func() {
os.RemoveAll(f.Name())
}, syscall.SIGINT, syscall.SIGTERM)
go func() {
for line := range t.Lines {
fmt.Println(line.Text)
}
}()
_, err = bus.Manager.Publish(events.EventBootstrap, events.BootstrapPayload{APIAddress: apiAddress, Config: c.String(), Logfile: f.Name()})
return err
}

740
cmd/agent/iconunix.go Normal file
View File

@ -0,0 +1,740 @@
package main
var banner []byte = []byte{
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d,
0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00,
0x08, 0x06, 0x00, 0x00, 0x00, 0xf4, 0x78, 0xd4, 0xfa, 0x00, 0x00, 0x02,
0xf3, 0x7a, 0x54, 0x58, 0x74, 0x52, 0x61, 0x77, 0x20, 0x70, 0x72, 0x6f,
0x66, 0x69, 0x6c, 0x65, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x65, 0x78,
0x69, 0x66, 0x00, 0x00, 0x78, 0xda, 0xed, 0x97, 0x51, 0x72, 0xec, 0x28,
0x0c, 0x45, 0xff, 0x59, 0xc5, 0x2c, 0xc1, 0x92, 0x10, 0x92, 0x96, 0x83,
0xc1, 0x54, 0xbd, 0x1d, 0xcc, 0xf2, 0xe7, 0x82, 0xed, 0x9e, 0xa4, 0xd3,
0xef, 0xa3, 0x67, 0xbe, 0x5e, 0x55, 0x9b, 0x18, 0x88, 0x50, 0x5f, 0x84,
0x0e, 0xd0, 0x49, 0x3a, 0xfe, 0xfe, 0x35, 0xd2, 0x5f, 0x78, 0x28, 0xbc,
0xa4, 0xac, 0xe6, 0x25, 0x4a, 0xd9, 0xf0, 0xe4, 0xc8, 0xc1, 0x15, 0x1d,
0xdf, 0xce, 0xa7, 0xae, 0x9a, 0xb6, 0xbc, 0xea, 0xfb, 0xe1, 0xcb, 0xfa,
0xcd, 0x9e, 0x1e, 0x03, 0x0c, 0x93, 0xa0, 0x95, 0x73, 0xc0, 0xcb, 0xd9,
0xd2, 0x6d, 0xbf, 0x85, 0xae, 0x96, 0x2a, 0x7a, 0xfa, 0x45, 0xc8, 0xdb,
0x35, 0xb0, 0x7f, 0x1f, 0x88, 0x7c, 0x4d, 0xef, 0x4f, 0x42, 0xd7, 0x44,
0x32, 0x23, 0x9a, 0x21, 0xf4, 0x4b, 0x28, 0x2e, 0x21, 0xe1, 0x73, 0x80,
0x2e, 0x81, 0x7a, 0x2e, 0x6b, 0x2b, 0xe1, 0xf6, 0x75, 0x09, 0xfb, 0x71,
0xb6, 0xfd, 0x5e, 0xa8, 0x9f, 0x6f, 0x9a, 0x95, 0xd8, 0xb9, 0xbc, 0x5b,
0xe4, 0xf9, 0xf7, 0x6c, 0xc8, 0x5e, 0x57, 0x18, 0x85, 0xf9, 0x10, 0x92,
0x0d, 0x35, 0x8b, 0x9f, 0x01, 0xc8, 0x7c, 0x39, 0x49, 0x5d, 0x9d, 0x59,
0x07, 0x1c, 0x67, 0xa9, 0x70, 0x55, 0xd4, 0x59, 0xee, 0x25, 0x21, 0x21,
0xaf, 0xf2, 0xf4, 0x78, 0x02, 0x11, 0x8d, 0x19, 0x6a, 0x7e, 0xe9, 0xf4,
0x4c, 0x8b, 0x5e, 0xd1, 0xba, 0x7b, 0xe9, 0x99, 0x56, 0xe6, 0xcb, 0x45,
0x9e, 0x92, 0x5c, 0x1e, 0xed, 0x4b, 0x7b, 0x22, 0x7d, 0x4d, 0x65, 0xa5,
0xfe, 0xcb, 0xcc, 0xd9, 0xaf, 0x1e, 0x7f, 0xb7, 0x9b, 0x9c, 0x52, 0x69,
0x7b, 0xca, 0xfe, 0x7c, 0xc7, 0xe8, 0x3e, 0xd6, 0x9a, 0xb1, 0x8a, 0x9a,
0x0b, 0x52, 0x5d, 0xae, 0x45, 0xdd, 0x4b, 0x59, 0x3d, 0xf8, 0xed, 0x98,
0x62, 0x4e, 0xed, 0x09, 0x7a, 0x65, 0x33, 0xbc, 0x0a, 0x09, 0x5b, 0x25,
0x50, 0x1c, 0xbb, 0xba, 0x81, 0x5a, 0xdf, 0xda, 0xb6, 0xa3, 0x34, 0x0a,
0x62, 0xe0, 0x1a, 0x94, 0xa9, 0x53, 0xa5, 0x41, 0xc7, 0x6a, 0x1b, 0x35,
0x84, 0x98, 0xf9, 0x48, 0x6c, 0xe8, 0x30, 0x37, 0x96, 0x65, 0x74, 0x31,
0x0e, 0x6e, 0x60, 0x47, 0xa0, 0x86, 0x42, 0x83, 0x4d, 0x42, 0xba, 0x38,
0xd8, 0x36, 0x60, 0x17, 0x58, 0xf9, 0x11, 0x0b, 0xad, 0x69, 0x63, 0x6b,
0x69, 0xcd, 0xe6, 0x98, 0xb9, 0x13, 0x5c, 0x99, 0x20, 0x46, 0x73, 0x5f,
0xbc, 0x5b, 0xd2, 0xbb, 0x1f, 0x18, 0x63, 0x1e, 0x05, 0xa2, 0xcd, 0x1f,
0xb9, 0x42, 0x5c, 0xcc, 0xeb, 0xd0, 0xd2, 0x4c, 0xa3, 0xcc, 0x1a, 0x6e,
0x20, 0x42, 0xe3, 0x4a, 0xaa, 0xae, 0x04, 0xdf, 0xe5, 0xf9, 0x99, 0x5c,
0x05, 0x04, 0x75, 0x66, 0x79, 0x1e, 0x91, 0x40, 0x62, 0xf7, 0x53, 0x62,
0x57, 0xfa, 0xf7, 0x26, 0x90, 0x05, 0x5a, 0xe0, 0xa8, 0x68, 0xcf, 0xe3,
0x42, 0xd6, 0x2f, 0x01, 0xa4, 0x08, 0x53, 0x2b, 0x82, 0x21, 0x01, 0x01,
0x50, 0xc3, 0x79, 0xa0, 0x42, 0x9b, 0x31, 0x1b, 0x11, 0x12, 0xe9, 0x00,
0x54, 0x11, 0x3a, 0x4b, 0xe6, 0x1d, 0x04, 0x48, 0x95, 0x3b, 0x82, 0x64,
0x1c, 0x99, 0x02, 0x36, 0xce, 0x73, 0x6a, 0x7c, 0xc4, 0x68, 0xb9, 0xb2,
0x32, 0xcc, 0x09, 0x76, 0x5c, 0x66, 0x20, 0xa1, 0x52, 0xc4, 0xc0, 0x26,
0xa4, 0x02, 0x56, 0xce, 0x8a, 0xfd, 0x63, 0xd9, 0xb1, 0x87, 0xaa, 0x8a,
0x66, 0x55, 0x2d, 0x6a, 0xea, 0x1a, 0x5a, 0x8b, 0x94, 0x5c, 0xb4, 0x94,
0x62, 0x65, 0x5e, 0x8a, 0xd5, 0xc4, 0x72, 0x32, 0xb5, 0x62, 0x66, 0x6e,
0x61, 0xd5, 0xc5, 0xb3, 0xab, 0x17, 0x37, 0x77, 0x0f, 0xaf, 0xc1, 0x21,
0xb8, 0x34, 0x35, 0x4a, 0x58, 0x78, 0x44, 0xd4, 0x8a, 0x39, 0x2b, 0x94,
0x2b, 0x3e, 0x5d, 0xe1, 0x50, 0xeb, 0xce, 0xbb, 0xec, 0x79, 0xd7, 0xb4,
0x97, 0xdd, 0x76, 0xdf, 0x63, 0xaf, 0x0d, 0xdb, 0xa7, 0xe5, 0xa6, 0xad,
0x34, 0x6b, 0xde, 0xa2, 0xd5, 0xce, 0x5d, 0x3a, 0xee, 0x8f, 0x5e, 0xba,
0x75, 0xef, 0xd1, 0xeb, 0x41, 0x07, 0xb6, 0xd2, 0x91, 0x0f, 0x3d, 0xca,
0x61, 0x87, 0x1f, 0x71, 0xd4, 0x81, 0xad, 0x36, 0x24, 0x8d, 0x3c, 0x74,
0x94, 0x61, 0xc3, 0x47, 0x8c, 0xfa, 0xa0, 0x76, 0x61, 0xfd, 0x51, 0xde,
0xa0, 0x46, 0x17, 0x35, 0x5e, 0xa4, 0xa6, 0xa3, 0x3d, 0xa8, 0xc1, 0x6a,
0x76, 0x4b, 0xd0, 0xbc, 0x4e, 0x74, 0x32, 0x03, 0x30, 0x4e, 0x99, 0x40,
0xdc, 0x26, 0x02, 0x6c, 0x68, 0x9e, 0xcc, 0x36, 0xa7, 0x9c, 0x79, 0x92,
0x9b, 0xcc, 0xb6, 0x60, 0x9c, 0x0a, 0x65, 0x04, 0xa9, 0x93, 0x59, 0xa7,
0x49, 0x0c, 0x04, 0xf3, 0x41, 0xac, 0x83, 0x6e, 0x76, 0x89, 0x4f, 0xa2,
0x93, 0xdc, 0xff, 0xe2, 0x96, 0x2c, 0x7f, 0xe3, 0xc6, 0xff, 0x95, 0x5c,
0x9a, 0xe8, 0xde, 0x24, 0xf7, 0x93, 0xdb, 0x2b, 0x6a, 0x7d, 0x7e, 0x0d,
0xb5, 0x45, 0xec, 0x3c, 0x85, 0x33, 0xa9, 0x9b, 0xe0, 0xf4, 0xc1, 0xa7,
0xb2, 0xe3, 0x07, 0xdf, 0x55, 0x3f, 0xdb, 0xf4, 0xbb, 0x81, 0x77, 0xdb,
0x8f, 0xd0, 0x47, 0xe8, 0x23, 0xf4, 0x11, 0xfa, 0x08, 0x7d, 0x84, 0x3e,
0x42, 0x7f, 0x8e, 0x90, 0x0c, 0xfc, 0xf1, 0x30, 0xff, 0x0b, 0xfc, 0x07,
0xa3, 0xff, 0xa7, 0x64, 0x64, 0x9a, 0xbd, 0x42, 0x00, 0x00, 0x00, 0x61,
0x7a, 0x54, 0x58, 0x74, 0x52, 0x61, 0x77, 0x20, 0x70, 0x72, 0x6f, 0x66,
0x69, 0x6c, 0x65, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x69, 0x70, 0x74,
0x63, 0x00, 0x00, 0x78, 0xda, 0x3d, 0x89, 0xc1, 0x0d, 0x80, 0x30, 0x0c,
0x03, 0xff, 0x99, 0x82, 0x11, 0x9c, 0xd8, 0x88, 0x76, 0x1d, 0xd2, 0x0f,
0xbf, 0x3e, 0xd8, 0x5f, 0x44, 0x45, 0x60, 0xcb, 0x96, 0x4f, 0xb6, 0x6b,
0xde, 0x69, 0xdb, 0x92, 0xc2, 0xd8, 0x14, 0xea, 0x1a, 0x50, 0xf9, 0x97,
0x0f, 0x4f, 0x04, 0x8f, 0x9a, 0x8d, 0x41, 0x54, 0xde, 0x06, 0xfb, 0x7a,
0xb2, 0x9e, 0xb3, 0x08, 0x74, 0xee, 0x14, 0x69, 0x31, 0x3e, 0x04, 0xec,
0x01, 0x30, 0x95, 0x14, 0xd2, 0x64, 0x95, 0xf3, 0x4b, 0x00, 0x00, 0x01,
0x85, 0x69, 0x43, 0x43, 0x50, 0x49, 0x43, 0x43, 0x20, 0x70, 0x72, 0x6f,
0x66, 0x69, 0x6c, 0x65, 0x00, 0x00, 0x78, 0x9c, 0x7d, 0x91, 0x3d, 0x48,
0xc3, 0x40, 0x1c, 0xc5, 0x5f, 0x53, 0xa5, 0x45, 0x2a, 0x0e, 0x16, 0x11,
0x71, 0xc8, 0x50, 0xc5, 0xc1, 0x82, 0xa8, 0x88, 0xe0, 0xa2, 0x55, 0x28,
0x42, 0x85, 0x52, 0x2b, 0xb4, 0xea, 0x60, 0x72, 0xe9, 0x17, 0x34, 0x69,
0x48, 0x52, 0x5c, 0x1c, 0x05, 0xd7, 0x82, 0x83, 0x1f, 0x8b, 0x55, 0x07,
0x17, 0x67, 0x5d, 0x1d, 0x5c, 0x05, 0x41, 0xf0, 0x03, 0xc4, 0xd1, 0xc9,
0x49, 0xd1, 0x45, 0x4a, 0xfc, 0x5f, 0x52, 0x68, 0x11, 0xe3, 0xc1, 0x71,
0x3f, 0xde, 0xdd, 0x7b, 0xdc, 0xbd, 0x03, 0x84, 0x7a, 0x99, 0xa9, 0x66,
0xc7, 0x18, 0xa0, 0x6a, 0x96, 0x91, 0x8a, 0xc7, 0xc4, 0x4c, 0x76, 0x55,
0x0c, 0xbc, 0x42, 0x40, 0x10, 0x7d, 0x98, 0xc1, 0x88, 0xc4, 0x4c, 0x7d,
0x2e, 0x99, 0x4c, 0xc0, 0x73, 0x7c, 0xdd, 0xc3, 0xc7, 0xd7, 0xbb, 0x28,
0xcf, 0xf2, 0x3e, 0xf7, 0xe7, 0xe8, 0x56, 0x72, 0x26, 0x03, 0x7c, 0x22,
0xf1, 0x2c, 0xd3, 0x0d, 0x8b, 0x78, 0x83, 0x78, 0x6a, 0xd3, 0xd2, 0x39,
0xef, 0x13, 0x87, 0x59, 0x51, 0x52, 0x88, 0xcf, 0x89, 0x47, 0x0d, 0xba,
0x20, 0xf1, 0x23, 0xd7, 0x65, 0x97, 0xdf, 0x38, 0x17, 0x1c, 0x16, 0x78,
0x66, 0xd8, 0x48, 0xa7, 0xe6, 0x89, 0xc3, 0xc4, 0x62, 0xa1, 0x8d, 0xe5,
0x36, 0x66, 0x45, 0x43, 0x25, 0x9e, 0x24, 0x8e, 0x28, 0xaa, 0x46, 0xf9,
0x42, 0xc6, 0x65, 0x85, 0xf3, 0x16, 0x67, 0xb5, 0x5c, 0x65, 0xcd, 0x7b,
0xf2, 0x17, 0x86, 0x72, 0xda, 0xca, 0x32, 0xd7, 0x69, 0x0e, 0x22, 0x8e,
0x45, 0x2c, 0x21, 0x09, 0x11, 0x32, 0xaa, 0x28, 0xa1, 0x0c, 0x0b, 0x51,
0x5a, 0x35, 0x52, 0x4c, 0xa4, 0x68, 0x3f, 0xe6, 0xe1, 0x1f, 0x70, 0xfc,
0x49, 0x72, 0xc9, 0xe4, 0x2a, 0x81, 0x91, 0x63, 0x01, 0x15, 0xa8, 0x90,
0x1c, 0x3f, 0xf8, 0x1f, 0xfc, 0xee, 0xd6, 0xcc, 0x4f, 0x8c, 0xbb, 0x49,
0xa1, 0x18, 0xd0, 0xf9, 0x62, 0xdb, 0x1f, 0x43, 0x40, 0x60, 0x17, 0x68,
0xd4, 0x6c, 0xfb, 0xfb, 0xd8, 0xb6, 0x1b, 0x27, 0x80, 0xff, 0x19, 0xb8,
0xd2, 0x5a, 0xfe, 0x4a, 0x1d, 0x98, 0xfe, 0x24, 0xbd, 0xd6, 0xd2, 0x22,
0x47, 0x40, 0xcf, 0x36, 0x70, 0x71, 0xdd, 0xd2, 0xe4, 0x3d, 0xe0, 0x72,
0x07, 0xe8, 0x7f, 0xd2, 0x25, 0x43, 0x72, 0x24, 0x3f, 0x4d, 0x21, 0x9f,
0x07, 0xde, 0xcf, 0xe8, 0x9b, 0xb2, 0x40, 0xef, 0x2d, 0xd0, 0xb5, 0xe6,
0xf6, 0xd6, 0xdc, 0xc7, 0xe9, 0x03, 0x90, 0xa6, 0xae, 0x12, 0x37, 0xc0,
0xc1, 0x21, 0x30, 0x5c, 0xa0, 0xec, 0x75, 0x8f, 0x77, 0x07, 0xdb, 0x7b,
0xfb, 0xf7, 0x4c, 0xb3, 0xbf, 0x1f, 0xb6, 0x32, 0x72, 0xc2, 0xf4, 0xb2,
0x50, 0x0c, 0x00, 0x00, 0x0d, 0x1a, 0x69, 0x54, 0x58, 0x74, 0x58, 0x4d,
0x4c, 0x3a, 0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e,
0x78, 0x6d, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x3f, 0x78, 0x70,
0x61, 0x63, 0x6b, 0x65, 0x74, 0x20, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x3d,
0x22, 0xef, 0xbb, 0xbf, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x57, 0x35,
0x4d, 0x30, 0x4d, 0x70, 0x43, 0x65, 0x68, 0x69, 0x48, 0x7a, 0x72, 0x65,
0x53, 0x7a, 0x4e, 0x54, 0x63, 0x7a, 0x6b, 0x63, 0x39, 0x64, 0x22, 0x3f,
0x3e, 0x0a, 0x3c, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x6d, 0x65, 0x74, 0x61,
0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x78, 0x3d, 0x22, 0x61, 0x64,
0x6f, 0x62, 0x65, 0x3a, 0x6e, 0x73, 0x3a, 0x6d, 0x65, 0x74, 0x61, 0x2f,
0x22, 0x20, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x74, 0x6b, 0x3d, 0x22, 0x58,
0x4d, 0x50, 0x20, 0x43, 0x6f, 0x72, 0x65, 0x20, 0x34, 0x2e, 0x34, 0x2e,
0x30, 0x2d, 0x45, 0x78, 0x69, 0x76, 0x32, 0x22, 0x3e, 0x0a, 0x20, 0x3c,
0x72, 0x64, 0x66, 0x3a, 0x52, 0x44, 0x46, 0x20, 0x78, 0x6d, 0x6c, 0x6e,
0x73, 0x3a, 0x72, 0x64, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a,
0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x77, 0x33, 0x2e, 0x6f, 0x72, 0x67,
0x2f, 0x31, 0x39, 0x39, 0x39, 0x2f, 0x30, 0x32, 0x2f, 0x32, 0x32, 0x2d,
0x72, 0x64, 0x66, 0x2d, 0x73, 0x79, 0x6e, 0x74, 0x61, 0x78, 0x2d, 0x6e,
0x73, 0x23, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a,
0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20,
0x72, 0x64, 0x66, 0x3a, 0x61, 0x62, 0x6f, 0x75, 0x74, 0x3d, 0x22, 0x22,
0x0a, 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x78,
0x6d, 0x70, 0x4d, 0x4d, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f,
0x2f, 0x6e, 0x73, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f,
0x6d, 0x2f, 0x78, 0x61, 0x70, 0x2f, 0x31, 0x2e, 0x30, 0x2f, 0x6d, 0x6d,
0x2f, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73,
0x3a, 0x73, 0x74, 0x45, 0x76, 0x74, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70,
0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e,
0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x61, 0x70, 0x2f, 0x31, 0x2e, 0x30, 0x2f,
0x73, 0x54, 0x79, 0x70, 0x65, 0x2f, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72,
0x63, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x23, 0x22, 0x0a, 0x20, 0x20,
0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x64, 0x63, 0x3d, 0x22,
0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x70, 0x75, 0x72, 0x6c, 0x2e,
0x6f, 0x72, 0x67, 0x2f, 0x64, 0x63, 0x2f, 0x65, 0x6c, 0x65, 0x6d, 0x65,
0x6e, 0x74, 0x73, 0x2f, 0x31, 0x2e, 0x31, 0x2f, 0x22, 0x0a, 0x20, 0x20,
0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x47, 0x49, 0x4d, 0x50,
0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77,
0x2e, 0x67, 0x69, 0x6d, 0x70, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x78, 0x6d,
0x70, 0x2f, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e,
0x73, 0x3a, 0x74, 0x69, 0x66, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70,
0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e,
0x63, 0x6f, 0x6d, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x2f, 0x31, 0x2e, 0x30,
0x2f, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73,
0x3a, 0x78, 0x6d, 0x70, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f,
0x2f, 0x6e, 0x73, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f,
0x6d, 0x2f, 0x78, 0x61, 0x70, 0x2f, 0x31, 0x2e, 0x30, 0x2f, 0x22, 0x0a,
0x20, 0x20, 0x20, 0x78, 0x6d, 0x70, 0x4d, 0x4d, 0x3a, 0x44, 0x6f, 0x63,
0x75, 0x6d, 0x65, 0x6e, 0x74, 0x49, 0x44, 0x3d, 0x22, 0x67, 0x69, 0x6d,
0x70, 0x3a, 0x64, 0x6f, 0x63, 0x69, 0x64, 0x3a, 0x67, 0x69, 0x6d, 0x70,
0x3a, 0x63, 0x38, 0x31, 0x32, 0x64, 0x35, 0x31, 0x62, 0x2d, 0x38, 0x35,
0x65, 0x63, 0x2d, 0x34, 0x39, 0x30, 0x38, 0x2d, 0x38, 0x33, 0x35, 0x33,
0x2d, 0x32, 0x66, 0x38, 0x38, 0x39, 0x38, 0x32, 0x66, 0x36, 0x39, 0x64,
0x64, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x70, 0x4d, 0x4d, 0x3a,
0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x49, 0x44, 0x3d, 0x22,
0x78, 0x6d, 0x70, 0x2e, 0x69, 0x69, 0x64, 0x3a, 0x34, 0x62, 0x37, 0x39,
0x34, 0x38, 0x38, 0x66, 0x2d, 0x32, 0x38, 0x33, 0x36, 0x2d, 0x34, 0x34,
0x61, 0x62, 0x2d, 0x38, 0x30, 0x62, 0x35, 0x2d, 0x30, 0x31, 0x37, 0x38,
0x37, 0x64, 0x35, 0x63, 0x62, 0x33, 0x33, 0x39, 0x22, 0x0a, 0x20, 0x20,
0x20, 0x78, 0x6d, 0x70, 0x4d, 0x4d, 0x3a, 0x4f, 0x72, 0x69, 0x67, 0x69,
0x6e, 0x61, 0x6c, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x49,
0x44, 0x3d, 0x22, 0x78, 0x6d, 0x70, 0x2e, 0x64, 0x69, 0x64, 0x3a, 0x37,
0x38, 0x63, 0x64, 0x64, 0x32, 0x39, 0x64, 0x2d, 0x31, 0x30, 0x38, 0x35,
0x2d, 0x34, 0x63, 0x33, 0x64, 0x2d, 0x39, 0x31, 0x62, 0x35, 0x2d, 0x35,
0x38, 0x66, 0x64, 0x33, 0x64, 0x35, 0x34, 0x64, 0x63, 0x63, 0x62, 0x22,
0x0a, 0x20, 0x20, 0x20, 0x64, 0x63, 0x3a, 0x46, 0x6f, 0x72, 0x6d, 0x61,
0x74, 0x3d, 0x22, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x70, 0x6e, 0x67,
0x22, 0x0a, 0x20, 0x20, 0x20, 0x47, 0x49, 0x4d, 0x50, 0x3a, 0x41, 0x50,
0x49, 0x3d, 0x22, 0x32, 0x2e, 0x30, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x47,
0x49, 0x4d, 0x50, 0x3a, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d,
0x3d, 0x22, 0x4c, 0x69, 0x6e, 0x75, 0x78, 0x22, 0x0a, 0x20, 0x20, 0x20,
0x47, 0x49, 0x4d, 0x50, 0x3a, 0x54, 0x69, 0x6d, 0x65, 0x53, 0x74, 0x61,
0x6d, 0x70, 0x3d, 0x22, 0x31, 0x36, 0x34, 0x34, 0x33, 0x36, 0x32, 0x31,
0x34, 0x34, 0x38, 0x38, 0x31, 0x35, 0x36, 0x37, 0x22, 0x0a, 0x20, 0x20,
0x20, 0x47, 0x49, 0x4d, 0x50, 0x3a, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f,
0x6e, 0x3d, 0x22, 0x32, 0x2e, 0x31, 0x30, 0x2e, 0x32, 0x38, 0x22, 0x0a,
0x20, 0x20, 0x20, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x4f, 0x72, 0x69, 0x65,
0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3d, 0x22, 0x31, 0x22, 0x0a,
0x20, 0x20, 0x20, 0x78, 0x6d, 0x70, 0x3a, 0x43, 0x72, 0x65, 0x61, 0x74,
0x6f, 0x72, 0x54, 0x6f, 0x6f, 0x6c, 0x3d, 0x22, 0x47, 0x49, 0x4d, 0x50,
0x20, 0x32, 0x2e, 0x31, 0x30, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x3c,
0x78, 0x6d, 0x70, 0x4d, 0x4d, 0x3a, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72,
0x79, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a,
0x53, 0x65, 0x71, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x72,
0x64, 0x66, 0x3a, 0x6c, 0x69, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x73, 0x74, 0x45, 0x76, 0x74, 0x3a, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e,
0x3d, 0x22, 0x73, 0x61, 0x76, 0x65, 0x64, 0x22, 0x0a, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x73, 0x74, 0x45, 0x76, 0x74, 0x3a, 0x63, 0x68, 0x61,
0x6e, 0x67, 0x65, 0x64, 0x3d, 0x22, 0x2f, 0x22, 0x0a, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x73, 0x74, 0x45, 0x76, 0x74, 0x3a, 0x69, 0x6e, 0x73,
0x74, 0x61, 0x6e, 0x63, 0x65, 0x49, 0x44, 0x3d, 0x22, 0x78, 0x6d, 0x70,
0x2e, 0x69, 0x69, 0x64, 0x3a, 0x32, 0x36, 0x37, 0x37, 0x62, 0x64, 0x36,
0x65, 0x2d, 0x39, 0x38, 0x30, 0x62, 0x2d, 0x34, 0x66, 0x30, 0x30, 0x2d,
0x39, 0x61, 0x37, 0x34, 0x2d, 0x65, 0x66, 0x33, 0x39, 0x61, 0x64, 0x31,
0x32, 0x65, 0x63, 0x34, 0x36, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x73, 0x74, 0x45, 0x76, 0x74, 0x3a, 0x73, 0x6f, 0x66, 0x74, 0x77,
0x61, 0x72, 0x65, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x3d, 0x22, 0x47, 0x69,
0x6d, 0x70, 0x20, 0x32, 0x2e, 0x31, 0x30, 0x20, 0x28, 0x4c, 0x69, 0x6e,
0x75, 0x78, 0x29, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x73,
0x74, 0x45, 0x76, 0x74, 0x3a, 0x77, 0x68, 0x65, 0x6e, 0x3d, 0x22, 0x32,
0x30, 0x32, 0x32, 0x2d, 0x30, 0x32, 0x2d, 0x30, 0x39, 0x54, 0x30, 0x30,
0x3a, 0x31, 0x35, 0x3a, 0x34, 0x34, 0x2b, 0x30, 0x31, 0x3a, 0x30, 0x30,
0x22, 0x2f, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x72, 0x64,
0x66, 0x3a, 0x53, 0x65, 0x71, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x3c, 0x2f,
0x78, 0x6d, 0x70, 0x4d, 0x4d, 0x3a, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72,
0x79, 0x3e, 0x0a, 0x20, 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a, 0x44,
0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a,
0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a, 0x52, 0x44, 0x46, 0x3e, 0x0a,
0x3c, 0x2f, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x6d, 0x65, 0x74, 0x61, 0x3e,
0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0a, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0a, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0a,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0a, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0a, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0a, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0a, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0a,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0a, 0x3c, 0x3f, 0x78,
0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x20, 0x65, 0x6e, 0x64, 0x3d, 0x22,
0x77, 0x22, 0x3f, 0x3e, 0x59, 0x94, 0xa1, 0xe5, 0x00, 0x00, 0x00, 0x06,
0x62, 0x4b, 0x47, 0x44, 0x00, 0xe0, 0x00, 0xfb, 0x00, 0xfc, 0xdc, 0x0d,
0x5e, 0xa6, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00,
0x0b, 0x13, 0x00, 0x00, 0x0b, 0x13, 0x01, 0x00, 0x9a, 0x9c, 0x18, 0x00,
0x00, 0x00, 0x07, 0x74, 0x49, 0x4d, 0x45, 0x07, 0xe6, 0x02, 0x08, 0x17,
0x0f, 0x2c, 0x1f, 0x94, 0xec, 0x69, 0x00, 0x00, 0x0f, 0xe9, 0x49, 0x44,
0x41, 0x54, 0x78, 0xda, 0xed, 0xdd, 0xd1, 0x72, 0xdc, 0x46, 0xb2, 0x45,
0x51, 0x27, 0xa3, 0xfe, 0xff, 0x97, 0xe1, 0x17, 0x2b, 0x42, 0x92, 0xc3,
0x6e, 0x52, 0x04, 0x09, 0x14, 0xf6, 0x5a, 0xcf, 0xf7, 0xc6, 0x58, 0x55,
0x95, 0x27, 0x0f, 0xda, 0x33, 0xf6, 0xfc, 0x05, 0x24, 0x1c, 0xc7, 0x71,
0xbc, 0xe7, 0xff, 0x6e, 0x66, 0xc6, 0x69, 0xc1, 0xf3, 0x19, 0x74, 0xb0,
0xf4, 0x95, 0x01, 0x50, 0x00, 0x00, 0x8b, 0x5f, 0x11, 0x00, 0x05, 0x00,
0x48, 0x2f, 0x7e, 0x45, 0x00, 0x14, 0x00, 0x20, 0xbc, 0xf8, 0x15, 0x01,
0x50, 0x00, 0x80, 0xf8, 0xf2, 0x57, 0x02, 0x40, 0x01, 0x00, 0x82, 0x8b,
0x5f, 0x11, 0x00, 0x05, 0x00, 0x08, 0x2f, 0x7e, 0x45, 0x00, 0x14, 0x00,
0x20, 0xbc, 0xf8, 0x15, 0x01, 0x50, 0x00, 0x80, 0xf0, 0xe2, 0x57, 0x04,
0x40, 0x01, 0x00, 0xc2, 0x8b, 0x5f, 0x11, 0x00, 0x05, 0x00, 0x08, 0x2f,
0x7e, 0x45, 0x00, 0x14, 0x00, 0x20, 0xbc, 0xf8, 0x15, 0x01, 0x50, 0x00,
0x80, 0xf0, 0xe2, 0x57, 0x04, 0x40, 0x01, 0x00, 0xe2, 0xcb, 0x5f, 0x09,
0x00, 0x05, 0x00, 0x2c, 0x7e, 0x14, 0x01, 0x50, 0x00, 0xc0, 0xe2, 0x57,
0x04, 0x00, 0x05, 0x00, 0x2c, 0x7e, 0x45, 0x00, 0x50, 0x00, 0xc0, 0xe2,
0x57, 0x04, 0x00, 0x05, 0x00, 0x2c, 0x7e, 0x45, 0x00, 0x50, 0x00, 0xc0,
0xe2, 0x57, 0x04, 0x00, 0x05, 0x00, 0x2c, 0x7e, 0x45, 0x00, 0x50, 0x00,
0xc0, 0xe2, 0x57, 0x04, 0x00, 0x05, 0x00, 0x2c, 0x7f, 0x25, 0x00, 0x14,
0x00, 0xc0, 0xe2, 0x57, 0x04, 0x40, 0x01, 0x00, 0x2c, 0x7e, 0x45, 0x00,
0x14, 0x00, 0xb0, 0xf8, 0x9d, 0x82, 0x22, 0x00, 0x0a, 0x00, 0x58, 0xfc,
0x28, 0x02, 0xa0, 0x00, 0x80, 0xc5, 0x8f, 0x22, 0x00, 0x0a, 0x00, 0x58,
0xfc, 0x28, 0x02, 0xa0, 0x00, 0x80, 0xc5, 0x8f, 0x22, 0x00, 0x0a, 0x00,
0x58, 0xfc, 0x28, 0x02, 0xa0, 0x00, 0x80, 0xe5, 0x8f, 0x12, 0x00, 0x0a,
0x00, 0x58, 0xfc, 0x28, 0x02, 0xa0, 0x00, 0x80, 0xc5, 0x8f, 0x22, 0x00,
0x0a, 0x00, 0x58, 0xfc, 0x28, 0x02, 0xa0, 0x00, 0x80, 0xc5, 0x8f, 0x22,
0x00, 0x0a, 0x00, 0x58, 0xfc, 0x28, 0x02, 0xa0, 0x00, 0x60, 0xf1, 0x83,
0x22, 0x00, 0x0a, 0x00, 0x16, 0x3f, 0x28, 0x02, 0xa0, 0x00, 0x60, 0xf1,
0x83, 0x22, 0x80, 0x02, 0x00, 0x16, 0x3f, 0x28, 0x02, 0x28, 0x00, 0x60,
0xf9, 0x83, 0x12, 0x80, 0x02, 0x00, 0x16, 0x3f, 0x28, 0x02, 0x28, 0x00,
0x60, 0xf1, 0x83, 0x22, 0x80, 0x02, 0x00, 0x16, 0x3f, 0x28, 0x02, 0x28,
0x00, 0x60, 0xf1, 0x83, 0x22, 0x80, 0x02, 0x00, 0x16, 0x3f, 0x28, 0x02,
0x28, 0x00, 0x60, 0xf1, 0x83, 0x22, 0x80, 0x02, 0x80, 0xc5, 0x0f, 0x28,
0x02, 0x28, 0x00, 0x58, 0xfc, 0x80, 0x22, 0x80, 0x02, 0x80, 0xe5, 0x0f,
0x4a, 0x00, 0x28, 0x00, 0x58, 0xfc, 0xa0, 0x08, 0x80, 0x02, 0x80, 0x12,
0x00, 0x96, 0x3f, 0x28, 0x00, 0x28, 0x02, 0x60, 0xf1, 0x83, 0x02, 0x80,
0x22, 0x00, 0x16, 0x3f, 0x28, 0x00, 0x28, 0x02, 0x60, 0xf1, 0x83, 0x02,
0x80, 0x22, 0x00, 0x16, 0x3f, 0x28, 0x00, 0x28, 0x02, 0x60, 0xf1, 0xa3,
0x00, 0x80, 0x22, 0x00, 0x16, 0x3f, 0x0a, 0x00, 0x28, 0x02, 0x60, 0xf1,
0xa3, 0x00, 0x80, 0x22, 0x00, 0x16, 0x3f, 0x0a, 0x00, 0x28, 0x02, 0x60,
0xf1, 0xa3, 0x00, 0x80, 0x22, 0x80, 0xc5, 0x0f, 0x0a, 0x00, 0x28, 0x02,
0x58, 0xfc, 0xa0, 0x00, 0x80, 0x22, 0x80, 0xc5, 0x0f, 0x0a, 0x00, 0x28,
0x02, 0x58, 0xfc, 0xa0, 0x00, 0x80, 0x22, 0x80, 0xc5, 0x0f, 0x0a, 0x00,
0x28, 0x02, 0x58, 0xfc, 0xa0, 0x00, 0x80, 0x22, 0x80, 0xc5, 0x0f, 0x0a,
0x00, 0x28, 0x02, 0x58, 0xfc, 0xa0, 0x00, 0x80, 0x22, 0x80, 0xc5, 0x0f,
0x0a, 0x00, 0x28, 0x02, 0x58, 0xfc, 0xa0, 0x00, 0x80, 0x22, 0x80, 0xc5,
0x0f, 0x0a, 0x00, 0x28, 0x02, 0x16, 0xbf, 0xc5, 0x0f, 0x0a, 0x00, 0x28,
0x02, 0x16, 0x3f, 0x28, 0x00, 0x80, 0x22, 0x60, 0xf1, 0x83, 0x02, 0x00,
0x28, 0x02, 0x16, 0x3f, 0x28, 0x00, 0xa0, 0x08, 0x28, 0x02, 0x16, 0x3f,
0x28, 0x00, 0xa0, 0x08, 0x60, 0xf1, 0x83, 0x02, 0x00, 0x8a, 0x00, 0x16,
0x3f, 0x28, 0x00, 0xa0, 0x08, 0x60, 0xf1, 0x83, 0x02, 0x00, 0x8a, 0x00,
0x16, 0x3f, 0x28, 0x00, 0xa0, 0x08, 0x60, 0xf1, 0x83, 0x02, 0x00, 0x8a,
0x00, 0x16, 0x3f, 0x28, 0x00, 0x3c, 0x6e, 0x01, 0xd6, 0x03, 0x5c, 0x11,
0xb0, 0xf8, 0xcd, 0x0f, 0x0a, 0x00, 0xe9, 0xc5, 0x27, 0xd0, 0x15, 0x01,
0x8b, 0xdf, 0xdc, 0xa0, 0x00, 0x10, 0x5e, 0x78, 0x02, 0x5e, 0x11, 0xf0,
0x2e, 0xcc, 0x0b, 0x0a, 0x00, 0xe1, 0x45, 0x27, 0xf0, 0x15, 0x01, 0xef,
0xc0, 0x9c, 0xa0, 0x00, 0x10, 0x5e, 0x70, 0x16, 0x40, 0xb3, 0x08, 0xb8,
0x77, 0xf3, 0x81, 0x02, 0x80, 0xc5, 0x26, 0xe8, 0x42, 0x45, 0xc0, 0x3d,
0x9b, 0x0b, 0x14, 0x00, 0x04, 0x9d, 0xc0, 0x0b, 0x15, 0x01, 0xf7, 0x6a,
0x1e, 0x50, 0x00, 0x10, 0x78, 0x82, 0x2f, 0x54, 0x04, 0xdc, 0xa3, 0x39,
0x40, 0x01, 0x40, 0xf0, 0x09, 0xc0, 0x50, 0x11, 0x70, 0x6f, 0xde, 0x3f,
0x0a, 0x00, 0x02, 0xd0, 0x42, 0x09, 0x15, 0x01, 0xf7, 0xe4, 0xdd, 0xa3,
0x00, 0xa0, 0x00, 0x7c, 0xc9, 0xc2, 0xb2, 0x60, 0xee, 0x59, 0x04, 0xdc,
0x8b, 0xf7, 0x8e, 0x02, 0x00, 0xdf, 0xb2, 0xa8, 0x2c, 0x9c, 0x7b, 0x14,
0x01, 0xf7, 0xe0, 0x9d, 0xa3, 0x00, 0xc0, 0x25, 0x0b, 0xca, 0x02, 0xba,
0xa6, 0x08, 0x38, 0x77, 0xef, 0x1b, 0x05, 0x00, 0x6e, 0xb1, 0x98, 0x2c,
0x24, 0x0b, 0xc9, 0xbb, 0x06, 0x05, 0x00, 0x5f, 0xa6, 0xce, 0xdd, 0xb9,
0x7a, 0xcf, 0xa0, 0x00, 0x50, 0x0a, 0x4c, 0xc1, 0x79, 0xee, 0xf9, 0x3b,
0x47, 0xef, 0x18, 0x05, 0x00, 0xb6, 0x0a, 0x4e, 0x01, 0xfa, 0xb9, 0x7b,
0x70, 0x6e, 0xde, 0x2f, 0x0a, 0x00, 0x6c, 0x1d, 0xa0, 0x82, 0xf4, 0x63,
0xf7, 0xe1, 0x9c, 0xbc, 0x5b, 0x14, 0x00, 0x78, 0x54, 0x90, 0x0a, 0xd4,
0xff, 0xbf, 0x17, 0xe7, 0xe2, 0xbd, 0xa2, 0x00, 0xc0, 0xa3, 0x03, 0x55,
0xb0, 0xfe, 0x7a, 0x3f, 0xce, 0xc1, 0x3b, 0x45, 0x01, 0x80, 0x54, 0xb0,
0x0a, 0x58, 0xef, 0xd3, 0xfb, 0xa4, 0x6c, 0x39, 0x02, 0x2c, 0x02, 0x5f,
0xc2, 0x16, 0x3f, 0x28, 0x00, 0xa0, 0x08, 0x28, 0x02, 0x16, 0x3f, 0x28,
0x00, 0xa0, 0x08, 0x60, 0xf1, 0x83, 0x02, 0x00, 0x8a, 0x00, 0x16, 0x3f,
0x28, 0x00, 0xa0, 0x08, 0x60, 0xf1, 0x83, 0x02, 0x00, 0x8a, 0x00, 0x16,
0x3f, 0x28, 0x00, 0xa0, 0x08, 0x60, 0xf1, 0x83, 0x02, 0x00, 0x8a, 0x00,
0x16, 0x3f, 0x28, 0x00, 0xa0, 0x08, 0x60, 0xf1, 0x83, 0x02, 0x00, 0x8a,
0x00, 0x16, 0x3f, 0x28, 0x00, 0xa0, 0x08, 0x60, 0xf1, 0x83, 0x02, 0x00,
0x8a, 0x80, 0xc5, 0x0f, 0x28, 0x00, 0xa0, 0x08, 0x58, 0xfc, 0x80, 0x02,
0x00, 0x8a, 0x80, 0xc5, 0x0f, 0x28, 0x00, 0xa0, 0x08, 0x58, 0xfc, 0x80,
0x02, 0x00, 0x8a, 0x80, 0xc5, 0x0f, 0x28, 0x00, 0xa0, 0x08, 0x58, 0xfc,
0x80, 0x02, 0x00, 0x8a, 0x80, 0xc5, 0x0f, 0x0a, 0x00, 0xa0, 0x08, 0x58,
0xfc, 0xa0, 0x00, 0x00, 0x8a, 0x80, 0xc5, 0x0f, 0x0a, 0x00, 0xa0, 0x08,
0x58, 0xfc, 0xa0, 0x00, 0x00, 0x8a, 0x80, 0xc5, 0x0f, 0x0a, 0x00, 0xd0,
0x2c, 0x02, 0x16, 0x3f, 0x28, 0x00, 0x40, 0xa8, 0x08, 0x58, 0xfc, 0xb0,
0xb7, 0x37, 0x47, 0x00, 0x00, 0x0a, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00,
0x0a, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0xa0, 0x00,
0x00, 0x00, 0x0a, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00,
0xa0, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x0a,
0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0xa0, 0x00, 0x00,
0x00, 0x0a, 0x00, 0x00, 0x28, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x28,
0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x28, 0x00, 0x00, 0x80, 0x02, 0x00,
0x00, 0x28, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x28, 0x00, 0x00, 0x80,
0x02, 0x00, 0x00, 0x28, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x28, 0x00,
0x00, 0x80, 0x02, 0x00, 0x00, 0x28, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00,
0x28, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0xa0, 0x00,
0x00, 0x00, 0x0a, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00,
0xa0, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x0a,
0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0xa0, 0x00, 0x00,
0x00, 0x0a, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0xa0,
0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x28, 0x00, 0x00, 0x80, 0x02, 0x00,
0x00, 0x28, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x28, 0x00, 0x00, 0x80,
0x02, 0x00, 0x00, 0x28, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x28, 0x00,
0x00, 0x80, 0x02, 0xc0, 0xde, 0x66, 0x66, 0x9c, 0x02, 0x98, 0x21, 0x14,
0x00, 0x00, 0x40, 0x01, 0xc0, 0x17, 0x0c, 0x60, 0x76, 0x50, 0x00, 0x00,
0x00, 0x05, 0x00, 0x5f, 0x32, 0x60, 0x66, 0x40, 0x01, 0x40, 0xa0, 0x81,
0x59, 0x01, 0x05, 0x00, 0xc1, 0x06, 0x66, 0x04, 0x14, 0x00, 0x04, 0x1c,
0x98, 0x0d, 0xf8, 0x90, 0xe5, 0x08, 0xb8, 0x2a, 0xe8, 0x8e, 0xe3, 0x38,
0x9c, 0x06, 0xe6, 0xc1, 0xe2, 0x47, 0x01, 0x40, 0x11, 0x00, 0x8b, 0x1f,
0x14, 0x00, 0x14, 0x01, 0xb0, 0xf8, 0x41, 0x01, 0x40, 0x11, 0x00, 0x8b,
0x1f, 0x14, 0x00, 0x14, 0x01, 0xb0, 0xf8, 0x41, 0x01, 0x40, 0x11, 0x00,
0x8b, 0x1f, 0x14, 0x00, 0x14, 0x01, 0xb0, 0xf8, 0x41, 0x01, 0x40, 0x11,
0x00, 0x8b, 0x1f, 0x14, 0x00, 0x14, 0x01, 0xb0, 0xf8, 0x51, 0x00, 0x40,
0x11, 0x00, 0x8b, 0x1f, 0x05, 0x00, 0x14, 0x01, 0xb0, 0xf8, 0x79, 0x3e,
0xff, 0x2e, 0x00, 0x04, 0x33, 0x78, 0x63, 0x28, 0x00, 0xb0, 0x2f, 0xbf,
0x00, 0xe0, 0x8d, 0x81, 0x02, 0x80, 0x60, 0x06, 0x6f, 0x0d, 0x14, 0x00,
0x00, 0x40, 0x01, 0xc0, 0x17, 0x19, 0x78, 0x73, 0x28, 0x00, 0x00, 0x80,
0x02, 0x00, 0xbe, 0xc4, 0xc0, 0xdb, 0x43, 0x01, 0x00, 0x00, 0x14, 0x00,
0xf0, 0x05, 0x06, 0xde, 0x20, 0x0a, 0x00, 0x00, 0xa0, 0x00, 0x80, 0x2f,
0x2f, 0xbc, 0x45, 0x50, 0x00, 0x00, 0x00, 0x05, 0x00, 0x7c, 0x71, 0xe1,
0x4d, 0x82, 0x02, 0x00, 0x82, 0x16, 0x6f, 0x13, 0x14, 0x00, 0xd8, 0xcc,
0xfc, 0xc3, 0x49, 0x38, 0x7f, 0x50, 0x00, 0x20, 0xf8, 0x85, 0x65, 0x09,
0x39, 0x73, 0xbf, 0x02, 0xa0, 0x00, 0x40, 0x74, 0x01, 0xf9, 0x1a, 0xbd,
0xee, 0xab, 0xdf, 0xb9, 0x83, 0x02, 0x80, 0xaf, 0xff, 0x5b, 0x2e, 0x28,
0x5a, 0xe7, 0xea, 0x57, 0x00, 0x14, 0x00, 0x88, 0x7c, 0xfd, 0x2b, 0x02,
0xd7, 0x2f, 0x7e, 0x67, 0x0d, 0x0a, 0x00, 0xbe, 0xfe, 0x7d, 0xb9, 0xfa,
0xe2, 0xf7, 0x66, 0x41, 0x01, 0x80, 0xef, 0xff, 0xfa, 0x57, 0x04, 0xae,
0x59, 0xfc, 0xce, 0x17, 0x14, 0x00, 0x7c, 0xfd, 0xfb, 0xb2, 0x75, 0x2e,
0xde, 0x2e, 0xbc, 0x9a, 0x3b, 0x47, 0x80, 0x00, 0xbd, 0xee, 0x0b, 0xf3,
0x8c, 0x3f, 0xe3, 0x55, 0x8b, 0xf3, 0xae, 0x7f, 0xed, 0x85, 0x77, 0x03,
0x67, 0x58, 0x8e, 0x00, 0xae, 0x5f, 0x0e, 0xb5, 0xaf, 0x45, 0x4b, 0x11,
0xae, 0xe7, 0x6f, 0x01, 0xe0, 0xeb, 0xff, 0x06, 0x0b, 0xab, 0xb4, 0x10,
0x6b, 0x67, 0xe9, 0x6f, 0x05, 0xa0, 0x00, 0x80, 0x85, 0xf5, 0xf2, 0x3f,
0xe7, 0xc9, 0x45, 0xe0, 0x3b, 0xff, 0x7c, 0x7e, 0x61, 0x00, 0x05, 0x00,
0x5f, 0xff, 0x16, 0xa5, 0x3f, 0x8f, 0x37, 0x0d, 0x0a, 0x00, 0xec, 0xf3,
0x25, 0xb9, 0xfb, 0xe2, 0xbc, 0xfa, 0xaf, 0xdf, 0xaf, 0x00, 0xa0, 0x00,
0xe0, 0x4b, 0xc9, 0x17, 0xb4, 0xbf, 0x5e, 0x6f, 0x1b, 0x14, 0x00, 0xd8,
0xf3, 0x0b, 0xf2, 0xee, 0x8b, 0xf5, 0x8e, 0x7f, 0x7d, 0x8a, 0x08, 0x28,
0x00, 0xf8, 0x42, 0xf2, 0x8b, 0x80, 0x2f, 0x7e, 0x6f, 0x1c, 0x7e, 0x9e,
0x5d, 0x47, 0x80, 0x70, 0xf4, 0xe5, 0xe8, 0x6d, 0x79, 0x5b, 0xf8, 0x05,
0x00, 0x7c, 0x19, 0x81, 0xb7, 0x8e, 0x5f, 0x00, 0xa0, 0x17, 0x88, 0xbe,
0xd0, 0xbc, 0x33, 0xef, 0x0c, 0xbf, 0x00, 0x00, 0x00, 0x7e, 0x01, 0x00,
0x5f, 0x65, 0x78, 0x6f, 0xde, 0x1b, 0x7e, 0x01, 0x80, 0x67, 0xb5, 0x61,
0x61, 0xec, 0x8e, 0x41, 0x01, 0x80, 0xde, 0xd7, 0x18, 0x98, 0x01, 0x14,
0x00, 0xf0, 0x65, 0x88, 0xbb, 0x06, 0x05, 0x00, 0x7c, 0xf9, 0x80, 0x59,
0x40, 0x01, 0x00, 0x5f, 0x84, 0xb8, 0x73, 0x50, 0x00, 0xc0, 0x17, 0x0f,
0x98, 0x09, 0x14, 0x00, 0xf0, 0x25, 0x88, 0xbb, 0x07, 0x05, 0x00, 0x7c,
0xe9, 0x80, 0xd9, 0xe0, 0x86, 0x25, 0xd8, 0x11, 0x50, 0x0d, 0x38, 0x5f,
0x80, 0x78, 0x97, 0xf8, 0x05, 0x00, 0x6a, 0xcd, 0x57, 0xc8, 0xe2, 0x2d,
0xa0, 0x00, 0x40, 0xef, 0x2b, 0x0b, 0xcc, 0x0a, 0x0a, 0x00, 0xf8, 0xe2,
0xc3, 0x9b, 0xf0, 0x26, 0x50, 0x00, 0xc0, 0x17, 0x0d, 0x98, 0x19, 0x14,
0x00, 0xf0, 0xa5, 0x87, 0xb7, 0x01, 0x0a, 0x00, 0xf8, 0x92, 0x01, 0xb3,
0x83, 0x02, 0x00, 0xbe, 0xf0, 0xf0, 0x46, 0x40, 0x01, 0x00, 0x5f, 0x30,
0x60, 0x86, 0xd8, 0xa4, 0xf0, 0x3a, 0x02, 0x0a, 0xc1, 0xe5, 0xcb, 0x0e,
0xef, 0x17, 0xfc, 0x02, 0x00, 0x00, 0x7e, 0x01, 0x70, 0x04, 0xf8, 0x7a,
0x02, 0xef, 0x18, 0xbf, 0x00, 0xc0, 0xb3, 0x1a, 0xae, 0xd0, 0xc4, 0xdb,
0x01, 0x05, 0x80, 0xde, 0x57, 0x13, 0x98, 0x2d, 0x50, 0x00, 0xf0, 0x05,
0x07, 0xde, 0x10, 0x28, 0x00, 0xf8, 0x42, 0x01, 0x33, 0x86, 0x02, 0x00,
0xbe, 0xdc, 0xc0, 0x5b, 0x22, 0x64, 0x39, 0x82, 0x7d, 0x5b, 0xfe, 0x9d,
0x82, 0xc9, 0x97, 0x09, 0x7c, 0xdf, 0xac, 0xed, 0x38, 0xfb, 0x8a, 0xd4,
0x0d, 0xcb, 0xad, 0x23, 0x78, 0xc6, 0x02, 0xbd, 0x7a, 0xb8, 0xee, 0x54,
0x00, 0x04, 0x0d, 0xde, 0xb8, 0xbc, 0x42, 0x01, 0xc8, 0x85, 0xca, 0x15,
0x83, 0xe5, 0x7f, 0x2f, 0x8d, 0x59, 0x6d, 0xbc, 0xf3, 0x27, 0xe4, 0x15,
0x0a, 0xc0, 0xe3, 0xc3, 0xe4, 0xbb, 0x06, 0x4b, 0x28, 0x62, 0x6e, 0x9f,
0xff, 0xde, 0x9f, 0x92, 0x57, 0xfc, 0xca, 0x7f, 0x07, 0xe0, 0xa1, 0x01,
0xf2, 0xe3, 0x3f, 0xc7, 0x60, 0x01, 0xf2, 0x0a, 0xbf, 0x00, 0x84, 0xbf,
0x1c, 0xbe, 0x62, 0xb0, 0x7c, 0xfd, 0x63, 0x96, 0x9f, 0xf9, 0xee, 0x9f,
0x98, 0x57, 0x28, 0x00, 0xc2, 0xe2, 0xc4, 0xc1, 0xf2, 0x5f, 0x8a, 0xc2,
0x5c, 0x9b, 0x69, 0x73, 0xad, 0x00, 0x70, 0xf3, 0x41, 0x3a, 0x7b, 0xa8,
0x04, 0x05, 0xe6, 0xdb, 0x4c, 0x9b, 0x6f, 0x05, 0x80, 0x4d, 0x86, 0xe8,
0xcc, 0xa1, 0xf2, 0xf5, 0x8f, 0x59, 0x7f, 0xc6, 0x0c, 0x54, 0x32, 0x0b,
0x05, 0xc0, 0xf2, 0x3f, 0x61, 0xa8, 0x7c, 0xfd, 0xc3, 0xfe, 0x73, 0x50,
0xc9, 0x2b, 0x14, 0x00, 0x8b, 0xff, 0xc4, 0xc1, 0xf2, 0xf5, 0x0f, 0xfb,
0xce, 0x42, 0x2d, 0xaf, 0x50, 0x00, 0x2c, 0xfe, 0x93, 0x06, 0xcb, 0xd7,
0x3f, 0xec, 0x39, 0x0f, 0xc5, 0xbc, 0x42, 0x01, 0xb0, 0xf8, 0x4f, 0x1a,
0x2c, 0xcb, 0x1f, 0xf6, 0x2b, 0x01, 0xd5, 0xbc, 0xe2, 0x35, 0xff, 0x20,
0x20, 0x8b, 0xff, 0xe5, 0x9f, 0xd7, 0x60, 0x81, 0xbc, 0x92, 0x57, 0x7e,
0x01, 0x30, 0x48, 0x68, 0xfb, 0x20, 0x23, 0x64, 0x84, 0x02, 0x60, 0xa8,
0x31, 0xd8, 0x20, 0x2f, 0xe4, 0xc5, 0x8e, 0xfc, 0x2d, 0x00, 0x83, 0x0c,
0xf0, 0xf8, 0x3c, 0x57, 0x04, 0xfc, 0x02, 0x60, 0xf1, 0x6b, 0xf3, 0x20,
0x43, 0x64, 0x08, 0x7e, 0x01, 0x30, 0xb4, 0x00, 0x7e, 0x11, 0xf0, 0x0b,
0x80, 0xc5, 0x8f, 0xe6, 0x0e, 0x72, 0x45, 0xae, 0xf8, 0x05, 0xc0, 0x80,
0x02, 0xe0, 0x17, 0x01, 0xbf, 0x00, 0x58, 0xfc, 0x68, 0xe9, 0x20, 0x6b,
0x64, 0x8d, 0x5f, 0x00, 0x0c, 0x23, 0x00, 0x7e, 0x11, 0xf0, 0x0b, 0x80,
0xc5, 0x8f, 0x46, 0x0e, 0xf2, 0x47, 0xfe, 0xf8, 0x05, 0xc0, 0xe0, 0x01,
0xe0, 0x17, 0x01, 0xbf, 0x00, 0x58, 0xfc, 0x68, 0xdf, 0xf8, 0x15, 0x00,
0x99, 0xa4, 0x00, 0x18, 0x32, 0x2c, 0x7f, 0x94, 0x00, 0xe4, 0xd3, 0xb5,
0x96, 0xc1, 0x02, 0x80, 0x3f, 0xdb, 0x3f, 0x3b, 0x17, 0x81, 0xd9, 0xf9,
0xe0, 0xd1, 0xae, 0x41, 0x66, 0x21, 0xb3, 0x22, 0x05, 0xc0, 0x20, 0x19,
0x2a, 0x90, 0x57, 0xc8, 0xab, 0x50, 0x01, 0x30, 0x48, 0x06, 0xcb, 0x29,
0x20, 0xaf, 0x90, 0x57, 0xa1, 0x02, 0x60, 0x90, 0x50, 0x04, 0xb0, 0xf8,
0x91, 0x57, 0xa1, 0x02, 0x60, 0x90, 0x50, 0x04, 0xb0, 0xf8, 0x91, 0x57,
0xa1, 0x02, 0x60, 0x90, 0x50, 0x04, 0xb0, 0xf8, 0x91, 0x57, 0xa1, 0x02,
0x60, 0x90, 0x50, 0x04, 0xb0, 0xf8, 0x91, 0x57, 0xa1, 0x02, 0x60, 0x90,
0x50, 0x02, 0xb0, 0xfc, 0x91, 0x59, 0xa1, 0x02, 0x60, 0x88, 0x50, 0x04,
0xb0, 0xf8, 0xe1, 0xba, 0xcc, 0x1a, 0x43, 0x84, 0xa1, 0x02, 0x99, 0x45,
0x2f, 0xb3, 0xc6, 0x10, 0x61, 0xa8, 0x40, 0x66, 0xd1, 0xcb, 0xac, 0x31,
0x44, 0x18, 0x2a, 0x90, 0x59, 0xf4, 0x32, 0x6b, 0x0c, 0x11, 0x86, 0x0a,
0x64, 0x16, 0xbd, 0xcc, 0x1a, 0x43, 0x84, 0xa1, 0xc2, 0xe2, 0x87, 0x5e,
0x66, 0x8d, 0x21, 0xc2, 0x50, 0x29, 0x02, 0x16, 0x3f, 0xf4, 0x32, 0x6b,
0x0c, 0x11, 0x28, 0x02, 0x16, 0x3f, 0xf4, 0x32, 0x6b, 0x0c, 0x11, 0x28,
0x02, 0x16, 0x3f, 0xf4, 0x32, 0x6b, 0x0c, 0x11, 0x28, 0x02, 0x16, 0x3f,
0xf4, 0x32, 0x6b, 0x0c, 0x11, 0x28, 0x02, 0x16, 0x3f, 0xf4, 0x32, 0x6b,
0x0c, 0x11, 0x28, 0x02, 0x16, 0x3f, 0xf4, 0x32, 0x6b, 0x0c, 0x12, 0x28,
0x02, 0x16, 0x3f, 0xf4, 0xf2, 0x6a, 0x0c, 0x12, 0x28, 0x01, 0x96, 0x3f,
0xf4, 0x32, 0x6b, 0x0c, 0x11, 0x28, 0x02, 0x16, 0x3f, 0xf4, 0x32, 0x6b,
0x0c, 0x11, 0x28, 0x02, 0x16, 0x3f, 0xf4, 0x32, 0x6b, 0x0c, 0x14, 0x58,
0xfe, 0x4a, 0x00, 0xf4, 0x32, 0x6b, 0x0c, 0x15, 0x58, 0xfc, 0x8a, 0x00,
0xf4, 0x32, 0x6b, 0x0c, 0x15, 0x58, 0xfc, 0x8a, 0x00, 0xf4, 0x32, 0xcb,
0x3f, 0x07, 0x00, 0x2c, 0x7e, 0x45, 0x00, 0x82, 0x99, 0xe5, 0x9f, 0x04,
0x08, 0x16, 0xbf, 0x22, 0x00, 0xc1, 0xcc, 0xf2, 0xef, 0x02, 0x00, 0x8b,
0x5f, 0x11, 0x80, 0x60, 0x66, 0xf9, 0xb7, 0x01, 0x82, 0xc5, 0xaf, 0x08,
0x40, 0x30, 0xb3, 0xc6, 0x50, 0x81, 0xc5, 0xaf, 0x08, 0x40, 0x2f, 0xb3,
0xc6, 0x50, 0x61, 0x88, 0x2c, 0x7e, 0x45, 0x00, 0x7a, 0x99, 0x35, 0x86,
0x0a, 0x43, 0x84, 0x22, 0x00, 0xbd, 0xcc, 0x1a, 0x43, 0x85, 0x21, 0x02,
0x99, 0x45, 0x2f, 0xb3, 0xc6, 0x50, 0x61, 0x88, 0x40, 0x66, 0xd1, 0xcb,
0xac, 0x31, 0x54, 0x18, 0x22, 0x90, 0x59, 0xf4, 0x32, 0x6b, 0x0c, 0x15,
0x86, 0x08, 0x64, 0x16, 0xbd, 0xcc, 0x1a, 0x43, 0x85, 0x21, 0x02, 0x99,
0x45, 0x2f, 0xb3, 0xc6, 0x50, 0x61, 0x88, 0x40, 0x66, 0xd1, 0xcb, 0xac,
0x31, 0x54, 0x18, 0x22, 0x90, 0x59, 0xf4, 0x32, 0x6b, 0x0c, 0x16, 0x86,
0x08, 0xe4, 0x15, 0xbd, 0xbc, 0x1a, 0x83, 0x85, 0x41, 0x02, 0x79, 0x45,
0x2f, 0xaf, 0xc6, 0x60, 0x61, 0x90, 0x40, 0x5e, 0xd1, 0xcb, 0xab, 0x31,
0x58, 0x18, 0x24, 0x90, 0x57, 0xf4, 0xf2, 0x6a, 0x0c, 0x16, 0x06, 0x09,
0xe4, 0x15, 0xbd, 0xbc, 0x1a, 0x83, 0x85, 0x41, 0x02, 0x79, 0x45, 0x2f,
0xaf, 0xc6, 0x60, 0x61, 0x90, 0x40, 0x5e, 0xd1, 0xcb, 0xab, 0x31, 0x58,
0x18, 0x24, 0x90, 0x57, 0xf4, 0xf2, 0x6a, 0x0c, 0x16, 0x06, 0x09, 0xe4,
0x15, 0xbd, 0xbc, 0x1a, 0x83, 0x85, 0x41, 0x02, 0x79, 0x45, 0x2f, 0xaf,
0xc6, 0x60, 0x61, 0x90, 0x40, 0x5e, 0xd1, 0xcb, 0xab, 0x31, 0x58, 0x18,
0x24, 0x90, 0x57, 0xf4, 0xf2, 0x6a, 0x0c, 0x16, 0x06, 0x09, 0xe4, 0x95,
0xbc, 0xea, 0xe5, 0xd5, 0x18, 0x2c, 0x0c, 0x12, 0xc8, 0x2b, 0x79, 0x15,
0xfc, 0xb3, 0xbb, 0x7e, 0x83, 0x65, 0x90, 0x40, 0x5e, 0xc9, 0xab, 0xe0,
0x19, 0xfc, 0x78, 0x4c, 0x0e, 0xc3, 0x60, 0x19, 0xa4, 0xcf, 0xbd, 0x1b,
0x33, 0xe4, 0xbc, 0xe5, 0x95, 0xbc, 0xda, 0x6a, 0x86, 0x7e, 0x7f, 0x44,
0x0e, 0xc7, 0x60, 0x19, 0xa4, 0x3f, 0x7b, 0x27, 0x66, 0xc7, 0xb9, 0xcb,
0x2b, 0x79, 0xb5, 0xd5, 0xec, 0xfc, 0xd7, 0xe3, 0x71, 0x58, 0x06, 0xcb,
0x20, 0x7d, 0xec, 0x5d, 0x98, 0x19, 0xe7, 0x2f, 0xaf, 0xe4, 0xd5, 0x56,
0x33, 0xf3, 0xea, 0xd1, 0x38, 0x3c, 0x83, 0xe5, 0x2d, 0xbc, 0xef, 0x1d,
0x98, 0x15, 0xf7, 0x20, 0xaf, 0xe4, 0xd5, 0x56, 0xb3, 0xf2, 0xde, 0xc7,
0xe2, 0x30, 0xbb, 0x83, 0x25, 0x50, 0xcd, 0x88, 0xfb, 0x90, 0x57, 0xf2,
0xea, 0x81, 0x33, 0xf2, 0xd1, 0x47, 0xe2, 0x70, 0x3b, 0x83, 0x25, 0x40,
0xcd, 0x86, 0x7b, 0x91, 0x57, 0xf2, 0xea, 0xc1, 0xb3, 0xf1, 0xa7, 0x8f,
0xc3, 0x61, 0x3f, 0x77, 0xb0, 0x04, 0xa6, 0x99, 0x70, 0x3f, 0xce, 0x4d,
0x5e, 0x05, 0x66, 0xe2, 0xb3, 0x8f, 0xc2, 0xe1, 0x3f, 0x67, 0xb0, 0x04,
0xa4, 0x59, 0x70, 0x4f, 0xce, 0x4f, 0x5e, 0x85, 0x66, 0xe1, 0xac, 0xc7,
0xe0, 0x32, 0xf6, 0x1d, 0x2c, 0x81, 0x68, 0x06, 0xdc, 0x97, 0x73, 0x94,
0x57, 0xc1, 0x19, 0x38, 0xfb, 0x11, 0xb8, 0x9c, 0x7d, 0x06, 0x4b, 0x00,
0x7a, 0xfb, 0xee, 0xcd, 0xbd, 0xc9, 0xab, 0xf0, 0xdb, 0xff, 0xaa, 0xcb,
0x77, 0x59, 0xf7, 0x1d, 0x2c, 0x81, 0xe7, 0xcd, 0xbb, 0x3f, 0xf7, 0x27,
0xaf, 0xdc, 0xcd, 0x7c, 0xf5, 0xa5, 0xbb, 0xbc, 0xfb, 0x0c, 0x96, 0x80,
0xf3, 0xd6, 0xdd, 0xa3, 0x7b, 0x94, 0x57, 0xee, 0xe2, 0xdb, 0x0a, 0x80,
0xcb, 0xbc, 0x7e, 0xb0, 0x04, 0x9a, 0x37, 0xee, 0x3e, 0xdd, 0xa7, 0xbc,
0x72, 0xf6, 0x97, 0x15, 0x00, 0x97, 0x2b, 0xc0, 0x9e, 0x1e, 0x60, 0xde,
0xb6, 0x7b, 0x75, 0xde, 0xce, 0x79, 0xab, 0xb7, 0xad, 0xe5, 0x3d, 0xef,
0xb2, 0x05, 0x96, 0x37, 0xed, 0x7e, 0xdd, 0xaf, 0xbc, 0x72, 0xb6, 0xb7,
0x2d, 0x00, 0x2e, 0xff, 0xfc, 0xcb, 0x17, 0x50, 0xde, 0xb2, 0x7b, 0x76,
0xcf, 0xf2, 0xca, 0x5b, 0xde, 0xa6, 0x00, 0x78, 0x0c, 0x9f, 0x7f, 0x0c,
0x02, 0xc9, 0x1b, 0x76, 0xdf, 0xee, 0x5b, 0x5e, 0x79, 0xc3, 0xdb, 0x16,
0x00, 0x8f, 0xe3, 0xe3, 0x8f, 0x43, 0x00, 0x79, 0xbb, 0xee, 0xdd, 0xbd,
0xcb, 0x2b, 0x6f, 0xf7, 0x31, 0x05, 0xc0, 0x63, 0x79, 0xfd, 0x58, 0x04,
0x8e, 0x37, 0xeb, 0xfe, 0xdd, 0xbf, 0xbc, 0xf2, 0x66, 0x1f, 0x5b, 0x00,
0x3c, 0x9e, 0x7f, 0x3f, 0x1e, 0x01, 0xe3, 0xad, 0xe2, 0x1d, 0xc8, 0x2b,
0x6f, 0x35, 0x53, 0x00, 0x0c, 0x15, 0xde, 0x28, 0xde, 0x03, 0xde, 0xe8,
0xf9, 0x96, 0x56, 0x89, 0x21, 0x02, 0x99, 0x45, 0x2f, 0xb3, 0x96, 0xa1,
0xc2, 0x10, 0x81, 0xcc, 0xa2, 0x97, 0x59, 0xcb, 0x50, 0x61, 0x88, 0x40,
0x66, 0xd1, 0xcb, 0xac, 0x65, 0xa8, 0x30, 0x44, 0x20, 0xb3, 0xe8, 0x65,
0xd6, 0x32, 0x54, 0x18, 0x22, 0x90, 0x59, 0xf4, 0x32, 0x6b, 0x19, 0x2a,
0x0c, 0x11, 0xc8, 0x2c, 0x7a, 0x99, 0xb5, 0x0c, 0x15, 0x86, 0x08, 0x64,
0x16, 0xbd, 0xcc, 0x5a, 0x86, 0x0a, 0x43, 0x04, 0x32, 0x8b, 0x5e, 0x66,
0x2d, 0x43, 0x85, 0x21, 0x02, 0x99, 0x45, 0x2f, 0xb3, 0x96, 0xa1, 0xc2,
0x10, 0x81, 0xcc, 0x72, 0xc6, 0x3d, 0xcb, 0x85, 0x1b, 0x2c, 0x43, 0x04,
0x8a, 0x80, 0xbc, 0x52, 0x00, 0x0c, 0x16, 0x06, 0x09, 0xe4, 0x95, 0xbc,
0x52, 0x00, 0x0c, 0x16, 0x06, 0x09, 0xe4, 0x95, 0xbc, 0x52, 0x00, 0x0c,
0x16, 0x06, 0x09, 0xe4, 0x95, 0xbc, 0x52, 0x00, 0x0c, 0x96, 0x41, 0x02,
0xe4, 0x95, 0xbc, 0xda, 0xd3, 0x38, 0xa4, 0x0f, 0x1c, 0x56, 0x74, 0xb0,
0xbc, 0x11, 0x90, 0x57, 0xf2, 0x4a, 0x01, 0x20, 0x34, 0x58, 0xde, 0x06,
0xc8, 0x2b, 0x79, 0xa5, 0x00, 0x10, 0x1a, 0x2c, 0x6f, 0x02, 0xe4, 0x95,
0xbc, 0x52, 0x00, 0x08, 0x0d, 0x96, 0xb7, 0x00, 0xf2, 0x4a, 0x5e, 0x29,
0x00, 0x84, 0x06, 0xcb, 0x1b, 0x00, 0x79, 0x25, 0xaf, 0x14, 0x00, 0x42,
0x83, 0xe5, 0xee, 0x01, 0x79, 0xa5, 0x00, 0x10, 0x1a, 0x2c, 0x77, 0x0e,
0xc8, 0x2b, 0x14, 0x80, 0xd0, 0x60, 0xb9, 0x6b, 0x40, 0x5e, 0xa1, 0x00,
0x84, 0x06, 0xcb, 0x1d, 0x03, 0xf2, 0x8a, 0xdf, 0xbd, 0x39, 0x02, 0x00,
0x50, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x05,
0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x50, 0x00, 0x00,
0x00, 0x05, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x50,
0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x05, 0x00,
0x00, 0x50, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x50, 0x00, 0x00, 0x40,
0x01, 0x00, 0x00, 0x14, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0x9e, 0x62,
0x39, 0x02, 0x38, 0xc7, 0xcc, 0x8c, 0x53, 0xf8, 0x7a, 0xc7, 0x71, 0x1c,
0x4e, 0x01, 0xfc, 0x02, 0x00, 0x00, 0x28, 0x00, 0x00, 0x80, 0x02, 0x00,
0x00, 0x28, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x0a, 0x00, 0x00, 0xa0,
0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x0a, 0x00,
0x00, 0xa0, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00,
0x0a, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0xa0, 0x00,
0x00, 0x00, 0x0a, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00,
0xa0, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x28, 0x00, 0x00, 0x80, 0x02,
0x00, 0x00, 0x28, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x28, 0x00, 0x00,
0x80, 0x02, 0x00, 0x00, 0x28, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x28,
0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x28, 0x00, 0x00, 0x80, 0x02, 0x00,
0x00, 0x28, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x28, 0x00, 0x00, 0x80,
0x02, 0x00, 0x00, 0x28, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0xb9, 0x02,
0x30, 0x33, 0xe3, 0x18, 0xe0, 0x73, 0xcc, 0x91, 0xb3, 0x86, 0xdd, 0xe6,
0xc8, 0x2f, 0x00, 0x00, 0x50, 0xfc, 0x05, 0x40, 0xa3, 0x06, 0x5f, 0xa4,
0xce, 0x1c, 0x7a, 0xf3, 0xe3, 0x17, 0x00, 0x00, 0xa8, 0xfe, 0x02, 0xa0,
0x51, 0x83, 0x2f, 0x51, 0x67, 0x0f, 0xad, 0xb9, 0x79, 0x33, 0x50, 0x60,
0x01, 0xb9, 0x03, 0xe8, 0xcd, 0xcb, 0x9b, 0x81, 0x02, 0x8b, 0xc7, 0x5d,
0x40, 0x6f, 0x4e, 0xde, 0x0c, 0x14, 0x58, 0x38, 0xee, 0x04, 0x7a, 0xf3,
0xb1, 0x5e, 0xfd, 0x3f, 0x1c, 0xc7, 0x71, 0x38, 0x3e, 0xb0, 0x64, 0x76,
0xb9, 0x1f, 0x99, 0x05, 0xef, 0xcb, 0xac, 0x65, 0xa8, 0xc0, 0xe2, 0x57,
0x04, 0xa0, 0x97, 0x59, 0xcb, 0x50, 0x81, 0xc5, 0xaf, 0x08, 0x40, 0x2f,
0xb3, 0x96, 0xa1, 0x02, 0x8b, 0x5f, 0x11, 0x80, 0x5e, 0x66, 0x2d, 0x43,
0x05, 0x16, 0xbf, 0x22, 0x00, 0xbd, 0xcc, 0x5a, 0x86, 0x0a, 0x43, 0x64,
0xf1, 0x2b, 0x02, 0xd0, 0xcb, 0xac, 0x65, 0xa8, 0x30, 0x44, 0x28, 0x02,
0xd0, 0xcb, 0xac, 0x65, 0xa8, 0x30, 0x44, 0x78, 0x0f, 0x32, 0x8b, 0x5e,
0x66, 0x2d, 0x43, 0x85, 0x21, 0x02, 0x99, 0x45, 0x2f, 0xb3, 0x96, 0xa1,
0xc2, 0x10, 0x81, 0xcc, 0xa2, 0x97, 0x59, 0xcb, 0x50, 0x61, 0x88, 0x40,
0x66, 0xd1, 0xcb, 0xac, 0x65, 0xa8, 0x30, 0x44, 0x20, 0xb3, 0xe8, 0x65,
0xd6, 0x32, 0x54, 0x18, 0x22, 0x90, 0x59, 0xf4, 0x32, 0x6b, 0x19, 0x2a,
0x0c, 0x11, 0xc8, 0x2c, 0x7a, 0x99, 0xb5, 0x0c, 0x15, 0x86, 0x08, 0x64,
0x16, 0xbd, 0xcc, 0x5a, 0x86, 0x0a, 0x43, 0x04, 0x32, 0x8b, 0x5e, 0x66,
0x2d, 0x43, 0x85, 0x21, 0x02, 0x99, 0x45, 0x2f, 0xb3, 0x96, 0xa1, 0xc2,
0x10, 0x81, 0xcc, 0xa2, 0x97, 0x59, 0xcb, 0x50, 0x61, 0x88, 0x40, 0x66,
0xd1, 0xcb, 0xac, 0x65, 0xa8, 0x30, 0x44, 0x20, 0xb3, 0xe8, 0x65, 0xd6,
0x32, 0x54, 0x18, 0x22, 0x90, 0x59, 0xf4, 0x32, 0x6b, 0x19, 0x2a, 0x0c,
0x11, 0xc8, 0x2c, 0x7a, 0x99, 0xb5, 0x0c, 0x15, 0x86, 0x08, 0x64, 0x16,
0xbd, 0xcc, 0x5a, 0x86, 0x0a, 0x43, 0x04, 0x32, 0x8b, 0x5e, 0x66, 0x2d,
0x43, 0x85, 0x21, 0x02, 0x99, 0x45, 0x2f, 0xb3, 0x96, 0xa1, 0xc2, 0x10,
0x81, 0xcc, 0xa2, 0x97, 0x59, 0xcb, 0x50, 0x61, 0x88, 0x40, 0x66, 0xd1,
0xcb, 0xac, 0x65, 0xa8, 0x30, 0x44, 0x20, 0xb3, 0x9c, 0x71, 0xcf, 0x32,
0x54, 0x86, 0xca, 0x10, 0x81, 0xcc, 0x92, 0x59, 0x0a, 0x80, 0xa1, 0xc2,
0x10, 0x81, 0xcc, 0x92, 0x59, 0x0a, 0x80, 0xa1, 0xc2, 0x10, 0x81, 0xcc,
0x92, 0x59, 0x0a, 0x80, 0xa1, 0xc2, 0x10, 0x81, 0xcc, 0x92, 0x59, 0x0a,
0x80, 0xa1, 0x32, 0x44, 0x80, 0xcc, 0x92, 0x59, 0x0a, 0x80, 0xa1, 0x32,
0x44, 0x80, 0xcc, 0x92, 0x59, 0x0a, 0x80, 0xa1, 0x32, 0x44, 0x80, 0xcc,
0x92, 0x59, 0x0a, 0x80, 0xa1, 0x32, 0x44, 0x80, 0xcc, 0x92, 0x59, 0x0a,
0x80, 0xa1, 0x32, 0x44, 0x80, 0xcc, 0x92, 0x59, 0x0a, 0xc0, 0x23, 0x1e,
0xe0, 0xae, 0x83, 0x65, 0x88, 0x40, 0x11, 0x90, 0x57, 0x0a, 0x00, 0xa1,
0xc1, 0x32, 0x48, 0x20, 0xaf, 0xe4, 0x95, 0x02, 0x40, 0x68, 0xb0, 0x0c,
0x12, 0x20, 0xaf, 0x50, 0x00, 0x42, 0x83, 0x65, 0x90, 0x00, 0x79, 0xc5,
0x0f, 0x7f, 0x03, 0x6b, 0x00, 0x01, 0xd3, 0x9f, 0x8a, 0xff, 0x63, 0x00,
0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82,
}

163
cmd/agent/installer.go Normal file
View File

@ -0,0 +1,163 @@
package main
import (
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"os"
"os/exec"
"syscall"
"time"
events "github.com/c3os-io/c3os/pkg/bus"
config "github.com/c3os-io/c3os/pkg/config"
"github.com/c3os-io/c3os/internal/bus"
"github.com/c3os-io/c3os/internal/c3os"
"github.com/c3os-io/c3os/internal/cmd"
"github.com/c3os-io/c3os/internal/utils"
machine "github.com/c3os-io/c3os/internal/machine"
qr "github.com/mudler/go-nodepair/qrcode"
"github.com/mudler/go-pluggable"
"github.com/pterm/pterm"
"gopkg.in/yaml.v2"
)
func optsToArgs(options map[string]string) (res []string) {
for k, v := range options {
if k != "device" && k != "cc" && k != "reboot" && k != "poweroff" {
res = append(res, fmt.Sprintf("--%s", k))
res = append(res, fmt.Sprintf("%s", v))
}
}
return
}
func install(dir ...string) error {
utils.OnSignal(func() {
svc, err := machine.Getty(1)
if err == nil {
svc.Start()
}
}, syscall.SIGINT, syscall.SIGTERM)
tk := ""
r := map[string]string{}
bus.Manager.Response(events.EventChallenge, func(p *pluggable.Plugin, r *pluggable.EventResponse) {
tk = r.Data
})
bus.Manager.Response(events.EventInstall, func(p *pluggable.Plugin, resp *pluggable.EventResponse) {
err := json.Unmarshal([]byte(resp.Data), &r)
if err != nil {
fmt.Println(err)
}
})
// Reads config, and if present and offline is defined,
// runs the installation
cc, err := config.Scan(dir...)
if err == nil && cc.C3OS != nil && cc.C3OS.Offline {
runInstall(map[string]string{
"device": cc.C3OS.Device,
"cc": cc.String(),
})
svc, err := machine.Getty(1)
if err == nil {
svc.Start()
}
return nil
}
_, err = bus.Manager.Publish(events.EventChallenge, events.EventPayload{Config: cc.String()})
if err != nil {
return err
}
cmd.PrintBranding(banner)
cmd.PrintTextFromFile(c3os.BrandingFile("install_text"), "Installation")
time.Sleep(5 * time.Second)
if tk != "" {
qr.Print(tk)
}
if _, err := bus.Manager.Publish(events.EventInstall, events.InstallPayload{Token: tk, Config: cc.String()}); err != nil {
return err
}
if len(r) == 0 {
return errors.New("no configuration, stopping installation")
}
pterm.Info.Println("Starting installation")
utils.SH("elemental run-stage c3os-install.pre")
bus.RunHookScript("/usr/bin/c3os-agent.install.pre.hook")
runInstall(r)
pterm.Info.Println("Installation completed, press enter to go back to the shell.")
utils.Prompt("")
// give tty1 back
svc, err := machine.Getty(1)
if err == nil {
svc.Start()
}
return nil
}
func runInstall(options map[string]string) error {
f, _ := ioutil.TempFile("", "xxxx")
device, ok := options["device"]
if !ok {
fmt.Println("device must be specified among options")
os.Exit(1)
}
cloudInit, ok := options["cc"]
if !ok {
fmt.Println("cloudInit must be specified among options")
os.Exit(1)
}
c := &config.Config{}
yaml.Unmarshal([]byte(cloudInit), c)
_, reboot := options["reboot"]
_, poweroff := options["poweroff"]
ioutil.WriteFile(f.Name(), []byte(cloudInit), os.ModePerm)
args := []string{"install"}
args = append(args, optsToArgs(options)...)
args = append(args, "-c", f.Name(), fmt.Sprintf("%s", device))
cmd := exec.Command("elemental", args...)
cmd.Env = os.Environ()
cmd.Stdout = os.Stdout
cmd.Stdin = os.Stdin
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
fmt.Println(err)
os.Exit(1)
}
utils.SH("elemental run-stage c3os-install.after")
bus.RunHookScript("/usr/bin/c3os-agent.install.after.hook")
if reboot || c.C3OS != nil && c.C3OS.Reboot {
utils.Reboot()
}
if poweroff || c.C3OS != nil && c.C3OS.Poweroff {
utils.PowerOFF()
}
return nil
}

View File

@ -0,0 +1,13 @@
package main_test
import (
"testing"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)
func TestInstaller(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "Installer Suite")
}

286
cmd/agent/main.go Normal file
View File

@ -0,0 +1,286 @@
package main
import (
//"fmt"
"context"
"encoding/json"
"fmt"
"os"
"strings"
"github.com/c3os-io/c3os/internal/bus"
cmd "github.com/c3os-io/c3os/internal/cmd"
machine "github.com/c3os-io/c3os/internal/machine"
"github.com/c3os-io/c3os/internal/github"
config "github.com/c3os-io/c3os/pkg/config"
"github.com/urfave/cli"
"gopkg.in/yaml.v2"
)
var cmds = []cli.Command{
{
Name: "upgrade",
Flags: []cli.Flag{
&cli.BoolFlag{
Name: "force",
Usage: "Force an upgrade",
},
&cli.StringFlag{
Name: "image",
Usage: "Specify an full image reference, e.g.: quay.io/some/image:tag",
},
},
Description: `
Manually upgrade a c3os node.
By default takes no arguments, defaulting to latest available release, to specify a version, pass it as argument:
$ c3os upgrade v1.20....
To retrieve all the available versions, use "c3os upgrade list-releases"
$ c3os upgrade list-releases
See https://docs.c3os.io/after_install/upgrades/#manual for documentation.
`,
Subcommands: []cli.Command{
{
Flags: []cli.Flag{
&cli.StringFlag{
Name: "output",
Usage: "Output format (json|yaml|terminal)",
},
},
Name: "list-releases",
Description: `List all available releases versions`,
Action: func(c *cli.Context) error {
rels, err := github.FindReleases(context.Background(), "", "c3os-io/c3os")
if err != nil {
return err
}
switch strings.ToLower(c.String("output")) {
case "yaml":
d, _ := yaml.Marshal(rels)
fmt.Println(string(d))
case "json":
d, _ := json.Marshal(rels)
fmt.Println(string(d))
default:
for _, r := range rels {
fmt.Println(r)
}
}
return nil
},
},
},
Action: func(c *cli.Context) error {
args := c.Args()
var v string
if len(args) == 1 {
v = args[0]
}
return upgrade(v, c.String("image"), c.Bool("force"))
},
},
{
Name: "start",
Usage: "Starts the c3os agent",
UsageText: "starts the agent",
Description: `
Starts the c3os agent which automatically bootstrap and advertize to the c3os network.
`,
Aliases: []string{"s"},
Flags: []cli.Flag{
&cli.BoolFlag{
Name: "force",
},
&cli.StringFlag{
Name: "api",
Value: "http://127.0.0.1:8080",
},
},
Action: func(c *cli.Context) error {
dirs := []string{"/oem", "/usr/local/cloud-config"}
args := c.Args()
if len(args) > 0 {
dirs = args
}
return agent(c.String("api"), dirs, c.Bool("force"))
},
},
{
Name: "rotate",
Usage: "Rotate a c3os node network configuration via CLI",
Description: `
Updates a c3os node VPN configuration.
For example, to update the network token in a node:
$ c3os rotate --network-token XXX
`,
Aliases: []string{"r"},
Flags: []cli.Flag{
&cli.BoolFlag{
Name: "restart",
},
&cli.StringFlag{
Name: "network-token",
EnvVar: "NETWORK_TOKEN",
},
&cli.StringFlag{
Name: "api",
Value: "127.0.0.1:8080",
},
&cli.StringFlag{
Name: "root-dir",
},
},
UsageText: "Rotate network token manually in the node",
Action: func(c *cli.Context) error {
dirs := []string{"/oem", "/usr/local/cloud-config"}
args := c.Args()
if len(args) > 0 {
dirs = args
}
return rotate(dirs, c.String("network-token"), c.String("api"), c.String("root-dir"), c.Bool("restart"))
},
},
{
Name: "get-network-token",
Description: "Print network token from local configuration",
Usage: "Print network token from local configuration",
Action: func(c *cli.Context) error {
dirs := []string{"/oem", "/usr/local/cloud-config"}
args := c.Args()
if len(args) > 0 {
dirs = args
}
cc, err := config.Scan(dirs...)
if err != nil {
return err
}
fmt.Print(cc.C3OS.NetworkToken)
return nil
},
},
{
Name: "uuid",
Usage: "Prints the local UUID",
Description: "Print node uuid",
Aliases: []string{"u"},
Action: func(c *cli.Context) error {
fmt.Print(machine.UUID())
return nil
},
},
{
Name: "interactive-install",
Description: `
Starts c3os in interactive mode.
It will ask prompt for several questions and perform an install
See also https://docs.c3os.io/installation/interactive_install/ for documentation.
This command is meant to be used from the boot GRUB menu, but can be started manually`,
Flags: []cli.Flag{
&cli.BoolFlag{
Name: "shell",
},
},
Usage: "Starts interactive installation",
Action: func(c *cli.Context) error {
return interactiveInstall(c.Bool("shell"))
},
},
{
Name: "install",
Usage: "Starts the c3os pairing installation",
Description: `
Starts c3os in pairing mode.
It will print out a QR code which can be used with "c3os register" to send over a configuration and bootstraping a c3os node.
See also https://docs.c3os.io/installation/device_pairing/ for documentation.
This command is meant to be used from the boot GRUB menu, but can be started manually`,
Aliases: []string{"i"},
Action: func(c *cli.Context) error {
return install("/oem", "/usr/local/cloud-config", "/run/initramfs/live")
},
},
{
Name: "recovery",
Aliases: []string{"r"},
Action: recovery,
Usage: "Starts c3os recovery mode",
Description: `
Starts c3os recovery mode.
In recovery mode a QR code will be printed out on the screen which should be used in conjuction with "c3os bridge". Pass by the QR code as snapshot
to the bridge to connect over the machine which runs the "c3os recovery" command.
See also https://docs.c3os.io/after_install/recovery_mode/ for documentation.
This command is meant to be used from the boot GRUB menu, but can likely be used standalone`,
},
{
Name: "reset",
Action: reset,
Usage: "Starts c3os reset mode",
Description: `
Starts c3os reset mode, it will nuke completely the node data and restart fresh.
Attention ! this will delete any persistent data on the node. It is equivalent to re-init the node right after the installation.
In reset mode a the node will automatically reset
See also https://docs.c3os.io/after_install/reset_mode/ for documentation.
This command is meant to be used from the boot GRUB menu, but can likely be used standalone`,
},
}
func main() {
bus.Manager.Initialize()
app := &cli.App{
Name: "c3os",
Version: "0.1",
Author: "Ettore Di Giacinto",
Usage: "c3os CLI to bootstrap, upgrade, connect and manage a c3os network",
Description: `
The c3os CLI can be used to manage a c3os box and perform all day-two tasks, like:
- register a node
- connect to a node in recovery mode
- to establish a VPN connection
- set, list roles
- interact with the network API
and much more.
For all the example cases, see: https://docs.c3os.io .
`,
UsageText: ``,
Copyright: "Ettore Di Giacinto",
Commands: cmd.CommonCommand(cmds...),
}
err := app.Run(os.Args)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
}

36
cmd/agent/make_art.sh Executable file
View File

@ -0,0 +1,36 @@
#/bin/sh
if [ -z "$GOPATH" ]; then
echo GOPATH environment variable not set
exit
fi
if [ ! -e "$GOPATH/bin/2goarray" ]; then
echo "Installing 2goarray..."
go get github.com/cratonica/2goarray
if [ $? -ne 0 ]; then
echo Failure executing go get github.com/cratonica/2goarray
exit
fi
fi
if [ -z "$1" ]; then
echo Please specify a PNG file
exit
fi
if [ ! -f "$1" ]; then
echo $1 is not a valid file
exit
fi
OUTPUT=iconunix.go
echo Generating $OUTPUT
echo "//+build linux darwin" > $OUTPUT
echo >> $OUTPUT
cat "$1" | $GOPATH/bin/2goarray banner main >> $OUTPUT
if [ $? -ne 0 ]; then
echo Failure generating $OUTPUT
exit
fi
echo Finished

View File

@ -0,0 +1,221 @@
package main
import (
"fmt"
"strings"
"github.com/c3os-io/c3os/internal/cmd"
"github.com/c3os-io/c3os/internal/utils"
config "github.com/c3os-io/c3os/pkg/config"
"github.com/erikgeiser/promptkit/textinput"
"github.com/jaypipes/ghw"
"github.com/mudler/edgevpn/pkg/node"
"github.com/mudler/yip/pkg/schema"
"github.com/pterm/pterm"
"gopkg.in/yaml.v2"
)
const (
canBeEmpty = "Unset"
yesNo = "[y]es/[N]o"
)
func prompt(prompt, initialValue, placeHolder string, canBeEmpty, hidden bool) (string, error) {
input := textinput.New(prompt)
input.InitialValue = initialValue
input.Placeholder = placeHolder
if canBeEmpty {
input.Validate = func(s string) bool { return true }
}
input.Hidden = hidden
return input.RunPrompt()
}
func isYes(s string) bool {
i := strings.ToLower(s)
if i == "y" || i == "yes" {
return true
}
return false
}
const (
_ = 1 << (10 * iota)
KiB
MiB
GiB
TiB
)
func interactiveInstall(spawnShell bool) error {
cmd.PrintBranding(banner)
pterm.DefaultBox.WithTitle("Installation").WithTitleBottomRight().WithRightPadding(0).WithBottomPadding(0).Println(
`Interactive installation. Documentation is available at https://docs.c3os.io.`)
disks := []string{}
maxSize := float64(0)
preferedDevice := "/dev/sda"
block, err := ghw.Block()
if err == nil {
for _, disk := range block.Disks {
size := float64(disk.SizeBytes) / float64(GiB)
if size > maxSize {
maxSize = size
preferedDevice = "/dev/" + disk.Name
}
disks = append(disks, fmt.Sprintf("/dev/%s: %s (%.2f GiB) ", disk.Name, disk.Model, float64(disk.SizeBytes)/float64(GiB)))
}
}
pterm.Info.Println("Available Disks:")
for _, d := range disks {
pterm.Info.Println(" " + d)
}
var networkToken string
device, err := prompt("What's the target install device?", preferedDevice, "Cannot be empty", false, false)
if err != nil {
return err
}
userName, err := prompt("User to setup", "c3os", canBeEmpty, true, false)
if err != nil {
return err
}
userPassword, err := prompt("Password", "", canBeEmpty, true, true)
if err != nil {
return err
}
if userPassword == "" {
userPassword = "!"
}
sshUsername, err := prompt("Username to grant SSH access to (github/gitlab supported)", "github:someuser", canBeEmpty, true, false)
if err != nil {
return err
}
sshPubkey, err := prompt("SSH pubkey", "github:username", canBeEmpty, true, false)
if err != nil {
return err
}
k3sAuto, err := prompt("Do you want to enable k3s automated setup? (requires multiple nodes)", "n", yesNo, true, false)
if err != nil {
return err
}
if isYes(k3sAuto) {
hasNetworkToken, err := prompt("Do you have a network token already?", "n", yesNo, true, false)
if err != nil {
return err
}
if isYes(hasNetworkToken) {
networkToken, err = prompt("Input network token", "", "", false, true)
if err != nil {
return err
}
} else {
networkToken = node.GenerateNewConnectionData().Base64()
}
}
k3sStandalone, err := prompt("Do you want to enable k3s standalone?", "n", yesNo, true, false)
if err != nil {
return err
}
allGood, err := prompt("Are settings ok?", "n", yesNo, true, false)
if err != nil {
return err
}
if !isYes(allGood) {
return interactiveInstall(spawnShell)
}
c := &config.Config{
C3OS: &config.C3OS{
NetworkToken: networkToken,
Device: device,
},
K3s: config.K3s{
Enabled: isYes(k3sStandalone),
},
}
usersToSet := map[string]schema.User{}
if userName != "" {
user := schema.User{
Name: userName,
PasswordHash: userPassword,
Groups: []string{"admin"},
}
if sshUsername != "" {
user.SSHAuthorizedKeys = append(user.SSHAuthorizedKeys, sshUsername)
}
if sshPubkey != "" {
user.SSHAuthorizedKeys = append(user.SSHAuthorizedKeys, sshPubkey)
}
usersToSet = map[string]schema.User{
userName: user,
}
}
cloudConfig := schema.YipConfig{Name: "Config generated by the installer",
Stages: map[string][]schema.Stage{config.NetworkStage.String(): {
{
Users: usersToSet,
},
}}}
dat, err := yaml.Marshal(cloudConfig)
if err != nil {
return err
}
dat2, err := yaml.Marshal(c)
if err != nil {
return err
}
content1 := make(map[string]interface{})
err = yaml.Unmarshal(dat, &content1)
if err != nil {
return err
}
err = yaml.Unmarshal(dat2, &content1)
if err != nil {
return err
}
dat, err = yaml.Marshal(content1)
if err != nil {
return err
}
pterm.Info.Println("Starting installation")
err = runInstall(map[string]string{
"device": device,
"cc": string(dat),
})
if err != nil {
pterm.Error.Println(err.Error())
}
if spawnShell {
return utils.Shell().Run()
}
return err
}

130
cmd/agent/recovery.go Normal file
View File

@ -0,0 +1,130 @@
package main
import (
"context"
"fmt"
"io"
"os/exec"
"time"
"github.com/c3os-io/c3os/internal/c3os"
"github.com/c3os-io/c3os/internal/cmd"
"github.com/c3os-io/c3os/internal/utils"
config "github.com/c3os-io/c3os/pkg/config"
"github.com/ipfs/go-log"
"github.com/urfave/cli"
machine "github.com/c3os-io/c3os/internal/machine"
"github.com/creack/pty"
"github.com/gliderlabs/ssh"
"github.com/mudler/edgevpn/pkg/logger"
"github.com/mudler/edgevpn/pkg/node"
"github.com/mudler/edgevpn/pkg/services"
nodepair "github.com/mudler/go-nodepair"
qr "github.com/mudler/go-nodepair/qrcode"
"github.com/pterm/pterm"
)
const recoveryAddr = "127.0.0.1:2222"
func startRecoveryService(ctx context.Context, token, name, address, loglevel string) error {
nc := config.Network(token, "", loglevel, "c3osrecovery0")
lvl, err := log.LevelFromString(loglevel)
if err != nil {
lvl = log.LevelError
}
llger := logger.New(lvl)
o, _, err := nc.ToOpts(llger)
if err != nil {
llger.Fatal(err.Error())
}
o = append(o,
services.Alive(
time.Duration(20)*time.Second,
time.Duration(10)*time.Second,
time.Duration(10)*time.Second)...)
// opts, err := vpn.Register(vpnOpts...)
// if err != nil {
// return err
// }
o = append(o, services.RegisterService(llger, time.Duration(5*time.Second), name, address)...)
e, err := node.New(o...)
if err != nil {
return err
}
return e.Start(ctx)
}
func recovery(c *cli.Context) error {
cmd.PrintBranding(banner)
tk := nodepair.GenerateToken()
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
serviceUUID := utils.RandStringRunes(10)
generatedPassword := utils.RandStringRunes(7)
startRecoveryService(ctx, tk, serviceUUID, recoveryAddr, "fatal")
cmd.PrintTextFromFile(c3os.BrandingFile("recovery_text"), "Recovery")
time.Sleep(5 * time.Second)
pterm.Info.Printfln(
"starting ssh server on '%s', password: '%s' service: '%s' ", recoveryAddr, generatedPassword, serviceUUID)
qr.Print(utils.EncodeRecoveryToken(tk, serviceUUID, generatedPassword))
go sshServer(recoveryAddr, generatedPassword)
// Wait for user input and go back to shell
utils.Prompt("")
cancel()
// give tty1 back
svc, err := machine.Getty(1)
if err == nil {
svc.Start()
}
return nil
}
func sshServer(listenAdddr, password string) {
ssh.Handle(func(s ssh.Session) {
cmd := exec.Command("bash")
ptyReq, winCh, isPty := s.Pty()
if isPty {
cmd.Env = append(cmd.Env, fmt.Sprintf("TERM=%s", ptyReq.Term))
f, err := pty.Start(cmd)
if err != nil {
pterm.Warning.Println("Failed reserving tty")
}
go func() {
for win := range winCh {
setWinsize(f, win.Width, win.Height)
}
}()
go func() {
io.Copy(f, s) // stdin
}()
io.Copy(s, f) // stdout
cmd.Wait()
} else {
io.WriteString(s, "No PTY requested.\n")
s.Exit(1)
}
})
pterm.Info.Println(ssh.ListenAndServe(listenAdddr, nil, ssh.PasswordAuth(func(ctx ssh.Context, pass string) bool {
return pass == password
}),
))
}

View File

@ -0,0 +1,12 @@
package main
import (
"os"
"syscall"
"unsafe"
)
func setWinsize(f *os.File, w, h int) {
syscall.Syscall(syscall.SYS_IOCTL, f.Fd(), uintptr(syscall.TIOCSWINSZ),
uintptr(unsafe.Pointer(&struct{ h, w, x, y uint16 }{uint16(h), uint16(w), 0, 0})))
}

View File

@ -0,0 +1,8 @@
package main
import (
"os"
)
func setWinsize(f *os.File, w, h int) {
}

78
cmd/agent/reset.go Normal file
View File

@ -0,0 +1,78 @@
package main
import (
"fmt"
"os"
"os/exec"
"sync"
"time"
"github.com/c3os-io/c3os/internal/c3os"
"github.com/c3os-io/c3os/internal/cmd"
"github.com/c3os-io/c3os/internal/machine"
"github.com/c3os-io/c3os/internal/utils"
"github.com/pterm/pterm"
"github.com/urfave/cli"
)
func reset(c *cli.Context) error {
cmd.PrintBranding(banner)
cmd.PrintTextFromFile(c3os.BrandingFile("reset_text"), "Reset")
// We don't close the lock, as none of the following actions are expected to return
lock := sync.Mutex{}
go func() {
// Wait for user input and go back to shell
utils.Prompt("")
// give tty1 back
svc, err := machine.Getty(1)
if err == nil {
svc.Start()
}
lock.Lock()
fmt.Println("Reset aborted")
panic(utils.Shell().Run())
}()
time.Sleep(60 * time.Second)
lock.Lock()
args := []string{"reset"}
args = append(args, "--reset-persistent")
cmd := exec.Command("elemental", args...)
cmd.Env = os.Environ()
cmd.Stdout = os.Stdout
cmd.Stdin = os.Stdin
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
fmt.Println(err)
os.Exit(1)
}
pterm.Info.Println("Rebooting in 60 seconds, press Enter to abort...")
// We don't close the lock, as none of the following actions are expected to return
lock2 := sync.Mutex{}
go func() {
// Wait for user input and go back to shell
utils.Prompt("")
// give tty1 back
svc, err := machine.Getty(1)
if err == nil {
svc.Start()
}
lock2.Lock()
fmt.Println("Reboot aborted")
panic(utils.Shell().Run())
}()
time.Sleep(60 * time.Second)
lock2.Lock()
utils.Reboot()
return nil
}

33
cmd/agent/rotate.go Normal file
View File

@ -0,0 +1,33 @@
package main
import (
machine "github.com/c3os-io/c3os/internal/machine"
"github.com/c3os-io/c3os/internal/vpn"
config "github.com/c3os-io/c3os/pkg/config"
)
func rotate(configDir []string, newToken, apiAddress, rootDir string, restart bool) error {
if err := config.ReplaceToken(configDir, newToken); err != nil {
return err
}
c, err := config.Scan(configDir...)
if err != nil {
return err
}
err = vpn.Setup(machine.EdgeVPNDefaultInstance, apiAddress, rootDir, false, c)
if err != nil {
return err
}
if restart {
svc, err := machine.EdgeVPN(machine.EdgeVPNDefaultInstance, rootDir)
if err != nil {
return err
}
return svc.Restart()
}
return nil
}

51
cmd/agent/upgrade.go Normal file
View File

@ -0,0 +1,51 @@
package main
import (
"context"
"errors"
"fmt"
"os"
"os/exec"
"github.com/c3os-io/c3os/internal/github"
"github.com/c3os-io/c3os/internal/utils"
)
func upgrade(version, image string, force bool) error {
if version == "" && image == "" {
githubRepo, err := utils.OSRelease("GITHUB_REPO")
if err != nil {
return err
}
releases, _ := github.FindReleases(context.Background(), "", githubRepo)
version = releases[0]
fmt.Println("latest release is ", version)
}
if utils.Version() == version && !force {
fmt.Println("latest version already installed. use --force to force upgrade")
return nil
}
flavor := utils.Flavor()
if flavor == "" {
return errors.New("no flavor detected")
}
registry, err := utils.OSRelease("IMAGE_REPO")
if err != nil {
return err
}
img := fmt.Sprintf("%s:%s-%s", registry, flavor, version)
if image != "" {
img = image
}
args := []string{"upgrade", "--system.uri", fmt.Sprintf("docker:%s", img)}
cmd := exec.Command("elemental", args...)
cmd.Env = os.Environ()
cmd.Stdout = os.Stdout
cmd.Stdin = os.Stdin
cmd.Stderr = os.Stderr
return cmd.Run()
}

118
cmd/cli/bridge.go Normal file
View File

@ -0,0 +1,118 @@
package main
import (
"context"
"fmt"
"net"
"time"
"github.com/c3os-io/c3os/internal/utils"
"github.com/c3os-io/c3os/pkg/config"
"github.com/ipfs/go-log"
"github.com/mudler/edgevpn/api"
"github.com/mudler/edgevpn/pkg/logger"
"github.com/mudler/edgevpn/pkg/node"
"github.com/mudler/edgevpn/pkg/services"
"github.com/mudler/edgevpn/pkg/vpn"
qr "github.com/mudler/go-nodepair/qrcode"
"github.com/urfave/cli"
)
// bridge is just starting a VPN with edgevpn to the given network token.
func bridge(c *cli.Context) error {
qrCodePath := ""
fromQRCode := false
var serviceUUID, sshPassword string
if c.String("qr-code-image") != "" {
qrCodePath = c.String("qr-code-image")
fromQRCode = true
}
if c.Bool("qr-code-snapshot") {
qrCodePath = ""
fromQRCode = true
}
token := c.String("network-token")
if fromQRCode {
recoveryToken := qr.Reader(qrCodePath)
data := utils.DecodeRecoveryToken(recoveryToken)
if len(data) != 3 {
fmt.Println("Token not decoded correctly")
return fmt.Errorf("invalid token")
}
token = data[0]
serviceUUID = data[1]
sshPassword = data[2]
if serviceUUID == "" || sshPassword == "" || token == "" {
return fmt.Errorf("decoded invalid values")
}
}
ctx := context.Background()
nc := config.Network(token, c.String("address"), c.String("log-level"), "c3os0")
lvl, err := log.LevelFromString(nc.LogLevel)
if err != nil {
lvl = log.LevelError
}
llger := logger.New(lvl)
o, vpnOpts, err := nc.ToOpts(llger)
if err != nil {
llger.Fatal(err.Error())
}
opts := []node.Option{}
if !fromQRCode {
// We just connect to a VPN token
o = append(o,
services.Alive(
time.Duration(20)*time.Second,
time.Duration(10)*time.Second,
time.Duration(10)*time.Second)...)
if c.Bool("dhcp") {
// Adds DHCP server
address, _, err := net.ParseCIDR(c.String("address"))
if err != nil {
return err
}
nodeOpts, vO := vpn.DHCP(llger, 15*time.Minute, c.String("lease-dir"), address.String())
o = append(o, nodeOpts...)
vpnOpts = append(vpnOpts, vO...)
}
opts, err = vpn.Register(vpnOpts...)
if err != nil {
return err
}
} else {
// We hook into a service
llger.Info("Connecting to service", serviceUUID)
llger.Info("SSH access password is", sshPassword)
llger.Info("SSH server reachable at 127.0.0.1:2200")
opts = append(opts, node.WithNetworkService(
services.ConnectNetworkService(
30*time.Second,
serviceUUID,
"127.0.0.1:2200",
),
))
llger.Info("To connect, keep this terminal open and run in another terminal 'ssh 127.0.0.1 -p 2200' the password is ", sshPassword)
llger.Info("Note: the connection might not be available instantly and first attempts will likely fail.")
llger.Info(" Few attempts might be required before establishing a tunnel to the host.")
}
e, err := node.New(append(o, opts...)...)
if err != nil {
return err
}
go api.API(ctx, c.String("api"), 5*time.Second, 20*time.Second, e, nil, false)
return e.Start(ctx)
}

181
cmd/cli/main.go Normal file
View File

@ -0,0 +1,181 @@
package main
import (
//"fmt"
"fmt"
"os"
cmd "github.com/c3os-io/c3os/internal/cmd"
"github.com/urfave/cli"
)
var cliCmd = []cli.Command{
{
Name: "register",
UsageText: "register --reboot --device /dev/sda /image/snapshot.png",
Usage: "Registers and bootstraps a node",
Description: `
Bootstraps a node which is started in pairing mode. It can send over a configuration file used to install the c3os node.
For example:
$ c3os register --config config.yaml --device /dev/sda ~/Downloads/screenshot.png
will decode the QR code from ~/Downloads/screenshot.png and bootstrap the node remotely.
If the image is omitted, a screenshot will be taken and used to decode the QR code.
See also https://docs.c3os.io/installation/device_pairing/ for documentation.
`,
ArgsUsage: "Register optionally accepts an image. If nothing is passed will take a screenshot of the screen and try to decode the QR code",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "config",
Usage: "C3OS YAML configuration file",
},
&cli.StringFlag{
Name: "device",
Usage: "Device used for the installation target",
},
&cli.BoolFlag{
Name: "reboot",
Usage: "Reboot node after installation",
},
&cli.BoolFlag{
Name: "poweroff",
Usage: "Shutdown node after installation",
},
&cli.StringFlag{
Name: "log-level",
Usage: "Set log level",
},
},
Action: func(c *cli.Context) error {
args := c.Args()
var ref string
if len(args) == 1 {
ref = args[0]
}
return register(c.String("log-level"), ref, c.String("config"), c.String("device"), c.Bool("reboot"), c.Bool("poweroff"))
},
},
{
Name: "bridge",
UsageText: "bridge --network-token XXX",
Usage: "Connect to a c3os VPN network",
Description: `
Starts a bridge with a c3os network or a node.
# With a network
By default, "bridge" will create a VPN network connection to the node with the token supplied, thus it requires elevated permissions in order to work.
For example:
$ sudo c3os bridge --network-token <TOKEN>
Will start a VPN, which local ip is fixed to 10.1.0.254 (tweakable with --address).
The API will also be accessible at http://127.0.0.1:8080
# With a node
"c3os bridge" can be used also to connect over to a node in recovery mode. When operating in this modality c3os bridge requires no specific permissions, indeed a tunnel
will be created locally to connect to the machine remotely.
For example:
$ c3os bridge --qr-code-image /path/to/image.png
Will scan the QR code in the image and connect over. Further instructions on how to connect over will be printed out to the screen.
See also: https://docs.c3os.io/after_install/troubleshooting/#connect-to-the-cluster-network and https://docs.c3os.io/after_install/recovery_mode/
`,
Flags: []cli.Flag{
&cli.StringFlag{
Name: "network-token",
Required: false,
EnvVar: "NETWORK_TOKEN",
Usage: "Network token to connect over",
},
&cli.StringFlag{
Name: "log-level",
Required: false,
EnvVar: "LOGLEVEL",
Value: "info",
Usage: "Bridge log level",
},
&cli.BoolFlag{
Name: "qr-code-snapshot",
Required: false,
Usage: "Bool to take a local snapshot instead of reading from an image file for recovery",
EnvVar: "QR_CODE_SNAPSHOT",
},
&cli.StringFlag{
Name: "qr-code-image",
Usage: "Path to an image containing a valid QR code for recovery mode",
Required: false,
EnvVar: "QR_CODE_IMAGE",
},
&cli.StringFlag{
Name: "api",
Value: "127.0.0.1:8080",
Usage: "Listening API url",
},
&cli.BoolFlag{
Name: "dhcp",
EnvVar: "DHCP",
Usage: "Enable DHCP",
},
&cli.StringFlag{
Value: "10.1.0.254/24",
Name: "address",
EnvVar: "ADDRESS",
Usage: "Specify an address for the bridge",
},
&cli.StringFlag{
Value: "/tmp/c3os",
Name: "lease-dir",
EnvVar: "lease-dir",
Usage: "DHCP Lease directory",
},
},
Action: bridge,
},
}
func main() {
app := &cli.App{
Name: "c3os",
Version: "0.1",
Author: "Ettore Di Giacinto",
Usage: "c3os CLI to bootstrap, upgrade, connect and manage a c3os network",
Description: `
The c3os CLI can be used to manage a c3os box and perform all day-two tasks, like:
- register a node
- connect to a node in recovery mode
- to establish a VPN connection
- set, list roles
- interact with the network API
and much more.
For all the example cases, see: https://docs.c3os.io .
`,
UsageText: ``,
Copyright: "Ettore Di Giacinto",
Commands: cmd.CommonCommand(cliCmd...),
}
err := app.Run(os.Args)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
}

46
cmd/cli/register.go Normal file
View File

@ -0,0 +1,46 @@
package main
import (
"context"
"fmt"
"io/ioutil"
nodepair "github.com/mudler/go-nodepair"
qr "github.com/mudler/go-nodepair/qrcode"
)
func register(loglevel, arg, configFile, device string, reboot, poweroff bool) error {
b, _ := ioutil.ReadFile(configFile)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
// dmesg -D to suppress tty ev
fmt.Println("Sending registration payload, please wait")
config := map[string]string{
"device": device,
"cc": string(b),
}
if reboot {
config["reboot"] = ""
}
if poweroff {
config["poweroff"] = ""
}
err := nodepair.Send(
ctx,
config,
nodepair.WithReader(qr.Reader),
nodepair.WithToken(arg),
nodepair.WithLogLevel(loglevel),
)
if err != nil {
return err
}
fmt.Println("Payload sent, installation will start on the machine briefly")
return nil
}

26
cmd/provider/main.go Normal file
View File

@ -0,0 +1,26 @@
package main
import (
"os"
"github.com/c3os-io/c3os/internal/provider"
"github.com/c3os-io/c3os/pkg/bus"
"github.com/mudler/go-pluggable"
)
func main() {
factory := pluggable.NewPluginFactory()
// Input: bus.EventInstallPayload
// Expected output: map[string]string{}
factory.Add(bus.EventInstall, provider.Install)
factory.Add(bus.EventBootstrap, provider.Bootstrap)
// Input: config
// Expected output: string
factory.Add(bus.EventChallenge, provider.Challenge)
factory.Run(pluggable.EventType(os.Args[1]), os.Args[2], os.Stdout)
}