/
util.go
230 lines (196 loc) · 6.15 KB
/
util.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
package virtualmachine
import (
"errors"
"fmt"
"io"
"log"
"os"
"github.com/digitalocean/go-libvirt"
"github.com/guyst16/mykube/pkg/libvirtconn"
"github.com/pkg/sftp"
"golang.org/x/crypto/ssh"
)
type Virtualmachine struct {
os_name string
os_path string
cloudconfig_path string
vcpu_amount int
memory_amount int
name string
}
var STATES = map[libvirt.ConnectListAllDomainsFlags]string{libvirt.ConnectListDomainsRunning: "Running", libvirt.ConnectListDomainsPaused: "Paused", libvirt.ConnectListDomainsShutoff: "Shutoff"}
// Create virtual machine object
func NewVirtualmachine(os_name string, os_path string, cloudconfig_path string, vcpu_amount int, memory_amount int, name string) *Virtualmachine {
v := Virtualmachine{os_name: os_name, os_path: os_path, cloudconfig_path: cloudconfig_path, vcpu_amount: vcpu_amount, memory_amount: memory_amount, name: name}
return &v
}
func GetVirtualMachine(vmName string) (dom *libvirt.Domain) {
libvirtconn := libvirtconn.ConnectLibvirtLocal()
vm, _ := libvirtconn.DomainLookupByName(vmName)
return &vm
}
func ListAllVirtualmachines() {
println("ID\tNAME\t\tUUID\t\t\t\t\tSTATE")
println("-----------------------------------------------------------------------")
libvirtconn := libvirtconn.ConnectLibvirtLocal()
for state := range STATES {
flags := state
domains, _, _ := libvirtconn.ConnectListAllDomains(1, flags)
for _, vm := range domains {
fmt.Printf("%d\t%s\t%x\t%s\n", vm.ID, vm.Name, vm.UUID, STATES[state])
}
}
}
func (vm Virtualmachine) CreateVirtualmachine() {
vmXML := ModifyXML("assets/vmTemplate.xml", vm.name, vm.os_path, vm.cloudconfig_path)
libvirtconn := libvirtconn.ConnectLibvirtLocal()
vmXMLString := string(vmXML)
_, err := libvirtconn.DomainDefineXML(vmXMLString)
if err != nil {
log.Fatal(err)
}
}
// Start defined vm
func StartVirtualMachine(vmName string) {
libvirtconn := libvirtconn.ConnectLibvirtLocal()
domain := GetVirtualMachine(vmName)
if domain == nil {
log.Fatal("Virtual machine not defined")
}
err := libvirtconn.DomainCreate(*domain)
if err != nil {
log.Fatal(err)
}
}
// Delete defined vm
func DeleteVirtualMachine(vmName string) (err error) {
libvirtconn := libvirtconn.ConnectLibvirtLocal()
domain := GetVirtualMachine(vmName)
if domain == nil {
return errors.New("vm undefined")
}
err = libvirtconn.DomainUndefine(*domain)
if err != nil {
return err
}
err = libvirtconn.DomainDestroy(*domain)
if err != nil {
return err
}
return nil
}
// Get virtual machine public IP
func GetVirtualMachineIP(vmName string) (vmIPAddress string, err error) {
libvirtconn := libvirtconn.ConnectLibvirtLocal()
domain := GetVirtualMachine(vmName)
domainIPAddress := ""
if domain == nil {
return domainIPAddress, errors.New("virtual machine not defined")
}
// Get list of the domain interfaces addresses
intrefacesList, err := libvirtconn.DomainInterfaceAddresses(*domain, 0, 0)
if err != nil {
return domainIPAddress, err
}
if len(intrefacesList) == 0 {
return domainIPAddress, errors.New("domain " + vmName + " doesn't have an IP address")
}
return intrefacesList[0].Addrs[0].Addr, nil
}
// Copy file from vm to host
func CopyFileFromVirtualMachineToHost(sshClient *ssh.Client, remoteFilePath string, localFilePath string) (err error) {
defer sshClient.Close()
// Open an SFTP session on the remote machine
sftpClient, err := sftp.NewClient(sshClient)
if err != nil {
fmt.Println("Failed to create SFTP client:", err)
return
}
defer sftpClient.Close()
// Check if the file exists
_, err = sftpClient.Stat("/etc/kubernetes/admin.conf")
if err != nil {
return err
}
// Copy file to local
// File exists, open the remote file
remoteFile, err := sftpClient.Open(remoteFilePath)
if err != nil {
fmt.Println("Error opening remote file:", err)
return
}
defer remoteFile.Close()
// Create a local file to copy the contents to
localFile, err := os.Create(localFilePath)
if err != nil {
fmt.Println("Error creating local file:", err)
return
}
defer localFile.Close()
// Copy the contents of the remote file to the local file
_, err = io.Copy(localFile, remoteFile)
if err != nil {
fmt.Println("Error copying file:", err)
return
}
return nil
}
// Get ssh client for a virtaul machine
func GetVirtualMachineSSHConnection(vmName string, vmPubKeyPath string) (shhClient *ssh.Client, err error) {
privateKey, err := LoadPrivateKeyFromFile(vmPubKeyPath)
if err != nil {
return nil, err
}
config := &ssh.ClientConfig{
User: "sumit",
Auth: []ssh.AuthMethod{
ssh.PublicKeys(privateKey),
},
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
}
vmIP, err := GetVirtualMachineIP(vmName)
if err != nil {
return nil, err
}
sshClient, err := ssh.Dial("tcp", fmt.Sprintf("%s:%d", vmIP, 22), config)
if err != nil {
return nil, err
}
return sshClient, nil
}
func LoadPrivateKeyFromFile(filePath string) (ssh.Signer, error) {
// Read the contents of the file
fileContent, err := os.ReadFile(filePath)
if err != nil {
return nil, err
}
key, err := ssh.ParsePrivateKey(fileContent)
if err != nil {
return nil, err
}
return key, nil
}
// Print cluster connection details
func GetConnectionDetails(vmName string, mykubeAssetsDir string) (err error) {
// Validate virtual machine has an IP
vmIP, err := GetVirtualMachineIP(vmName)
if err != nil {
return err
}
// Get home directory
userHomeDir, err := os.UserHomeDir()
if err != nil {
log.Fatal(err)
}
ASSETS_MYKUBE_DIR := userHomeDir + "/" + mykubeAssetsDir
ASSETS_MYKUBE_VM_DIR := ASSETS_MYKUBE_DIR + "/" + vmName
fmt.Println("Virtual machine is up and running")
fmt.Println("To connect the cluster please run:\n$ export KUBECONFIG=" + ASSETS_MYKUBE_VM_DIR + "/kube.conf")
fmt.Println("Or use the console:\nhttps://" + vmIP + ":31000")
fmt.Println("\nLogin to console by creating new cluster-admin token:")
fmt.Println("$ kubectl create serviceaccount mykube-admin --namespace default")
fmt.Println("$ kubectl create clusterrolebinding --clusterrole=cluster-admin --serviceaccount default:mykube-admin mykube-admin-rb")
fmt.Println("$ kubectl create token mykube-admin --namespace default")
fmt.Println("\nCopy token and paste in console")
return nil
}