Skip to content

Commit 049ee12

Browse files
authored
Merge pull request #1 from solusio/task-oneumyvakin-windows-disk-driver-SIO-5985
Add set SATA disk driver for Windows virtual servers.
2 parents a1d2dff + c6f7295 commit 049ee12

File tree

6 files changed

+76
-44
lines changed

6 files changed

+76
-44
lines changed

README.md

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@ Using this tool you can import virtual servers from VMWare ESXi host to a comput
1010
3. Import of a virtual machine with a directory with the space character (" ") will fail.
1111
4. Importing of a virtual machine with a large disk may fail because of unstable network connection.
1212
5. If OS of a virtual server is older than OS of a SolusVM 2 compute resource then import will fail with `libguestfs error: file_architecture: unknown architecture: /usr/lib/modules/6.8.0-31-generic` or `no installed kernel packages were found`.
13-
6. If Windows virtual machine not stopped properly the following error will occur: `virt-v2v: error: filesystem was mounted read-only, even though we asked for it to be mounted read-write. This usually means that the filesystem was not cleanly unmounted. Possible causes include trying to convert a guest which is running, or using Windows Hibernation or Fast Restart`.
13+
6. If Windows virtual machine was not stopped gracefully the following error will occur: `virt-v2v: error: filesystem was mounted read-only, even though we asked for it to be mounted read-write. This usually means that the filesystem was not cleanly unmounted. Possible causes include trying to convert a guest which is running, or using Windows Hibernation or Fast Restart`.
14+
7. After the import, Windows virtual server will be using `sata` disk driver which is not optimal, but it is only to allow the first boot. On the first boot, VirtIO drivers will be automatically installed inside the guest OS. Then you have to shutdown the virtual server and change disk driver to `scsi`.
15+
8. If Windows virtual server can't boot with the "Inaccessible boot device" error, try to change "Disk Driver" setting to `sata` or `virtio`. Install VirtIO drivers inside Windows using VirtIO ISO for Windows, then stop virtual server and change "Disk Driver" setting back to `scsi`. It's highly recommended to run virtual server with `scsi` disk driver.
1416

1517
## Prerequisites
1618

@@ -79,7 +81,10 @@ Example of the file:
7981
"centos7-64": 2,
8082
"ubuntu-64": 17,
8183
"almalinux-64": 18,
82-
"debian12-64": 50
84+
"debian12-64": 50,
85+
"windows9srv-64": 25,
86+
"windows2019srv-64": 25,
87+
"windows2019srvNext-64": 55
8388
},
8489
"user_id": 1,
8590
"project_id": 1,

disks.go

Lines changed: 47 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,19 @@
11
package main
22

33
import (
4+
"context"
45
"encoding/xml"
56
"errors"
67
"fmt"
78
libvirtxml "github.com/libvirt/libvirt-go-xml"
89
"github.com/solusio/import-vmware/command"
910
"github.com/solusio/import-vmware/common"
11+
"github.com/solusio/solus-go-sdk"
12+
"net/url"
1013
"os"
1114
"path/filepath"
15+
"strings"
16+
"time"
1217
)
1318

1419
const (
@@ -53,34 +58,54 @@ func importDisks(sourceIP string, plan ImportPlan) error {
5358
return fmt.Errorf("failed to move %q to %q: %s", disks[0].path, vs.PrimaryDiskDestinationPath, err)
5459
}
5560

56-
if len(vs.AdditionalDisks) == 0 {
57-
continue
58-
}
61+
if strings.Contains(vs.GuestOS, "windows") {
62+
baseURL, err := url.Parse(plan.Settings.APIURL)
63+
if err != nil {
64+
return fmt.Errorf("parse api url %q: %w", plan.Settings.APIURL, err)
65+
}
5966

60-
if len(disks) == 1 {
61-
return fmt.Errorf("virtual server %q additional disks not found in %q, expected additional disks count is %d",
62-
vs.OriginName,
63-
importedXMLPath,
64-
len(vs.AdditionalDisks))
67+
client, err := solus.NewClient(baseURL, solus.APITokenAuthenticator{Token: plan.Settings.APIToken})
68+
if err != nil {
69+
return fmt.Errorf("create client: %w", err)
70+
}
71+
72+
ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
73+
data := solus.VirtualServerUpdateSettingsRequest{
74+
DiskDriver: "sata",
75+
}
76+
if _, err := client.VirtualServers.UpdateSettings(ctx, vs.VirtualServerID, data); err != nil {
77+
cancel()
78+
return fmt.Errorf("update virtual server %d disk driver to sata: %w", vs.VirtualServerID, err)
79+
}
80+
cancel()
6581
}
6682

67-
additionalDisks := disks[1:]
83+
if len(vs.AdditionalDisks) > 0 {
84+
if len(disks) == 1 {
85+
return fmt.Errorf("virtual server %q additional disks not found in %q, expected additional disks count is %d",
86+
vs.OriginName,
87+
importedXMLPath,
88+
len(vs.AdditionalDisks))
89+
}
6890

69-
if len(additionalDisks) != len(vs.AdditionalDisks) {
70-
return fmt.Errorf("virtual server %q number of additional disks in %q is %d, but %d expected",
71-
vs.OriginName,
72-
importedXMLPath,
73-
len(additionalDisks),
74-
len(vs.AdditionalDisks))
75-
}
91+
additionalDisks := disks[1:]
7692

77-
for i, disk := range additionalDisks {
78-
if err := os.Rename(disk.path, vs.AdditionalDisks[i].DestinationPath); err != nil {
79-
return fmt.Errorf("failed to move virtual server %q disk %q to %q: %s",
93+
if len(additionalDisks) != len(vs.AdditionalDisks) {
94+
return fmt.Errorf("virtual server %q number of additional disks in %q is %d, but %d expected",
8095
vs.OriginName,
81-
disk.path,
82-
vs.AdditionalDisks[i].DestinationPath,
83-
err)
96+
importedXMLPath,
97+
len(additionalDisks),
98+
len(vs.AdditionalDisks))
99+
}
100+
101+
for i, disk := range additionalDisks {
102+
if err := os.Rename(disk.path, vs.AdditionalDisks[i].DestinationPath); err != nil {
103+
return fmt.Errorf("failed to move virtual server %q disk %q to %q: %s",
104+
vs.OriginName,
105+
disk.path,
106+
vs.AdditionalDisks[i].DestinationPath,
107+
err)
108+
}
84109
}
85110
}
86111
}

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ require (
1313
github.com/digitalocean/go-libvirt v0.0.0-20240308204700-df736b2945cf // indirect
1414
github.com/kr/fs v0.1.0 // indirect
1515
github.com/libvirt/libvirt-go-xml v7.4.0+incompatible // indirect
16-
github.com/solusio/solus-go-sdk v0.0.0-20240524062700-52e7ee9a6035 // indirect
16+
github.com/solusio/solus-go-sdk v0.0.0-20240531111439-a9f6da81f560 // indirect
1717
golang.org/x/sys v0.19.0 // indirect
1818
gopkg.in/guregu/null.v4 v4.0.0 // indirect
1919
)

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ github.com/solusio/solus-go-sdk v0.0.0-20240516085532-daf5d30e61a0 h1:+sR7X4l/sx
2121
github.com/solusio/solus-go-sdk v0.0.0-20240516085532-daf5d30e61a0/go.mod h1:pIvIG/rIvED2rM9fhk41wAog/zE4QUKWBL7ABH9ad4Y=
2222
github.com/solusio/solus-go-sdk v0.0.0-20240524062700-52e7ee9a6035 h1:n7G6LCap8JY0jG04mKjlDkz7aTsQ1Mon6rcKX8Gbab8=
2323
github.com/solusio/solus-go-sdk v0.0.0-20240524062700-52e7ee9a6035/go.mod h1:pIvIG/rIvED2rM9fhk41wAog/zE4QUKWBL7ABH9ad4Y=
24+
github.com/solusio/solus-go-sdk v0.0.0-20240531111439-a9f6da81f560 h1:P3ZYo0LzievAK4Nz/TX+KK2lzI4GfGKR6goZSS5KjQs=
25+
github.com/solusio/solus-go-sdk v0.0.0-20240531111439-a9f6da81f560/go.mod h1:pIvIG/rIvED2rM9fhk41wAog/zE4QUKWBL7ABH9ad4Y=
2426
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
2527
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
2628
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=

plan.go

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -14,24 +14,24 @@ type ImportPlan struct {
1414
}
1515

1616
type VirtualServer struct {
17-
VMXFilePath string `json:"vmx_file_path,omitempty"`
18-
VirtualServerID int `json:"virtual_server_id,omitempty"`
19-
VirtualServerUUID string `json:"virtual_server_uuid,omitempty"`
20-
OriginDir string `json:"origin_dir,omitempty"`
21-
OriginName string `json:"origin_name,omitempty"`
22-
Hostname string `json:"hostname,omitempty"`
23-
ComputeResourceID int `json:"compute_resource_id,omitempty"`
24-
GuestOS string `json:"guest_os,omitempty"`
25-
CustomPlan solus.Plan `json:"custom_plan"`
26-
PrimaryDiskSourcePath string `json:"primary_disk_source_path,omitempty"`
27-
PrimaryDiskDestinationPath string `json:"primary_disk_destination_path,omitempty"`
28-
AdditionalDisks []Disk `json:"additional_disks,omitempty"`
29-
PrimaryIP *string `json:"primary_ip,omitempty"`
30-
AdditionalIPv4 *int `json:"additional_ipv4,omitempty"`
31-
Password string `json:"password,omitempty"`
32-
SSHKeys []int `json:"ssh_keys,omitempty"`
33-
MacAddress *string `json:"mac_address,omitempty"`
34-
Firmware *string `json:"firmware,omitempty"`
17+
VMXFilePath string `json:"vmx_file_path,omitempty"`
18+
VirtualServerID int `json:"virtual_server_id,omitempty"`
19+
VirtualServerUUID string `json:"virtual_server_uuid,omitempty"`
20+
OriginDir string `json:"origin_dir,omitempty"`
21+
OriginName string `json:"origin_name,omitempty"`
22+
Hostname string `json:"hostname,omitempty"`
23+
ComputeResourceID int `json:"compute_resource_id,omitempty"`
24+
GuestOS string `json:"guest_os,omitempty"`
25+
CustomPlan solus.Plan `json:"custom_plan"`
26+
PrimaryDiskSourcePath string `json:"primary_disk_source_path,omitempty"`
27+
PrimaryDiskDestinationPath string `json:"primary_disk_destination_path,omitempty"`
28+
AdditionalDisks []Disk `json:"additional_disks,omitempty"`
29+
PrimaryIP *string `json:"primary_ip,omitempty"`
30+
AdditionalIPv4 *int `json:"additional_ipv4,omitempty"`
31+
Password string `json:"password,omitempty"`
32+
SSHKeys []int `json:"ssh_keys,omitempty"`
33+
MacAddress *string `json:"mac_address,omitempty"`
34+
Firmware *solus.Firmware `json:"firmware,omitempty"`
3535
}
3636

3737
type Disk struct {

vmx.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ type VMXFile struct {
2222
// guestOS = "windows2022srvNext-64"
2323
GuestOS string `vmx:"guestOS"`
2424
// firmware = "efi"
25-
Firmware string `vmx:"firmware"`
25+
Firmware solus.Firmware `vmx:"firmware"`
2626
IDEDevices []vmx.IDEDevice `vmx:"ide,omitempty"`
2727
SCSIDevices []vmx.SCSIDevice `vmx:"scsi,omitempty"`
2828
SATADevices []vmx.SATADevice `vmx:"sata,omitempty"`

0 commit comments

Comments
 (0)