Completed
Pull Request — master (#462)
by
unknown
02:25
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
#!/usr/bin/env python
2
3
# Licensed to the StackStorm, Inc ('StackStorm') under one or more
4
# contributor license agreements.  See the NOTICE file distributed with
5
# this work for additional information regarding copyright ownership.
6
# The ASF licenses this file to You under the Apache License, Version 2.0
7
# (the "License"); you may not use this file except in compliance with
8
# the License.  You may obtain a copy of the License at
9
#
10
#     http://www.apache.org/licenses/LICENSE-2.0
11
#
12
# Unless required by applicable law or agreed to in writing, software
13
# distributed under the License is distributed on an "AS IS" BASIS,
14
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
# See the License for the specific language governing permissions and
16
# limitations under the License.
17
18
from pyVmomi import vim
19
import sys
20
21
from vmwarelib import inventory
22
from vmwarelib import checkinputs
23
from vmwarelib.actions import BaseAction
24
25
26
class VMAddHDD(BaseAction):
27
    def run(self, vm_id, vm_name, datastore_cluster,
28
            datastore, disk_size, provision_type):
29
        # ensure that minimal inputs are provided
30
        checkinputs.one_of_two_strings(vm_id, vm_name, "ID or Name")
31
32
        vm = inventory.get_virtualmachine(self.si_content, vm_id, vm_name)
33
        spec = vim.vm.ConfigSpec()
34
        hdd_unit_number = self.get_next_unit_number(vm)
35
        ctrl_key = self.get_controller_key(vm)
36
37
        # Prepare new Disk configuration
38
        disk_changes = []
39
        disk_spec = vim.vm.device.VirtualDeviceSpec()
40
        disk_spec.fileOperation = "create"
41
        disk_spec.operation = vim.vm.device.VirtualDeviceSpec.Operation.add
42
        disk_spec.device = vim.vm.device.VirtualDisk()
43
        disk_spec.device.backing =\
44
            vim.vm.device.VirtualDisk.FlatVer2BackingInfo()
45
        disk_spec.device.backing.diskMode = "persistent"
46
47
        if provision_type == 'thin':
48
            disk_spec.device.backing.thinProvisioned = True
49
50
        disk_spec.device.unitNumber = hdd_unit_number
51
        disk_spec.device.capacityInKB = int(disk_size) * 1024 * 1024
52
        disk_spec.device.controllerKey = ctrl_key
53
54
        # If Datastore Cluster is provided attach Disk via that
55
        if datastore_cluster:
56
            ds_clust_obj = inventory.get_datastore_cluster(
57
                self.si_content, name=datastore_cluster)
58
            disk_changes.append(disk_spec)
59
            spec.deviceChange = disk_changes
60
            srm = self.si_content.storageResourceManager
61
62
            storage_placement_spec = self.get_storage_placement_spec(
63
                ds_clust_obj, vm, spec)
64
            datastores = srm.RecommendDatastores(
65
                storageSpec=storage_placement_spec)
66
67
            if not datastores.recommendations:
68
                sys.stderr.write('Skipping as No datastore Recommendations')
69
70
            add_disk_task = srm.ApplyStorageDrsRecommendation_Task(
71
                datastores.recommendations[0].key)
72
73
        elif datastore:
74
            datastore_obj = inventory.get_datastore(self.si_content,
75
                                                    name=datastore)
76
            disk_spec.device.backing.datastore = datastore_obj
77
            disk_changes.append(disk_spec)
78
            spec.deviceChange = disk_changes
79
            add_disk_task = vm.ReconfigVM_Task(spec)
80
        else:
81
            disk_changes.append(disk_spec)
82
            spec.deviceChange = disk_changes
83
            add_disk_task = vm.ReconfigVM_Task(spec)
84
85
        successfully_added_disk = self._wait_for_task(add_disk_task)
86
        return {'state': successfully_added_disk}
87
88
    def get_storage_placement_spec(self, ds_clust_obj, vm, vm_reconfig_spec):
89
        storage_placement_spec = vim.storageDrs.StoragePlacementSpec()
90
        storage_placement_spec.type =\
91
            vim.storageDrs.StoragePlacementSpec.PlacementType.reconfigure
92
        storage_placement_spec.configSpec = vm_reconfig_spec
93
        storage_placement_spec.podSelectionSpec =\
94
            vim.storageDrs.PodSelectionSpec()
95
        storage_placement_spec.vm = vm
96
97
        vm_pod_cfg = vim.storageDrs.PodSelectionSpec.VmPodConfig()
98
        vm_pod_cfg.storagePod = ds_clust_obj
99
        disk_locator = vim.storageDrs.PodSelectionSpec.DiskLocator()
100
        disk_locator.diskBackingInfo =\
101
            vm_reconfig_spec.deviceChange[0].device.backing
102
        vm_pod_cfg.disk = [disk_locator]
103
        storage_placement_spec.podSelectionSpec.initialVmConfig = [vm_pod_cfg]
104
        return storage_placement_spec
105
106
    def get_next_unit_number(self, vm):
107
        unit_number = 0
108
        # Cycle though devices on VM and find
109
        # entries with attribute "fileName".
110
        for device in vm.config.hardware.device:
111
            if hasattr(device.backing, 'fileName'):
112
                unit_number = int(device.unitNumber) + 1
113
                # unit number 7 is reserved
114
                if unit_number == 7:
115
                    unit_number += 1
116
        return unit_number
117
118
    def get_controller_key(self, vm):
119
        # 1000 is the default used for hdd controllers
120
        key = 1000
121
        for device in vm.config.hardware.device:
122
            if isinstance(device, vim.vm.device.VirtualSCSIController):
123
                key = device.key
124
        return key
125