mirror of
https://github.com/ultravioletrs/cocos.git
synced 2026-08-07 07:14:50 +00:00
Move libvirt connect func to libvirt package
Signed-off-by: Darko Draskovic <darko.draskovic@gmail.com>
This commit is contained in:
@@ -34,19 +34,19 @@ Create `img` directory in `cmd/manager`. Create `tmp` directory in `cmd/manager`
|
||||
First, we will download *focal-server-cloudimg-amd64*. It is a `qcow2` file with Ubuntu server preinstalled, ready to use with the QEMU virtual machine.
|
||||
|
||||
```sh
|
||||
FOCAL=focal-server-cloudimg-amd64.img
|
||||
cd cmd/manager
|
||||
# Use this dir for focal-server-cloudimg-amd64.img and a test copy of firmware vars file.
|
||||
mkdir img
|
||||
# Use this dir for temporary firmware vars file and temporary disk image per virtual machine.
|
||||
mkdir tmp
|
||||
|
||||
FOCAL=focal-server-cloudimg-amd64.img
|
||||
wget -O img/$FOCAL https://cloud-images.ubuntu.com/focal/current/$FOCAL
|
||||
# focal-server-cloudimg-amd64 comes without the root password
|
||||
sudo apt-get install libguestfs-tools
|
||||
PASSWORD=coolpass
|
||||
sudo virt-customize -a img/$FOCAL --root-password password:$PASSWORD
|
||||
|
||||
# Use this dir for temporary firmware vars file and temporary disk image per virtual machine.
|
||||
mkdir tmp
|
||||
```
|
||||
|
||||
#### Resize disk image, partition and filesystem
|
||||
|
||||
We need to resize the disk image:
|
||||
@@ -59,7 +59,16 @@ To resize `ext4` partition and filesystem on the `qcow2` disk image, start the v
|
||||
|
||||
```sh
|
||||
cd cmd/manager
|
||||
cp /usr/share/OVMF/OVMF_VARS.fd img/
|
||||
|
||||
sudo find / -name OVMF_CODE.fd
|
||||
# => /usr/share/OVMF/OVMF_CODE.fd
|
||||
export MANAGER_QEMU_OVMF_CODE_FILE=/usr/share/OVMF/OVMF_CODE.fd
|
||||
|
||||
sudo find / -name OVMF_VARS.fd
|
||||
# => /usr/share/OVMF/OVMF_VARS.fd
|
||||
export MANAGER_QEMU_OVMF_VARS_FILE=/usr/share/OVMF/OVMF_VARS.fd
|
||||
|
||||
# Exported env vars are visible in subshell: start_VM.sh relies on MANAGER_QEMU_OVMF_CODE_FILE and MANAGER_QEMU_OVMF_VARS_FILE
|
||||
./start_VM.sh
|
||||
```
|
||||
|
||||
@@ -75,6 +84,12 @@ An example (for focal) of this output is:
|
||||
```
|
||||
So, the partition that holds the root file system is `/dev/sda1`.
|
||||
|
||||
Check the current size of the partition:
|
||||
```sh
|
||||
df -h
|
||||
# Output: /dev/sda1 2.0G 1.5G 520M 74% /
|
||||
```
|
||||
|
||||
Run the `parted` command to increase the `ext4` partition size. We will resize the `/dev/sda` because this is the QEMU hard disk containing the `/dev/sda1` partition and the newly added free space.
|
||||
```sh
|
||||
parted /dev/sda
|
||||
@@ -90,7 +105,6 @@ fix the GPT to use all of the space (an extra 16777216 blocks) or continue with
|
||||
the current setting?
|
||||
Fix/Ignore?
|
||||
```
|
||||
|
||||
Type `fix` here to use all of the available space.
|
||||
|
||||
An example of the output of the `print free` command should be something like this:
|
||||
@@ -130,6 +144,11 @@ The last step is to resize the filesystem of the root file system partition. To
|
||||
```sh
|
||||
resize2fs /dev/sda1
|
||||
```
|
||||
Check the new size of the partition:
|
||||
```sh
|
||||
df -h
|
||||
# Output: /dev/sda1 3.0G 1.5G 1.5G 50% /
|
||||
```
|
||||
|
||||
#### Set up the network interface
|
||||
|
||||
@@ -315,7 +334,6 @@ cp build/agent /cocos/agent
|
||||
# Copy the 'cocos-agent.service' systemd unit file to the '/etc/systemd/system/' directory.
|
||||
cp systemd/cocos-agent.service /etc/systemd/system/
|
||||
```
|
||||
|
||||
Now we are ready to set up `agent` executable as a systemd daemon service:
|
||||
|
||||
```sh
|
||||
|
||||
+3
-46
@@ -11,12 +11,9 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"net"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/digitalocean/go-libvirt"
|
||||
"github.com/mainflux/mainflux/logger"
|
||||
"github.com/mainflux/mainflux/pkg/uuid"
|
||||
"github.com/ultravioletrs/agent/agent"
|
||||
@@ -87,13 +84,6 @@ func main() {
|
||||
}()
|
||||
tracer := tp.Tracer(svcName)
|
||||
|
||||
libvirtConn := initLibvirt(logger)
|
||||
defer func() {
|
||||
if err := libvirtConn.Disconnect(); err != nil {
|
||||
logger.Error(fmt.Sprintf("Error disconnecting from libvirt: %s", err))
|
||||
}
|
||||
}()
|
||||
|
||||
agentGRPCConfig := agentgrpc.Config{}
|
||||
if err := env.Parse(&agentGRPCConfig, env.Options{Prefix: envPrefixAgentGRPC}); err != nil {
|
||||
logger.Fatal(fmt.Sprintf("failed to load %s gRPC client configuration: %s", svcName, err))
|
||||
@@ -116,7 +106,7 @@ func main() {
|
||||
}
|
||||
logger.Info(fmt.Sprintf("%s %s", exe, strings.Join(args, " ")))
|
||||
|
||||
svc := newService(libvirtConn, agentClient, logger, tracer, qemuCfg)
|
||||
svc := newService(agentClient, logger, tracer, qemuCfg)
|
||||
|
||||
var httpServerConfig = server.Config{Port: defSvcHTTPPort}
|
||||
if err := env.Parse(&httpServerConfig, env.Options{Prefix: envPrefixHTTP}); err != nil {
|
||||
@@ -156,8 +146,8 @@ func main() {
|
||||
}
|
||||
}
|
||||
|
||||
func newService(libvirtConn *libvirt.Libvirt, agent agent.AgentServiceClient, logger logger.Logger, tracer trace.Tracer, qemuCfg qemu.Config) manager.Service {
|
||||
svc := manager.New(libvirtConn, agent, qemuCfg)
|
||||
func newService(agent agent.AgentServiceClient, logger logger.Logger, tracer trace.Tracer, qemuCfg qemu.Config) manager.Service {
|
||||
svc := manager.New(agent, qemuCfg)
|
||||
|
||||
svc = api.LoggingMiddleware(svc, logger)
|
||||
counter, latency := internal.MakeMetrics(svcName, "api")
|
||||
@@ -166,36 +156,3 @@ func newService(libvirtConn *libvirt.Libvirt, agent agent.AgentServiceClient, lo
|
||||
|
||||
return svc
|
||||
}
|
||||
|
||||
func initLibvirt(logger logger.Logger) *libvirt.Libvirt {
|
||||
// This dials libvirt on the local machine, but you can substitute the first
|
||||
// two parameters with "tcp", "<ip address>:<port>" to connect to libvirt on
|
||||
// a remote machine.
|
||||
c, err := net.DialTimeout("unix", "/var/run/libvirt/libvirt-sock", 2*time.Second)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to dial libvirt: %v", err)
|
||||
}
|
||||
|
||||
l := libvirt.New(c)
|
||||
if err := l.Connect(); err != nil {
|
||||
log.Fatalf("failed to connect: %v", err)
|
||||
}
|
||||
|
||||
v, err := l.Version()
|
||||
if err != nil {
|
||||
logger.Error(fmt.Sprintf("failed to retrieve libvirt version: %v", err))
|
||||
}
|
||||
fmt.Println("Version:", v)
|
||||
|
||||
domains, err := l.Domains()
|
||||
if err != nil {
|
||||
logger.Error(fmt.Sprintf("failed to retrieve domains: %v", err))
|
||||
}
|
||||
fmt.Println("ID\tName\t\tUUID")
|
||||
fmt.Printf("--------------------------------------------------------\n")
|
||||
for _, d := range domains {
|
||||
fmt.Printf("%d\t%s\t%x\n", d.ID, d.Name, d.UUID)
|
||||
}
|
||||
|
||||
return l
|
||||
}
|
||||
|
||||
+12
-1
@@ -3,8 +3,19 @@
|
||||
echo "Mapping CTRL-C to CTRL-]"
|
||||
stty intr ^]
|
||||
|
||||
#!/bin/bash
|
||||
|
||||
# Check if the destination file exists
|
||||
if [ ! -f "img/OVMF_VARS.fd" ]; then
|
||||
# Copy $MANAGER_QEMU_OVMF_VARS_FILE to the destination
|
||||
cp "$MANAGER_QEMU_OVMF_VARS_FILE" "img/OVMF_VARS.fd"
|
||||
echo "Copied $MANAGER_QEMU_OVMF_VARS_FILE to img/OVMF_VARS.fd"
|
||||
else
|
||||
echo "img/OVMF_VARS.fd already exists. No need to copy."
|
||||
fi
|
||||
|
||||
echo "Launching VM ..."
|
||||
/usr/bin/qemu-system-x86_64 -enable-kvm -machine q35 -cpu EPYC -smp 4,maxcpus=64 -m 2048M,slots=5,maxmem=30G -drive if=pflash,format=raw,unit=0,file=/usr/share/OVMF/OVMF_CODE.fd,readonly=on -drive if=pflash,format=raw,unit=1,file=img/OVMF_VARS.fd -device virtio-scsi-pci,id=scsi,disable-legacy=on,iommu_platform=true -drive file=img/focal-server-cloudimg-amd64.img,if=none,id=disk0,format=qcow2 -device scsi-hd,drive=disk0 -netdev user,id=vmnic,hostfwd=tcp::2222-:22,hostfwd=tcp::9301-:9031,hostfwd=tcp::7020-:7002 -device virtio-net-pci,disable-legacy=on,iommu_platform=true,netdev=vmnic,romfile= -nographic -monitor pty
|
||||
/usr/bin/qemu-system-x86_64 -enable-kvm -machine q35 -cpu EPYC -smp 4,maxcpus=64 -m 2048M,slots=5,maxmem=30G -drive if=pflash,format=raw,unit=0,file=$MANAGER_QEMU_OVMF_CODE_FILE,readonly=on -drive if=pflash,format=raw,unit=1,file=img/OVMF_VARS.fd -device virtio-scsi-pci,id=scsi,disable-legacy=on,iommu_platform=true -drive file=img/focal-server-cloudimg-amd64.img,if=none,id=disk0,format=qcow2 -device scsi-hd,drive=disk0 -netdev user,id=vmnic,hostfwd=tcp::2222-:22,hostfwd=tcp::9301-:9031,hostfwd=tcp::7020-:7002 -device virtio-net-pci,disable-legacy=on,iommu_platform=true,netdev=vmnic,romfile= -nographic -monitor pty
|
||||
|
||||
# restore the mapping
|
||||
stty intr ^c
|
||||
@@ -0,0 +1,44 @@
|
||||
package libvirt
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"net"
|
||||
"time"
|
||||
|
||||
libvirt "github.com/digitalocean/go-libvirt"
|
||||
"github.com/mainflux/mainflux/logger"
|
||||
)
|
||||
|
||||
func Connect(logger logger.Logger) *libvirt.Libvirt {
|
||||
// This dials libvirt on the local machine, but you can substitute the first
|
||||
// two parameters with "tcp", "<ip address>:<port>" to connect to libvirt on
|
||||
// a remote machine.
|
||||
c, err := net.DialTimeout("unix", "/var/run/libvirt/libvirt-sock", 2*time.Second)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to dial libvirt: %v", err)
|
||||
}
|
||||
|
||||
l := libvirt.New(c)
|
||||
if err := l.Connect(); err != nil {
|
||||
log.Fatalf("failed to connect: %v", err)
|
||||
}
|
||||
|
||||
v, err := l.Version()
|
||||
if err != nil {
|
||||
logger.Error(fmt.Sprintf("failed to retrieve libvirt version: %v", err))
|
||||
}
|
||||
fmt.Println("Version:", v)
|
||||
|
||||
domains, err := l.Domains()
|
||||
if err != nil {
|
||||
logger.Error(fmt.Sprintf("failed to retrieve domains: %v", err))
|
||||
}
|
||||
fmt.Println("ID\tName\t\tUUID")
|
||||
fmt.Printf("--------------------------------------------------------\n")
|
||||
for _, d := range domains {
|
||||
fmt.Printf("%d\t%s\t%x\n", d.ID, d.Name, d.UUID)
|
||||
}
|
||||
|
||||
return l
|
||||
}
|
||||
+33
-33
@@ -13,13 +13,36 @@ import (
|
||||
|
||||
var re = regexp.MustCompile(`'([^']*)'`)
|
||||
|
||||
func entityName(msg string) (string, error) {
|
||||
match := re.FindStringSubmatch(msg)
|
||||
if len(match) < 1 {
|
||||
return "", errors.New("entity not found")
|
||||
func CreateDomain(ctx context.Context, libvirt *libvirt.Libvirt, poolXML, volXML, domXML string) (string, error) {
|
||||
wd, err := os.Getwd()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return match[1], nil
|
||||
poolStr, err := readXMLFile(poolXML, "pool.xml")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
poolStr = replaceSubstring(poolStr, "./", wd+"/")
|
||||
|
||||
volStr, err := readXMLFile(volXML, "vol.xml")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
volStr = replaceSubstring(volStr, "./", wd+"/")
|
||||
|
||||
domStr, err := readXMLFile(domXML, "dom.xml")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
domStr = replaceSubstring(domStr, "./", wd+"/")
|
||||
|
||||
dom, err := createDomain(libvirt, poolStr, volStr, domStr)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to create domain: %s", err)
|
||||
}
|
||||
|
||||
return dom.Name, nil
|
||||
}
|
||||
|
||||
func createDomain(libvirtConn *libvirt.Libvirt, poolXML string, volXML string, domXML string) (libvirt.Domain, error) {
|
||||
@@ -101,36 +124,13 @@ vol_exists:
|
||||
return dom, nil
|
||||
}
|
||||
|
||||
func CreateDomain(ctx context.Context, libvirt *libvirt.Libvirt, poolXML, volXML, domXML string) (string, error) {
|
||||
wd, err := os.Getwd()
|
||||
if err != nil {
|
||||
return "", err
|
||||
func entityName(msg string) (string, error) {
|
||||
match := re.FindStringSubmatch(msg)
|
||||
if len(match) < 1 {
|
||||
return "", errors.New("entity not found")
|
||||
}
|
||||
|
||||
poolStr, err := readXMLFile(poolXML, "pool.xml")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
poolStr = replaceSubstring(poolStr, "./", wd+"/")
|
||||
|
||||
volStr, err := readXMLFile(volXML, "vol.xml")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
volStr = replaceSubstring(volStr, "./", wd+"/")
|
||||
|
||||
domStr, err := readXMLFile(domXML, "dom.xml")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
domStr = replaceSubstring(domStr, "./", wd+"/")
|
||||
|
||||
dom, err := createDomain(libvirt, poolStr, volStr, domStr)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to create domain: %s", err)
|
||||
}
|
||||
|
||||
return dom.Name, nil
|
||||
return match[1], nil
|
||||
}
|
||||
|
||||
func readXMLFile(filename string, defaultFilename string) (string, error) {
|
||||
|
||||
+1
-4
@@ -8,7 +8,6 @@ import (
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"github.com/digitalocean/go-libvirt"
|
||||
"github.com/ultravioletrs/agent/agent"
|
||||
"github.com/ultravioletrs/manager/manager/qemu"
|
||||
)
|
||||
@@ -35,7 +34,6 @@ type Service interface {
|
||||
}
|
||||
|
||||
type managerService struct {
|
||||
libvirt *libvirt.Libvirt
|
||||
agent agent.AgentServiceClient
|
||||
qemuCfg qemu.Config
|
||||
}
|
||||
@@ -43,9 +41,8 @@ type managerService struct {
|
||||
var _ Service = (*managerService)(nil)
|
||||
|
||||
// New instantiates the manager service implementation.
|
||||
func New(libvirtConn *libvirt.Libvirt, agent agent.AgentServiceClient, qemuCfg qemu.Config) Service {
|
||||
func New(agent agent.AgentServiceClient, qemuCfg qemu.Config) Service {
|
||||
return &managerService{
|
||||
libvirt: libvirtConn,
|
||||
agent: agent,
|
||||
qemuCfg: qemuCfg,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user