~ubuntu-cloud-archive/ubuntu/precise/cinder/trunk

« back to all changes in this revision

Viewing changes to cinder/volume/drivers/windows.py

  • Committer: Package Import Robot
  • Author(s): Chuck Short
  • Date: 2012-11-23 08:39:28 UTC
  • mfrom: (1.1.9)
  • Revision ID: package-import@ubuntu.com-20121123083928-xvzet603cjfj9p1t
Tags: 2013.1~g1-0ubuntu1
* New upstream release.
* debian/patches/avoid_setuptools_git_dependency.patch:
  Avoid git installation. (LP: #1075948) 

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# vim: tabstop=4 shiftwidth=4 softtabstop=4
 
2
 
 
3
# Copyright 2012 Pedro Navarro Perez
 
4
# All Rights Reserved.
 
5
#
 
6
#    Licensed under the Apache License, Version 2.0 (the "License"); you may
 
7
#    not use this file except in compliance with the License. You may obtain
 
8
#    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, WITHOUT
 
14
#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 
15
#    License for the specific language governing permissions and limitations
 
16
#    under the License.
 
17
"""
 
18
Volume driver for Windows Server 2012
 
19
 
 
20
This driver requires ISCSI target role installed
 
21
 
 
22
"""
 
23
import os
 
24
import sys
 
25
 
 
26
from cinder import exception
 
27
from cinder import flags
 
28
from cinder.openstack.common import cfg
 
29
from cinder.openstack.common import log as logging
 
30
from cinder.volume import driver
 
31
 
 
32
# Check needed for unit testing on Unix
 
33
if os.name == 'nt':
 
34
    import wmi
 
35
 
 
36
 
 
37
LOG = logging.getLogger(__name__)
 
38
 
 
39
FLAGS = flags.FLAGS
 
40
 
 
41
windows_opts = [
 
42
    cfg.StrOpt('windows_iscsi_lun_path',
 
43
              default='C:\iSCSIVirtualDisks',
 
44
              help='Path to store VHD backed volumes'),
 
45
]
 
46
 
 
47
FLAGS.register_opts(windows_opts)
 
48
 
 
49
 
 
50
class WindowsDriver(driver.ISCSIDriver):
 
51
    """Executes volume driver commands on Windows Storage server."""
 
52
 
 
53
    def __init__(self):
 
54
        super(WindowsDriver, self).__init__()
 
55
 
 
56
    def do_setup(self, context):
 
57
        """Setup the Windows Volume driver.
 
58
 
 
59
        Called one time by the manager after the driver is loaded.
 
60
        Validate the flags we care about
 
61
        """
 
62
        #Set the flags
 
63
        self._conn_wmi = wmi.WMI(moniker='//./root/wmi')
 
64
        self._conn_cimv2 = wmi.WMI(moniker='//./root/cimv2')
 
65
 
 
66
    def check_for_setup_error(self):
 
67
        """Check that the driver is working and can communicate.
 
68
        """
 
69
        #Invoking the portal an checking that is listening
 
70
        wt_portal = self._conn_wmi.WT_Portal()[0]
 
71
        listen = wt_portal.Listen
 
72
        if not listen:
 
73
            raise exception.VolumeBackendAPIException()
 
74
 
 
75
    def initialize_connection(self, volume, connector):
 
76
        """Driver entry point to attach a volume to an instance.
 
77
        """
 
78
        initiator_name = connector['initiator']
 
79
        target_name = volume['provider_location']
 
80
 
 
81
        cl = self._conn_wmi.__getattr__("WT_IDMethod")
 
82
        wt_idmethod = cl.new()
 
83
        wt_idmethod.HostName = target_name
 
84
        wt_idmethod.Method = 4
 
85
        wt_idmethod.Value = initiator_name
 
86
        wt_idmethod.put()
 
87
        #Getting the portal and port information
 
88
        wt_portal = self._conn_wmi.WT_Portal()[0]
 
89
        (address, port) = (wt_portal.Address, wt_portal.Port)
 
90
        #Getting the host information
 
91
        hosts = self._conn_wmi.WT_Host(Hostname=target_name)
 
92
        host = hosts[0]
 
93
 
 
94
        properties = {}
 
95
        properties['target_discovered'] = False
 
96
        properties['target_portal'] = '%s:%s' % (address, port)
 
97
        properties['target_iqn'] = host.TargetIQN
 
98
        properties['target_lun'] = 0
 
99
        properties['volume_id'] = volume['id']
 
100
 
 
101
        auth = volume['provider_auth']
 
102
        if auth:
 
103
            (auth_method, auth_username, auth_secret) = auth.split()
 
104
 
 
105
            properties['auth_method'] = auth_method
 
106
            properties['auth_username'] = auth_username
 
107
            properties['auth_password'] = auth_secret
 
108
 
 
109
        return {
 
110
            'driver_volume_type': 'iscsi',
 
111
            'data': properties,
 
112
        }
 
113
 
 
114
    def terminate_connection(self, volume, connector, **kwargs):
 
115
        """Driver entry point to unattach a volume from an instance.
 
116
 
 
117
        Unmask the LUN on the storage system so the given intiator can no
 
118
        longer access it.
 
119
        """
 
120
        initiator_name = connector['initiator']
 
121
        #DesAssigning target to initiators
 
122
        wt_idmethod = self._conn_wmi.WT_IDMethod(HostName=volume['name'],
 
123
                                                 Method=4,
 
124
                                                 Value=initiator_name)
 
125
        wt_idmethod.Delete_()
 
126
 
 
127
    def create_volume(self, volume):
 
128
        """Driver entry point for creating a new volume."""
 
129
        vhd_path = self._get_vhd_path(volume)
 
130
        vol_name = volume['name']
 
131
        #The WMI procedure returns a Generic failure
 
132
        cl = self._conn_wmi.__getattr__("WT_Disk")
 
133
        cl.NewWTDisk(DevicePath=vhd_path,
 
134
                     Description=vol_name,
 
135
                     SizeInMB=volume['size'] * 1024)
 
136
 
 
137
    def _get_vhd_path(self, volume):
 
138
        base_vhd_folder = FLAGS.windows_iscsi_lun_path
 
139
        if not os.path.exists(base_vhd_folder):
 
140
                LOG.debug(_('Creating folder %s '), base_vhd_folder)
 
141
                os.makedirs(base_vhd_folder)
 
142
        return os.path.join(base_vhd_folder, str(volume['name']) + ".vhd")
 
143
 
 
144
    def delete_volume(self, volume):
 
145
        """Driver entry point for destroying existing volumes."""
 
146
        vol_name = volume['name']
 
147
        wt_disk = self._conn_wmi.WT_Disk(Description=vol_name)[0]
 
148
        wt_disk.Delete_()
 
149
        vhdfiles = self._conn_cimv2.query(
 
150
        "Select * from CIM_DataFile where Name = '" +
 
151
        self._get_vhd_path(volume) + "'")
 
152
        if len(vhdfiles) > 0:
 
153
            vhdfiles[0].Delete()
 
154
 
 
155
    def create_snapshot(self, snapshot):
 
156
        """Driver entry point for creating a snapshot.
 
157
        """
 
158
        #Getting WT_Snapshot class
 
159
        vol_name = snapshot['volume_name']
 
160
        snapshot_name = snapshot['name']
 
161
 
 
162
        wt_disk = self._conn_wmi.WT_Disk(Description=vol_name)[0]
 
163
        #API Calls gets Generic Failure
 
164
        cl = self._conn_wmi.__getattr__("WT_Snapshot")
 
165
        disk_id = wt_disk.WTD
 
166
        out = cl.Create(WTD=disk_id)
 
167
        #Setting description since it used as a KEY
 
168
        wt_snapshot_created = self._conn_wmi.WT_Snapshot(Id=out[0])[0]
 
169
        wt_snapshot_created.Description = snapshot_name
 
170
        wt_snapshot_created.put()
 
171
 
 
172
    def create_volume_from_snapshot(self, volume, snapshot):
 
173
        """Driver entry point for exporting snapshots as volumes."""
 
174
        snapshot_name = snapshot['name']
 
175
        wt_snapshot = self._conn_wmi.WT_Snapshot(Description=snapshot_name)[0]
 
176
        disk_id = wt_snapshot.Export()[0]
 
177
        wt_disk = self._conn_wmi.WT_Disk(WTD=disk_id)[0]
 
178
        wt_disk.Description = volume['name']
 
179
        wt_disk.put()
 
180
 
 
181
    def delete_snapshot(self, snapshot):
 
182
        """Driver entry point for deleting a snapshot."""
 
183
        snapshot_name = snapshot['name']
 
184
        wt_snapshot = self._conn_wmi.WT_Snapshot(Description=snapshot_name)[0]
 
185
        wt_snapshot.Delete_()
 
186
 
 
187
    def _do_export(self, _ctx, volume, ensure=False):
 
188
        """Do all steps to get disk exported as LUN 0 at separate target.
 
189
 
 
190
        :param volume: reference of volume to be exported
 
191
        :param ensure: if True, ignore errors caused by already existing
 
192
            resources
 
193
        :return: iscsiadm-formatted provider location string
 
194
        """
 
195
        target_name = "%s%s" % (FLAGS.iscsi_target_prefix, volume['name'])
 
196
        #ISCSI target creation
 
197
        try:
 
198
            cl = self._conn_wmi.__getattr__("WT_Host")
 
199
            cl.NewHost(HostName=target_name)
 
200
        except Exception as exc:
 
201
            excep_info = exc.com_error.excepinfo[2]
 
202
            if not ensure or excep_info.find(u'The file exists') == -1:
 
203
                raise
 
204
            else:
 
205
                LOG.info(_('Ignored target creation error "%s"'
 
206
                                             ' while ensuring export'), exc)
 
207
        #Get the disk to add
 
208
        vol_name = volume['name']
 
209
        wt_disk = self._conn_wmi.WT_Disk(Description=vol_name)[0]
 
210
        wt_host = self._conn_wmi.WT_Host(HostName=target_name)[0]
 
211
        wt_host.AddWTDisk(wt_disk.WTD)
 
212
 
 
213
        return target_name
 
214
 
 
215
    def ensure_export(self, context, volume):
 
216
        """Driver entry point to get the export info for an existing volume."""
 
217
        self._do_export(context, volume, ensure=True)
 
218
 
 
219
    def create_export(self, context, volume):
 
220
        """Driver entry point to get the export info for a new volume."""
 
221
        loc = self._do_export(context, volume, ensure=False)
 
222
        return {'provider_location': loc}
 
223
 
 
224
    def remove_export(self, context, volume):
 
225
        """Driver exntry point to remove an export for a volume.
 
226
        """
 
227
        target_name = "%s%s" % (FLAGS.iscsi_target_prefix, volume['name'])
 
228
 
 
229
        #Get ISCSI target
 
230
        wt_host = self._conn_wmi.WT_Host(HostName=target_name)[0]
 
231
        wt_host.RemoveAllWTDisks()
 
232
        wt_host.Delete_()