1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package diskdetach
17
18 import (
19 "context"
20 "encoding/json"
21 "errors"
22
23 "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2019-07-01/compute"
24 "github.com/Azure/go-autorest/autorest/to"
25 "github.com/go-logr/logr"
26 "sigs.k8s.io/controller-runtime/pkg/client"
27
28 "github.com/chaos-mesh/chaos-mesh/api/v1alpha1"
29 "github.com/chaos-mesh/chaos-mesh/controllers/chaosimpl/azurechaos/utils"
30 impltypes "github.com/chaos-mesh/chaos-mesh/controllers/chaosimpl/types"
31 )
32
33 var _ impltypes.ChaosImpl = (*Impl)(nil)
34
35 type Impl struct {
36 client.Client
37
38 Log logr.Logger
39 }
40
41 func (impl *Impl) Apply(ctx context.Context, index int, records []*v1alpha1.Record, chaos v1alpha1.InnerObject) (v1alpha1.Phase, error) {
42 azurechaos, ok := chaos.(*v1alpha1.AzureChaos)
43 if !ok {
44 err := errors.New("chaos is not azurechaos")
45 impl.Log.Error(err, "chaos is not azureChaos", "chaos", chaos)
46 return v1alpha1.NotInjected, err
47 }
48 vmClient, err := utils.GetVMClient(ctx, impl.Client, azurechaos)
49 if err != nil {
50 impl.Log.Error(err, "fail to get the vm client")
51 return v1alpha1.NotInjected, err
52 }
53
54 var selected v1alpha1.AzureSelector
55 err = json.Unmarshal([]byte(records[index].Id), &selected)
56 if err != nil {
57 impl.Log.Error(err, "fail to unmarshal the selector")
58 return v1alpha1.NotInjected, err
59 }
60
61 vm, err := vmClient.Get(ctx, azurechaos.Spec.ResourceGroupName, azurechaos.Spec.VMName, compute.InstanceView)
62 if err != nil {
63 impl.Log.Error(err, "fail to get the specified vm")
64 return v1alpha1.NotInjected, err
65 }
66
67 diskIndex := -1
68 for index, disk := range *vm.StorageProfile.DataDisks {
69 if *disk.Lun == int32(*azurechaos.Spec.LUN) && *disk.Name == *azurechaos.Spec.DiskName {
70 diskIndex = index
71 break
72 }
73 }
74 if diskIndex == -1 {
75 impl.Log.Error(err, "fail to get the disk, please check the LUN and diskName")
76 return v1alpha1.NotInjected, err
77 }
78
79 newDiskList := append((*vm.StorageProfile.DataDisks)[:diskIndex], (*vm.StorageProfile.DataDisks)[diskIndex+1:]...)
80 vm.StorageProfile.DataDisks = &newDiskList
81
82 _, err = vmClient.CreateOrUpdate(ctx, azurechaos.Spec.ResourceGroupName, azurechaos.Spec.VMName, vm)
83 if err != nil {
84 impl.Log.Error(err, "fail to detach the disk from the vm")
85 return v1alpha1.NotInjected, err
86 }
87 return v1alpha1.Injected, nil
88 }
89 func (impl *Impl) Recover(ctx context.Context, index int, records []*v1alpha1.Record, chaos v1alpha1.InnerObject) (v1alpha1.Phase, error) {
90 azurechaos, ok := chaos.(*v1alpha1.AzureChaos)
91 if !ok {
92 err := errors.New("chaos is not azurechaos")
93 impl.Log.Error(err, "chaos is not AzureChaos", "chaos", chaos)
94 return v1alpha1.Injected, err
95 }
96
97 vmClient, err := utils.GetVMClient(ctx, impl.Client, azurechaos)
98 if err != nil {
99 impl.Log.Error(err, "fail to get the vm client")
100 return v1alpha1.Injected, err
101 }
102 disksClient, err := utils.GetDiskClient(ctx, impl.Client, azurechaos)
103 if err != nil {
104 impl.Log.Error(err, "fail to get the disk client")
105 return v1alpha1.Injected, err
106 }
107
108 disk, err := disksClient.Get(ctx, azurechaos.Spec.ResourceGroupName, *azurechaos.Spec.DiskName)
109 if err != nil {
110 impl.Log.Error(err, "fail to get the disk detail")
111 return v1alpha1.Injected, err
112 }
113 vm, err := vmClient.Get(ctx, azurechaos.Spec.ResourceGroupName, azurechaos.Spec.VMName, compute.InstanceView)
114 if err != nil {
115 impl.Log.Error(err, "fail to get the specified vm")
116 return v1alpha1.Injected, err
117 }
118
119 newDiskList := *vm.StorageProfile.DataDisks
120 newDiskList = append(newDiskList, compute.DataDisk{
121 Lun: to.Int32Ptr(int32(*azurechaos.Spec.LUN)),
122 Name: azurechaos.Spec.DiskName,
123 CreateOption: compute.DiskCreateOptionTypesAttach,
124 ManagedDisk: &compute.ManagedDiskParameters{
125 ID: disk.ID,
126 },
127 })
128 vm.StorageProfile.DataDisks = &newDiskList
129
130 var selected v1alpha1.AzureSelector
131 err = json.Unmarshal([]byte(records[index].Id), &selected)
132 if err != nil {
133 impl.Log.Error(err, "fail to unmarshal the selector")
134 return v1alpha1.NotInjected, err
135 }
136
137 _, err = vmClient.CreateOrUpdate(ctx, azurechaos.Spec.ResourceGroupName, azurechaos.Spec.VMName, vm)
138 if err != nil {
139 impl.Log.Error(err, "fail to attach the disk")
140 return v1alpha1.Injected, err
141 }
142 return v1alpha1.NotInjected, nil
143 }
144
145 func NewImpl(c client.Client, log logr.Logger) *Impl {
146 return &Impl{
147 Client: c,
148 Log: log.WithName("diskdetach"),
149 }
150 }
151