Completed
Pull Request — master (#460)
by Manas
02:13
created

NewHardDisk.run()   C

Complexity

Conditions 8

Size

Total Lines 56

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 56
rs 6.1256
cc 8

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
# Licensed to the StackStorm, Inc ('StackStorm') under one or more
2
# contributor license agreements.  See the NOTICE file distributed with
3
# this work for additional information regarding copyright ownership.
4
# The ASF licenses this file to You under the Apache License, Version 2.0
5
# (the "License"); you may not use this file except in compliance with
6
# the License.  You may obtain a copy of the License at
7
#
8
#     http://www.apache.org/licenses/LICENSE-2.0
9
#
10
# Unless required by applicable law or agreed to in writing, software
11
# distributed under the License is distributed on an "AS IS" BASIS,
12
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
# See the License for the specific language governing permissions and
14
# limitations under the License.
15
16
import sys
17
18
from pyVmomi import vim
19
20
from vmwarelib.actions import BaseAction
21
22
23
class NewHardDisk(BaseAction):
24
25
    @staticmethod
26
    def get_backinginfo_for_existing_disk(disk_path):
27
        backing_info = vim.vm.device.VirtualDevice.FileBackingInfo()
28
        backing_info.fileName = disk_path
29
        return backing_info
30
31
    @staticmethod
32
    def get_flatfile_backinginfo(storage_format, persistence):
33
        backing_info = vim.vm.device.VirtualDisk.FlatVer2BackingInfo()
34
        if storage_format == 'eagerzeroedthick':
35
            backing_info.thinProvisioned = False
36
            backing_info.eagerlyScrub = True
37
        elif storage_format == 'thin':
38
            backing_info.thinProvisioned = True
39
        elif storage_format == 'thin2gb':
40
            backing_info.thinProvisioned = True
41
            backing_info.split = True
42
        elif storage_format == 'thick':
43
            backing_info.thinProvisioned = False
44
        elif storage_format == 'thick2gb':
45
            backing_info.thinProvisioned = False
46
            backing_info.split = True
47
        backing_info.diskMode = persistence
48
        return backing_info
49
50
    @staticmethod
51
    def get_rawfile_backinginfo(device_name, persistence):
52
        backing_info = vim.vm.device.VirtualDisk.RawDiskMappingVer1BackingInfo()
53
        backing_info.deviceName = device_name
54
        backing_info.diskMode = persistence
55
        return backing_info
56
57
    @staticmethod
58
    def get_next_unit_number(vm):
59
        unit_number = 0
60
        for dev in vm.config.hardware.device:
61
            if isinstance(dev, vim.VirtualDisk):
62
                unit_number = int(dev.unitNumber) + 1
63
                # unit_number 7 reserved for scsi controller
64
                if unit_number == 7:
65
                    unit_number += 1
66
        return unit_number
67
68
    @staticmethod
69
    def get_vm_reconfig_spec(vm, datastore, disk_type, storage_format, persistence, disk_path,
70
                             device_name, capacity_gb):
71
        if disk_path:
72
            backing_info = NewHardDisk.get_backinginfo_for_existing_disk(disk_path)
73
        elif disk_type == 'flat':
74
            backing_info = NewHardDisk.get_flatfile_backinginfo(storage_format, persistence)
75
        elif disk_type.startswith('raw'):
76
            backing_info = NewHardDisk.get_rawfile_backinginfo(device_name, persistence)
77
        else:
78
            raise Exception("Wrong disk_type and empty disk_path. Either one should be present.")
79
        backing_info.datastore = datastore
80
81
        # creating Virtual Disk Device
82
        virtual_disk = vim.vm.device.VirtualDisk()
83
        virtual_disk.backing = backing_info
84
        virtual_disk.capacityInKB = (int(capacity_gb * 1024 * 1024) if disk_path == '' else 0)
85
        virtual_disk.controllerKey = 1000
86
        virtual_disk.unitNumber = NewHardDisk.get_next_unit_number(vm)
87
88
        # creating Virtual Device Spec
89
        disk_spec = vim.vm.device.VirtualDeviceSpec()
90
        if not disk_path:
91
            disk_spec.fileOperation = "create"
92
        disk_spec.operation = vim.vm.device.VirtualDeviceSpec.Operation.add
93
        disk_spec.device = virtual_disk
94
95
        # creating reconfig spec
96
        vm_reconfig_spec = vim.vm.ConfigSpec()
97
        vm_reconfig_spec.deviceChange = [disk_spec]
98
        return vm_reconfig_spec
99
100
    @staticmethod
101
    def get_storage_placement_spec(ds_clust_obj, vm, vm_reconfig_spec):
102
        storage_placement_spec = vim.storageDrs.StoragePlacementSpec()
103
        storage_placement_spec.type = vim.storageDrs.StoragePlacementSpec.\
104
            PlacementType.reconfigure
105
        storage_placement_spec.configSpec = vm_reconfig_spec
106
        storage_placement_spec.podSelectionSpec = vim.storageDrs.PodSelectionSpec()
107
        storage_placement_spec.vm = vm
108
109
        vm_pod_cfg = vim.storageDrs.PodSelectionSpec.VmPodConfig()
110
        vm_pod_cfg.storagePod = ds_clust_obj
111
        disk_locator = vim.storageDrs.PodSelectionSpec.DiskLocator()
112
        disk_locator.diskBackingInfo = vm_reconfig_spec.deviceChange[0].device.backing
113
        vm_pod_cfg.disk = [disk_locator]
114
        storage_placement_spec.podSelectionSpec.initialVmConfig = [vm_pod_cfg]
115
116
        return storage_placement_spec
117
118
    def run(self, vms, persistence='Persistent', disk_type='flat', capacity_gb=1, datastore=None,
119
            datastore_cluster=None, device_name=None, disk_path='', storage_format='Thin'):
120
        # TODO: 'controller' parameter is missing here. The reason is because we do not support
121
        # passing real objects like PowerCli and there is no uuid to find and address the
122
        # controller in the system.
123
        persistence = persistence.lower()
124
        disk_type = disk_type.lower()
125
        storage_format = storage_format.lower()
126
127
        si = self.si
128
        si_content = si.RetrieveContent()
129
        vm_objs = [vim.VirtualMachine(moid, stub=si._stub) for moid in vms]
130
        # by checking the name property, the vms' existance is checked.
131
        [vm_obj.name for vm_obj in vm_objs]
132
        datastore_obj = None
133
        if datastore:
134
            datastore_obj = vim.Datastore(datastore, stub=si._stub)
135
            # by checking the name property, the vms' existance is checked.
136
            datastore_obj.name
137
138
        result = []
139
140
        if datastore_cluster:
141
            ds_clust_obj = vim.StoragePod(datastore_cluster, stub=si._stub)
142
            # by retrieving the name property, the existance is checked.
143
            ds_clust_obj.name
144
            srm = si_content.storageResourceManager
145
146
            for vm in vm_objs:
147
                vm_reconfig_spec = NewHardDisk.get_vm_reconfig_spec(vm, datastore_obj, disk_type,
148
                    storage_format, persistence, disk_path, device_name, capacity_gb)
149
                storage_placement_spec = NewHardDisk.get_storage_placement_spec(ds_clust_obj, vm,
150
                    vm_reconfig_spec)
151
                datastores = srm.RecommendDatastores(storageSpec=storage_placement_spec)
152
                if not datastores.recommendations:
153
                    sys.stderr.write('Skipping %s as there is no datastore recommendation' %
154
                        vm.obj._GetMoId())
155
                add_disk_task = srm.ApplyStorageDrsRecommendation_Task(
156
                    datastores.recommendations[0].key)
157
                successfully_added_disk = self._wait_for_task(add_disk_task)
158
                result.append({
159
                    "vm_moid": vm._GetMoId(),
160
                    "success": successfully_added_disk
161
                })
162
        else:
163
            for vm in vm_objs:
164
                vm_reconfig_spec = NewHardDisk.get_vm_reconfig_spec(vm, datastore_obj, disk_type,
165
                    storage_format, persistence, disk_path, device_name, capacity_gb)
166
                add_disk_task = vm.ReconfigVM_Task(spec=vm_reconfig_spec)
167
                successfully_added_disk = self._wait_for_task(add_disk_task)
168
                result.append({
169
                    "vm_moid": vm._GetMoId(),
170
                    "success": successfully_added_disk
171
                })
172
173
        return result
174