Skip to content

Commit

Permalink
kubevirt zedbox service zedkube
Browse files Browse the repository at this point in the history
Signed-off-by: Naiming Shen <naiming@Admins-MacBook-Pro-3.local>
Signed-off-by: Naiming Shen <naiming@admins-mbp-3.lan>
Signed-off-by: Naiming Shen <naiming@Admins-MacBook-Pro-3.local>
Signed-off-by: Naiming Shen <naiming@admins-mbp-3.lan>
  • Loading branch information
Naiming Shen authored and eriknordmark committed Apr 25, 2024
1 parent 1614e41 commit 74e3d47
Show file tree
Hide file tree
Showing 8 changed files with 593 additions and 1 deletion.
51 changes: 51 additions & 0 deletions pkg/kube/cluster-init.sh
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,54 @@ trigger_k3s_selfextraction() {
#Make sure all prereqs are set after /var/lib is mounted to get logging info
setup_prereqs

VMICONFIG_FILENAME="/run/zedkube/vmiVNC.run"
VNC_RUNNING=false
# run virtctl vnc
check_and_run_vnc() {
pid=$(pgrep -f "/usr/bin/virtctl vnc" )
# if remote-console config file exist, and either has not started, or need to restart
if [ -f "$VMICONFIG_FILENAME" ] && { [ "$VNC_RUNNING" = false ] || [ -z "$pid" ]; } then
vmiName=""
vmiPort=""

# Read the file and extract values
while IFS= read -r line; do
case "$line" in
*"VMINAME:"*)
vmiName="${line#*VMINAME:}" # Extract the part after "VMINAME:"
vmiName="${vmiName%%[[:space:]]*}" # Remove leading/trailing whitespace
;;
*"VNCPORT:"*)
vmiPort="${line#*VNCPORT:}" # Extract the part after "VNCPORT:"
vmiPort="${vmiPort%%[[:space:]]*}" # Remove leading/trailing whitespace
;;
esac
done < "$VMICONFIG_FILENAME"

# Check if the 'vmiName' and 'vmiPort' values are empty, if so, log an error and return
if [ -z "$vmiName" ] || [ -z "$vmiPort" ]; then
logmsg "Error: VMINAME or VNCPORT is empty in $VMICONFIG_FILENAME"
return 1
fi

logmsg "virctl vnc on vmiName: $vmiName, port $vmiPort"
nohup /usr/bin/virtctl vnc "$vmiName" -n eve-kube-app --port "$vmiPort" --proxy-only &
VNC_RUNNING=true
else
if [ ! -f "$VMICONFIG_FILENAME" ]; then
if [ "$VNC_RUNNING" = true ]; then
if [ -n "$pid" ]; then
logmsg "Killing process with PID $pid"
kill -9 "$pid"
else
logmsg "Error: Process not found"
fi
fi
VNC_RUNNING=false
fi
fi
}

date >> $INSTALL_LOG

#Forever loop every 15 secs
Expand Down Expand Up @@ -324,5 +372,8 @@ fi
cp "$CTRD_LOG" "${CTRD_LOG}.1"
truncate -s 0 "$CTRD_LOG"
fi

# Check and run vnc
check_and_run_vnc
sleep 15
done
101 changes: 101 additions & 0 deletions pkg/pillar/cmd/zedkube/applogs.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
// Copyright (c) 2024 Zededa, Inc.
// SPDX-License-Identifier: Apache-2.0

//go:build kubevirt

package zedkube

import (
"bufio"
"context"
"io"
"regexp"
"strings"
"time"

"github.com/lf-edge/eve/pkg/pillar/base"
"github.com/lf-edge/eve/pkg/pillar/kubeapi"
"github.com/lf-edge/eve/pkg/pillar/types"
"github.com/sirupsen/logrus"
corev1 "k8s.io/api/core/v1"
"k8s.io/client-go/kubernetes"
)

// collectAppLogs - collect App logs from pods which covers both containers and virt-launcher pods
func collectAppLogs(ctx *zedkubeContext) {
sub := ctx.subAppInstanceConfig
items := sub.GetAll()
if len(items) == 0 {
return
}

if ctx.config == nil {
config, err := kubeapi.GetKubeConfig()
if err != nil {
return
}
ctx.config = config
}
clientset, err := kubernetes.NewForConfig(ctx.config)
if err != nil {
log.Errorf("collectAppLogs: can't get clientset %v", err)
return
}

// "Thu Aug 17 05:39:04 UTC 2023"
timestampRegex := regexp.MustCompile(`(\w{3} \w{3} \d{2} \d{2}:\d{2}:\d{2} \w+ \d{4})`)
nowStr := time.Now().String()

var sinceSec int64
sinceSec = logcollectInterval
for _, item := range items {
aiconfig := item.(types.AppInstanceConfig)
contName := base.GetAppKubeName(aiconfig.DisplayName, aiconfig.UUIDandVersion.UUID)

opt := &corev1.PodLogOptions{}
if ctx.appLogStarted {
opt = &corev1.PodLogOptions{
SinceSeconds: &sinceSec,
}
} else {
ctx.appLogStarted = true
}
req := clientset.CoreV1().Pods(kubeapi.EVEKubeNameSpace).GetLogs(contName, opt)
podLogs, err := req.Stream(context.Background())
if err != nil {
log.Errorf("collectAppLogs: pod %s, log error %v", contName, err)
continue
}
defer podLogs.Close()

scanner := bufio.NewScanner(podLogs)
for scanner.Scan() {
logLine := scanner.Text()

matches := timestampRegex.FindStringSubmatch(logLine)
var timeStr string
if len(matches) > 0 {
timeStr = matches[0]
ts := strings.Split(logLine, timeStr)
if len(ts) > 1 {
logLine = ts[0]
}
} else {
timeStr = nowStr
}
// Process and print the log line here
aiLogger := ctx.appContainerLogger.WithFields(logrus.Fields{
"appuuid": aiconfig.UUIDandVersion.UUID.String(),
"containername": contName,
"eventtime": timeStr,
})
aiLogger.Infof("%s", logLine)
}
if scanner.Err() != nil {
if scanner.Err() != io.EOF {
log.Errorf("collectAppLogs: pod %s, scanner error %v", contName, scanner.Err())
}
break // Break out of the loop when EOF is reached or error occurs
}
}
}
99 changes: 99 additions & 0 deletions pkg/pillar/cmd/zedkube/etherpassthrough.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
// Copyright (c) 2024 Zededa, Inc.
// SPDX-License-Identifier: Apache-2.0

//go:build kubevirt

package zedkube

import (
"fmt"

"github.com/lf-edge/eve/pkg/pillar/kubeapi"
"github.com/lf-edge/eve/pkg/pillar/types"
"github.com/vishvananda/netlink"
)

// checkIoAdapterEthernet - check and create NAD for direct-attached ethernet
func checkIoAdapterEthernet(ctx *zedkubeContext, aiConfig *types.AppInstanceConfig) error {

if aiConfig.FixedResources.VirtualizationMode != types.NOHYPER {
return nil
}
ioAdapter := aiConfig.IoAdapterList
for _, io := range ioAdapter {
if io.Type == types.IoNetEth {
nadname := "host-" + io.Name
_, ok := ctx.networkInstanceStatusMap.Load(nadname)
if !ok {
bringupInterface(io.Name)
err := ioEtherCreate(ctx, &io)
if err != nil {
log.Errorf("checkIoAdapterEthernet: create io adapter error %v", err)
}
ctx.ioAdapterMap.Store(nadname, true)
log.Functionf("ccheckIoAdapterEthernet: nad created %v", nadname)
} else {
log.Functionf("checkIoAdapterEthernet: nad already exist %v", nadname)
}
}
}
return nil
}

func checkDelIoAdapterEthernet(ctx *zedkubeContext, aiConfig *types.AppInstanceConfig) {

if aiConfig.FixedResources.VirtualizationMode != types.NOHYPER {
return
}
ioAdapter := aiConfig.IoAdapterList
for _, io := range ioAdapter {
if io.Type == types.IoNetEth {
nadname := "host-" + io.Name
_, ok := ctx.ioAdapterMap.Load(nadname)
if ok {
// remove the syncMap entry
ctx.ioAdapterMap.Delete(nadname)
}
// delete the NAD in kubernetes
kubeapi.DeleteNAD(log, nadname)
log.Functionf("checkDelIoAdapterEthernet: delete existing nad %v", nadname)
}
}
}

// ioEtherCreate - create and send NAD for direct-attached ethernet
func ioEtherCreate(ctx *zedkubeContext, ioAdapt *types.IoAdapter) error {
name := ioAdapt.Name
spec := fmt.Sprintf(
`{
"cniVersion": "0.3.1",
"plugins": [
{
"type": "host-device",
"device": "%s"
}
]
}`, name)

err := kubeapi.CreateOrUpdateNAD(log, "host-"+name, spec)
if err != nil {
log.Errorf("ioEtherCreate: spec, CreateOrUpdateNAD, error %v", err)
} else {
log.Functionf("ioEtherCreate: spec, CreateOrUpdateNAD, done")
}
return err
}

func bringupInterface(intfName string) {
link, err := netlink.LinkByName(intfName)
if err != nil {
log.Errorf("bringupInterface: %v", err)
return
}

// Set the IFF_UP flag to bring up the interface
if err := netlink.LinkSetUp(link); err != nil {
log.Errorf("bringupInterface: %v", err)
return
}
}
45 changes: 45 additions & 0 deletions pkg/pillar/cmd/zedkube/nokube.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// Copyright (c) 2024 Zededa, Inc.
// SPDX-License-Identifier: Apache-2.0

//go:build !kubevirt

package zedkube

import (
"time"

"github.com/lf-edge/eve/pkg/pillar/agentbase"
"github.com/lf-edge/eve/pkg/pillar/base"
"github.com/lf-edge/eve/pkg/pillar/pubsub"
"github.com/sirupsen/logrus"
)

const (
agentName = "zedkube"
// Time limits for event loop handlers
errorTime = 3 * time.Minute
warningTime = 40 * time.Second
stillRunningInterval = 25 * time.Second
)

type zedkubeContext struct {
agentbase.AgentBase
}

// Run in this file is just stub for non-kubevirt hypervisors.
func Run(ps *pubsub.PubSub, loggerArg *logrus.Logger, logArg *base.LogObject, arguments []string) int {
logger := loggerArg
log := logArg

zedkubeCtx := zedkubeContext{}
agentbase.Init(&zedkubeCtx, logger, log, agentName,
agentbase.WithPidFile(),
agentbase.WithWatchdog(ps, warningTime, errorTime),
agentbase.WithArguments(arguments))

stillRunning := time.NewTicker(stillRunningInterval)
for range stillRunning.C {
ps.StillRunning(agentName, warningTime, errorTime)
}
return 0
}
Loading

0 comments on commit 74e3d47

Please sign in to comment.