new book manual
This commit is contained in:
30
collections/manual/documentation/developers/internals/zos/development/net.sh
Executable file
30
collections/manual/documentation/developers/internals/zos/development/net.sh
Executable file
@@ -0,0 +1,30 @@
|
||||
#!/bin/bash
|
||||
|
||||
# This is the same as the first case at qemu/README.md in a single script
|
||||
|
||||
sudo ip link add zos0 type bridge
|
||||
sudo ip link set zos0 up
|
||||
|
||||
sudo ip addr add 192.168.123.1/24 dev zos0
|
||||
md5=$(echo $USER| md5sum )
|
||||
ULA=${md5:0:2}:${md5:2:4}:${md5:6:4}
|
||||
sudo ip addr add fd${ULA}::1/64 dev zos0
|
||||
# you might want to add fe80::1/64
|
||||
sudo ip addr add fe80::1/64 dev zos0
|
||||
|
||||
sudo iptables -t nat -I POSTROUTING -s 192.168.123.0/24 -j MASQUERADE
|
||||
sudo ip6tables -t nat -I POSTROUTING -s fd${ULA}::/64 -j MASQUERADE
|
||||
sudo iptables -t filter -I FORWARD --source 192.168.123.0/24 -j ACCEPT
|
||||
sudo iptables -t filter -I FORWARD --destination 192.168.123.0/24 -j ACCEPT
|
||||
sudo sysctl -w net.ipv4.ip_forward=1
|
||||
|
||||
sudo dnsmasq --strict-order \
|
||||
--except-interface=lo \
|
||||
--interface=zos0 \
|
||||
--bind-interfaces \
|
||||
--dhcp-range=192.168.123.20,192.168.123.50 \
|
||||
--dhcp-range=::1000,::1fff,constructor:zos0,ra-stateless,12h \
|
||||
--conf-file="" \
|
||||
--pid-file=/var/run/qemu-dnsmasq-zos0.pid \
|
||||
--dhcp-leasefile=/var/run/qemu-dnsmasq-zos0.leases \
|
||||
--dhcp-no-override
|
@@ -0,0 +1,61 @@
|
||||
# Adding a new package
|
||||
|
||||
Binary packages are added via providing [a build script](../../bins/), then an automated workflow will build/publish an flist with this binary.
|
||||
|
||||
For example, to add `rmb` binary, we need to provide a bash script with a `build_rmb` function:
|
||||
|
||||
|
||||
```bash
|
||||
RMB_VERSION="0.1.2"
|
||||
RMB_CHECKSUM="4fefd664f261523b348fc48e9f1c980b"
|
||||
RMB_LINK="https://github.com/threefoldtech/rmb-rs/releases/download/v${RMB_VERSION}/rmb"
|
||||
|
||||
download_rmb() {
|
||||
echo "download rmb"
|
||||
download_file ${RMB_LINK} ${RMB_CHECKSUM} rmb
|
||||
}
|
||||
|
||||
prepare_rmb() {
|
||||
echo "[+] prepare rmb"
|
||||
github_name "rmb-${RMB_VERSION}"
|
||||
}
|
||||
|
||||
install_rmb() {
|
||||
echo "[+] install rmb"
|
||||
|
||||
mkdir -p "${ROOTDIR}/bin"
|
||||
|
||||
cp ${DISTDIR}/rmb ${ROOTDIR}/bin/
|
||||
chmod +x ${ROOTDIR}/bin/*
|
||||
}
|
||||
|
||||
build_rmb() {
|
||||
pushd "${DISTDIR}"
|
||||
|
||||
download_rmb
|
||||
popd
|
||||
|
||||
prepare_rmb
|
||||
install_rmb
|
||||
}
|
||||
```
|
||||
|
||||
Note that, you can just download a statically build binary instead of building it.
|
||||
|
||||
|
||||
The other step is to add it to workflow to be built automatically, in [bins workflow](../../.github/workflows/bins.yaml), add your binary's job:
|
||||
|
||||
```yaml
|
||||
jobs:
|
||||
containerd:
|
||||
...
|
||||
...
|
||||
rmb:
|
||||
uses: ./.github/workflows/bin-package.yaml
|
||||
with:
|
||||
package: rmb
|
||||
secrets:
|
||||
token: ${{ secrets.HUB_JWT }}
|
||||
```
|
||||
|
||||
Once e.g. a `devnet` release is published, your package will be built then pushed to an flist repository. After that, you can start your local zos node, wait for it to finish downloading, then you should find your binary available.
|
@@ -0,0 +1,70 @@
|
||||
# Quick start
|
||||
|
||||
- [Quick start](#quick-start)
|
||||
- [Starting a local zos node](#starting-a-local-zos-node)
|
||||
- [Accessing node](#accessing-node)
|
||||
- [Development](#development)
|
||||
|
||||
## Starting a local zos node
|
||||
|
||||
* Make sure `qemu` and `dnsmasq` are installed
|
||||
* [Create a farm](../manual/manual.md#creating-a-farm)
|
||||
* [Download a zos image](https://bootstrap.grid.tf/kernel/zero-os-development-zos-v3-generic-7e587e499a.efi)
|
||||
* Make sure `zos0` bridge is allowed by qemu, you can add `allow zos0` in `/etc/qemu/bridge.conf` (create the file if it's not there)
|
||||
* Setup the network using this script [this script](./net.sh)
|
||||
|
||||
Then, inside zos repository
|
||||
|
||||
```
|
||||
make -C cmds
|
||||
cd qemu
|
||||
mv <downloaded image path> ./zos.efi
|
||||
sudo ./vm.sh -n myzos-01 -c "farmer_id=<your farm id here> printk.devmsg=on runmode=dev"
|
||||
```
|
||||
|
||||
You should see the qemu console and boot logs, wait for awhile and you can [browse farms](https://dashboard.dev.grid.tf/explorer/farms) to see your node is added/detected automatically.
|
||||
|
||||
To stop the machine you can do `Control + a` then `x`.
|
||||
|
||||
You can read more about setting up a qemu development environment and more network options [here](../../qemu/README.md).
|
||||
|
||||
## Accessing node
|
||||
|
||||
After booting up, the node should start downloading external packages, this would take some time depending on your internet connection.
|
||||
|
||||
See [how to ssh into it.](../../qemu/README.md#to-ssh-into-the-machine)
|
||||
|
||||
How to get the node IP?
|
||||
Given the network script `dhcp-range`, it usually would be one of `192.168.123.43`, `192.168.123.44` or `192.168.123.45`.
|
||||
|
||||
Or you can simply install `arp-scan` then do something like:
|
||||
|
||||
```
|
||||
✗ sudo arp-scan --interface=zos0 --localnet
|
||||
Interface: zos0, type: EN10MB, MAC: de:26:45:e6:87:95, IPv4: 192.168.123.1
|
||||
Starting arp-scan 1.9.7 with 256 hosts (https://github.com/royhills/arp-scan)
|
||||
192.168.123.44 54:43:83:1f:eb:81 (Unknown)
|
||||
```
|
||||
|
||||
Now we know for sure it's `192.168.123.44`.
|
||||
|
||||
To check logs and see if the downloading of packages is still in progress, you can simply do:
|
||||
|
||||
```
|
||||
zinit log
|
||||
```
|
||||
|
||||
## Development
|
||||
|
||||
While the overlay will enable your to boot with the binaries that's been built locally, sometimes you'll need to test the changes of certain modules without restarting the node (or intending to do so for e.g. testing a migration).
|
||||
|
||||
For example if we changed anything related to `noded`, we can do the following:
|
||||
|
||||
Inside zos repository:
|
||||
|
||||
* Build binaries locally
|
||||
* `make -C cmds`
|
||||
* Copy the binary inside the machine
|
||||
* `scp bin/zos root@192.168.123.44:/bin/noded`
|
||||
* SSH into the machine then use `zinit` to restart it:
|
||||
* `zinit stop noded && zinit start noded`
|
@@ -0,0 +1,6 @@
|
||||
Development
|
||||
===========
|
||||
|
||||
* [Quick start](./quickstart.md)
|
||||
* [Testing](./testing.md)
|
||||
* [Binary packages](./packages.md)
|
@@ -0,0 +1,157 @@
|
||||
# Testing
|
||||
|
||||
Beside unit testing, you might want to test your change in an integrated environment, the following are two options to do it.
|
||||
|
||||
- [Testing](#testing)
|
||||
- [Using grid/node client](#using-gridnode-client)
|
||||
- [Using a test app](#using-a-test-app)
|
||||
- [An example to talk to container and qsfs modules](#an-example-to-talk-to-container-and-qsfs-modules)
|
||||
- [An example of directly using zinit package](#an-example-of-directly-using-zinit-package)
|
||||
|
||||
|
||||
## Using grid/node client
|
||||
|
||||
You can simply use any grid client to deploy a workload of any type, you should specify your node's twin ID (and make sure you are on the correct network).
|
||||
|
||||
Inside the node, you can do `noded -id` and `noded -net` to get your current node ID and network. Also, [you can check your farm](https://dashboard.dev.grid.tf/explorer/farms) and get node information from there.
|
||||
|
||||
Another option is the golang [node client](../manual/manual.md#interaction).
|
||||
|
||||
While deploying on your local node, logs with `zinit log` would be helpful to see any possible errors and to debug your code.
|
||||
|
||||
## Using a test app
|
||||
|
||||
If you need to test a specific module or functionality, you can create a simple test app inside e.g. [tools directory](../../tools/).
|
||||
|
||||
Inside this simple test app, you can import any module or talk to another one using [zbus](../internals/internals.md#ipc).
|
||||
|
||||
### An example to talk to container and qsfs modules
|
||||
|
||||
|
||||
```go
|
||||
// tools/del/main.go
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/rs/zerolog/log"
|
||||
|
||||
"github.com/threefoldtech/zbus"
|
||||
"github.com/threefoldtech/zos/pkg"
|
||||
"github.com/threefoldtech/zos/pkg/stubs"
|
||||
)
|
||||
|
||||
func main() {
|
||||
zerolog.SetGlobalLevel(zerolog.DebugLevel)
|
||||
|
||||
zbus, err := zbus.NewRedisClient("unix:///var/run/redis.sock")
|
||||
if err != nil {
|
||||
log.Err(err).Msg("cannot init zbus client")
|
||||
return
|
||||
}
|
||||
|
||||
var workloadType, workloadID string
|
||||
|
||||
flag.StringVar(&workloadType, "type", "", "workload type (qsfs or container)")
|
||||
flag.StringVar(&workloadID, "id", "", "workload ID")
|
||||
|
||||
flag.Parse()
|
||||
|
||||
if workloadType == "" || workloadID == "" {
|
||||
log.Error().Msg("you need to provide both type and id")
|
||||
return
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
defer cancel()
|
||||
|
||||
if workloadType == "qsfs" {
|
||||
qsfsd := stubs.NewQSFSDStub(zbus)
|
||||
err := qsfsd.SignalDelete(ctx, workloadID)
|
||||
if err != nil {
|
||||
log.Err(err).Msg("cannot delete qsfs workload")
|
||||
}
|
||||
} else if workloadType == "container" {
|
||||
args := strings.Split(workloadID, ":")
|
||||
if len(args) != 2 {
|
||||
log.Error().Msg("container id must contain namespace, e.g. qsfs:wl129")
|
||||
}
|
||||
|
||||
containerd := stubs.NewContainerModuleStub(zbus)
|
||||
err := containerd.SignalDelete(ctx, args[0], pkg.ContainerID(args[1]))
|
||||
if err != nil {
|
||||
log.Err(err).Msg("cannot delete container workload")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
Then we can simply build, upload and execute this in our node:
|
||||
|
||||
```
|
||||
cd tools/del
|
||||
go build
|
||||
scp del root@192.168.123.44:/root/del
|
||||
```
|
||||
|
||||
Then ssh into `192.168.123.44` and simply execute your test app:
|
||||
|
||||
```
|
||||
./del
|
||||
```
|
||||
|
||||
### An example of directly using zinit package
|
||||
|
||||
```go
|
||||
// tools/zinit_test
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"regexp"
|
||||
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/rs/zerolog/log"
|
||||
|
||||
"github.com/threefoldtech/zos/pkg/zinit"
|
||||
)
|
||||
|
||||
func main() {
|
||||
zerolog.SetGlobalLevel(zerolog.DebugLevel)
|
||||
z := zinit.New("/var/run/zinit.sock")
|
||||
|
||||
regex := fmt.Sprintf(`^ip netns exec %s %s`, "ndmz", "/sbin/udhcpc")
|
||||
_, err := regexp.Compile(regex)
|
||||
if err != nil {
|
||||
log.Err(err).Msgf("cannot compile %s", regex)
|
||||
return
|
||||
}
|
||||
|
||||
// try match
|
||||
matched, err := z.Matches(zinit.WithExecRegex(regex))
|
||||
if err != nil {
|
||||
log.Err(err).Msg("cannot filter services")
|
||||
}
|
||||
|
||||
matchedStr, err := json.Marshal(matched)
|
||||
if err != nil {
|
||||
log.Err(err).Msg("cannot convert matched map to json")
|
||||
}
|
||||
|
||||
log.Debug().Str("matched", string(matchedStr)).Msg("matched services")
|
||||
|
||||
// // try destroy
|
||||
// err = z.Destroy(10*time.Second, matched...)
|
||||
// if err != nil {
|
||||
// log.Err(err).Msg("cannot destroy matched services")
|
||||
// }
|
||||
}
|
||||
```
|
Reference in New Issue
Block a user