Completed
Push — master ( f419ff...edacad )
by Manas
02:43
created

VMAddHDD   A

Complexity

Total Complexity 13

Size/Duplication

Total Lines 99
Duplicated Lines 0 %
Metric Value
wmc 13
dl 0
loc 99
rs 10

4 Methods

Rating   Name   Duplication   Size   Complexity  
A get_storage_placement_spec() 0 17 1
A get_controller_key() 0 7 3
A get_next_unit_number() 0 11 4
B run() 0 60 5
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
from pyVmomi import vim
17
import sys
18
19
from vmwarelib import inventory
20
from vmwarelib import checkinputs
21
from vmwarelib.actions import BaseAction
22
23
24
class VMAddHDD(BaseAction):
25
    def run(self, vm_id, vm_name, datastore_cluster,
26
            datastore, disk_size, provision_type):
27
        # ensure that minimal inputs are provided
28
        checkinputs.one_of_two_strings(vm_id, vm_name, "ID or Name")
29
30
        vm = inventory.get_virtualmachine(self.si_content, vm_id, vm_name)
31
        spec = vim.vm.ConfigSpec()
32
        hdd_unit_number = self.get_next_unit_number(vm)
33
        ctrl_key = self.get_controller_key(vm)
34
35
        # Prepare new Disk configuration
36
        disk_changes = []
37
        disk_spec = vim.vm.device.VirtualDeviceSpec()
38
        disk_spec.fileOperation = "create"
39
        disk_spec.operation = vim.vm.device.VirtualDeviceSpec.Operation.add
40
        disk_spec.device = vim.vm.device.VirtualDisk()
41
        disk_spec.device.backing =\
42
            vim.vm.device.VirtualDisk.FlatVer2BackingInfo()
43
        disk_spec.device.backing.diskMode = "persistent"
44
45
        if provision_type == 'thin':
46
            disk_spec.device.backing.thinProvisioned = True
47
48
        disk_spec.device.unitNumber = hdd_unit_number
49
        disk_spec.device.capacityInKB = int(disk_size) * 1024 * 1024
50
        disk_spec.device.controllerKey = ctrl_key
51
52
        # If Datastore Cluster is provided attach Disk via that
53
        if datastore_cluster:
54
            ds_clust_obj = inventory.get_datastore_cluster(
55
                self.si_content, name=datastore_cluster)
56
            disk_changes.append(disk_spec)
57
            spec.deviceChange = disk_changes
58
            srm = self.si_content.storageResourceManager
59
60
            storage_placement_spec = self.get_storage_placement_spec(
61
                ds_clust_obj, vm, spec)
62
            datastores = srm.RecommendDatastores(
63
                storageSpec=storage_placement_spec)
64
65
            if not datastores.recommendations:
66
                sys.stderr.write('Skipping as No datastore Recommendations')
67
68
            add_disk_task = srm.ApplyStorageDrsRecommendation_Task(
69
                datastores.recommendations[0].key)
70
71
        elif datastore:
72
            datastore_obj = inventory.get_datastore(self.si_content,
73
                                                    name=datastore)
74
            disk_spec.device.backing.datastore = datastore_obj
75
            disk_changes.append(disk_spec)
76
            spec.deviceChange = disk_changes
77
            add_disk_task = vm.ReconfigVM_Task(spec)
78
        else:
79
            disk_changes.append(disk_spec)
80
            spec.deviceChange = disk_changes
81
            add_disk_task = vm.ReconfigVM_Task(spec)
82
83
        successfully_added_disk = self._wait_for_task(add_disk_task)
84
        return {'state': successfully_added_disk}
85
86
    def get_storage_placement_spec(self, ds_clust_obj, vm, vm_reconfig_spec):
87
        storage_placement_spec = vim.storageDrs.StoragePlacementSpec()
88
        storage_placement_spec.type =\
89
            vim.storageDrs.StoragePlacementSpec.PlacementType.reconfigure
90
        storage_placement_spec.configSpec = vm_reconfig_spec
91
        storage_placement_spec.podSelectionSpec =\
92
            vim.storageDrs.PodSelectionSpec()
93
        storage_placement_spec.vm = vm
94
95
        vm_pod_cfg = vim.storageDrs.PodSelectionSpec.VmPodConfig()
96
        vm_pod_cfg.storagePod = ds_clust_obj
97
        disk_locator = vim.storageDrs.PodSelectionSpec.DiskLocator()
98
        disk_locator.diskBackingInfo =\
99
            vm_reconfig_spec.deviceChange[0].device.backing
100
        vm_pod_cfg.disk = [disk_locator]
101
        storage_placement_spec.podSelectionSpec.initialVmConfig = [vm_pod_cfg]
102
        return storage_placement_spec
103
104
    def get_next_unit_number(self, vm):
105
        unit_number = 0
106
        # Cycle though devices on VM and find
107
        # entries with attribute "fileName".
108
        for device in vm.config.hardware.device:
109
            if hasattr(device.backing, 'fileName'):
110
                unit_number = int(device.unitNumber) + 1
111
                # unit number 7 is reserved
112
                if unit_number == 7:
113
                    unit_number += 1
114
        return unit_number
115
116
    def get_controller_key(self, vm):
117
        # 1000 is the default used for hdd controllers
118
        key = 1000
119
        for device in vm.config.hardware.device:
120
            if isinstance(device, vim.vm.device.VirtualSCSIController):
121
                key = device.key
122
        return key
123