~ubuntu-branches/ubuntu/raring/nova/raring-proposed

« back to all changes in this revision

Viewing changes to .pc/rbd-security.patch/nova/virt/libvirt/volume.py

  • Committer: Package Import Robot
  • Author(s): Chuck Short, Adam Gandelman, Chuck Short
  • Date: 2012-11-23 09:04:58 UTC
  • mfrom: (1.1.66)
  • Revision ID: package-import@ubuntu.com-20121123090458-91565o7aev1i1h71
Tags: 2013.1~g1-0ubuntu1
[ Adam Gandelman ]
* debian/control: Ensure novaclient is upgraded with nova,
  require python-keystoneclient >= 1:2.9.0. (LP: #1073289)
* debian/patches/{ubuntu/*, rbd-security.patch}: Dropped, applied
  upstream.
* debian/control: Add python-testtools to Build-Depends.

[ Chuck Short ]
* New upstream version.
* Refreshed debian/patches/avoid_setuptools_git_dependency.patch.
* debian/rules: FTBFS if missing binaries.
* debian/nova-scheudler.install: Add missing rabbit-queues and
  nova-rpc-zmq-receiver.
* Remove nova-volume since it doesnt exist anymore, transition to cinder-*.
* debian/rules: install apport hook in the right place.
* debian/patches/ubuntu-show-tests.patch: Display test failures.
* debian/control: Add depends on genisoimage
* debian/control: Suggest guestmount.
* debian/control: Suggest websockify. (LP: #1076442)
* debian/nova.conf: Disable nova-volume service.
* debian/control: Depend on xen-system-* rather than the hypervisor.
* debian/control, debian/mans/nova-conductor.8, debian/nova-conductor.init,
  debian/nova-conductor.install, debian/nova-conductor.logrotate
  debian/nova-conductor.manpages, debian/nova-conductor.postrm
  debian/nova-conductor.upstart.in: Add nova-conductor service.
* debian/control: Add python-fixtures as a build deps.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# vim: tabstop=4 shiftwidth=4 softtabstop=4
2
 
 
3
 
# Copyright 2011 OpenStack LLC.
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 drivers for libvirt."""
19
 
 
20
 
import os
21
 
import time
22
 
 
23
 
from nova import exception
24
 
from nova import flags
25
 
from nova.openstack.common import log as logging
26
 
from nova import utils
27
 
from nova.virt.libvirt import config
28
 
from nova.virt.libvirt import utils as virtutils
29
 
 
30
 
LOG = logging.getLogger(__name__)
31
 
FLAGS = flags.FLAGS
32
 
flags.DECLARE('num_iscsi_scan_tries', 'nova.volume.driver')
33
 
 
34
 
 
35
 
class LibvirtVolumeDriver(object):
36
 
    """Base class for volume drivers."""
37
 
    def __init__(self, connection):
38
 
        self.connection = connection
39
 
 
40
 
    def connect_volume(self, connection_info, mount_device):
41
 
        """Connect the volume. Returns xml for libvirt."""
42
 
        conf = config.LibvirtConfigGuestDisk()
43
 
        conf.source_type = "block"
44
 
        conf.driver_name = virtutils.pick_disk_driver_name(is_block_dev=True)
45
 
        conf.driver_format = "raw"
46
 
        conf.driver_cache = "none"
47
 
        conf.source_path = connection_info['data']['device_path']
48
 
        conf.target_dev = mount_device
49
 
        conf.target_bus = "virtio"
50
 
        conf.serial = connection_info.get('serial')
51
 
        return conf
52
 
 
53
 
    def disconnect_volume(self, connection_info, mount_device):
54
 
        """Disconnect the volume"""
55
 
        pass
56
 
 
57
 
 
58
 
class LibvirtFakeVolumeDriver(LibvirtVolumeDriver):
59
 
    """Driver to attach Network volumes to libvirt."""
60
 
 
61
 
    def connect_volume(self, connection_info, mount_device):
62
 
        conf = config.LibvirtConfigGuestDisk()
63
 
        conf.source_type = "network"
64
 
        conf.driver_name = "qemu"
65
 
        conf.driver_format = "raw"
66
 
        conf.driver_cache = "none"
67
 
        conf.source_protocol = "fake"
68
 
        conf.source_host = "fake"
69
 
        conf.target_dev = mount_device
70
 
        conf.target_bus = "virtio"
71
 
        conf.serial = connection_info.get('serial')
72
 
        return conf
73
 
 
74
 
 
75
 
class LibvirtNetVolumeDriver(LibvirtVolumeDriver):
76
 
    """Driver to attach Network volumes to libvirt."""
77
 
 
78
 
    def connect_volume(self, connection_info, mount_device):
79
 
        conf = config.LibvirtConfigGuestDisk()
80
 
        conf.source_type = "network"
81
 
        conf.driver_name = virtutils.pick_disk_driver_name(is_block_dev=False)
82
 
        conf.driver_format = "raw"
83
 
        conf.driver_cache = "none"
84
 
        conf.source_protocol = connection_info['driver_volume_type']
85
 
        conf.source_host = connection_info['data']['name']
86
 
        conf.target_dev = mount_device
87
 
        conf.target_bus = "virtio"
88
 
        conf.serial = connection_info.get('serial')
89
 
        netdisk_properties = connection_info['data']
90
 
        if netdisk_properties.get('auth_enabled'):
91
 
            conf.auth_username = netdisk_properties['auth_username']
92
 
            conf.auth_secret_type = netdisk_properties['secret_type']
93
 
            conf.auth_secret_uuid = netdisk_properties['secret_uuid']
94
 
        return conf
95
 
 
96
 
 
97
 
class LibvirtISCSIVolumeDriver(LibvirtVolumeDriver):
98
 
    """Driver to attach Network volumes to libvirt."""
99
 
 
100
 
    def _run_iscsiadm(self, iscsi_properties, iscsi_command, **kwargs):
101
 
        check_exit_code = kwargs.pop('check_exit_code', 0)
102
 
        (out, err) = utils.execute('iscsiadm', '-m', 'node', '-T',
103
 
                                   iscsi_properties['target_iqn'],
104
 
                                   '-p', iscsi_properties['target_portal'],
105
 
                                   *iscsi_command, run_as_root=True,
106
 
                                   check_exit_code=check_exit_code)
107
 
        LOG.debug("iscsiadm %s: stdout=%s stderr=%s" %
108
 
                  (iscsi_command, out, err))
109
 
        return (out, err)
110
 
 
111
 
    def _iscsiadm_update(self, iscsi_properties, property_key, property_value,
112
 
                         **kwargs):
113
 
        iscsi_command = ('--op', 'update', '-n', property_key,
114
 
                         '-v', property_value)
115
 
        return self._run_iscsiadm(iscsi_properties, iscsi_command, **kwargs)
116
 
 
117
 
    @utils.synchronized('connect_volume')
118
 
    def connect_volume(self, connection_info, mount_device):
119
 
        """Attach the volume to instance_name"""
120
 
        iscsi_properties = connection_info['data']
121
 
        # NOTE(vish): If we are on the same host as nova volume, the
122
 
        #             discovery makes the target so we don't need to
123
 
        #             run --op new. Therefore, we check to see if the
124
 
        #             target exists, and if we get 255 (Not Found), then
125
 
        #             we run --op new. This will also happen if another
126
 
        #             volume is using the same target.
127
 
        try:
128
 
            self._run_iscsiadm(iscsi_properties, ())
129
 
        except exception.ProcessExecutionError as exc:
130
 
            # iscsiadm returns 21 for "No records found" after version 2.0-871
131
 
            if exc.exit_code in [21, 255]:
132
 
                self._run_iscsiadm(iscsi_properties, ('--op', 'new'))
133
 
            else:
134
 
                raise
135
 
 
136
 
        if iscsi_properties.get('auth_method'):
137
 
            self._iscsiadm_update(iscsi_properties,
138
 
                                  "node.session.auth.authmethod",
139
 
                                  iscsi_properties['auth_method'])
140
 
            self._iscsiadm_update(iscsi_properties,
141
 
                                  "node.session.auth.username",
142
 
                                  iscsi_properties['auth_username'])
143
 
            self._iscsiadm_update(iscsi_properties,
144
 
                                  "node.session.auth.password",
145
 
                                  iscsi_properties['auth_password'])
146
 
 
147
 
        # NOTE(vish): If we have another lun on the same target, we may
148
 
        #             have a duplicate login
149
 
        self._run_iscsiadm(iscsi_properties, ("--login",),
150
 
                           check_exit_code=[0, 255])
151
 
 
152
 
        self._iscsiadm_update(iscsi_properties, "node.startup", "automatic")
153
 
 
154
 
        host_device = ("/dev/disk/by-path/ip-%s-iscsi-%s-lun-%s" %
155
 
                        (iscsi_properties['target_portal'],
156
 
                         iscsi_properties['target_iqn'],
157
 
                         iscsi_properties.get('target_lun', 0)))
158
 
 
159
 
        # The /dev/disk/by-path/... node is not always present immediately
160
 
        # TODO(justinsb): This retry-with-delay is a pattern, move to utils?
161
 
        tries = 0
162
 
        while not os.path.exists(host_device):
163
 
            if tries >= FLAGS.num_iscsi_scan_tries:
164
 
                raise exception.NovaException(_("iSCSI device not found at %s")
165
 
                                              % (host_device))
166
 
 
167
 
            LOG.warn(_("ISCSI volume not yet found at: %(mount_device)s. "
168
 
                       "Will rescan & retry.  Try number: %(tries)s") %
169
 
                     locals())
170
 
 
171
 
            # The rescan isn't documented as being necessary(?), but it helps
172
 
            self._run_iscsiadm(iscsi_properties, ("--rescan",))
173
 
 
174
 
            tries = tries + 1
175
 
            if not os.path.exists(host_device):
176
 
                time.sleep(tries ** 2)
177
 
 
178
 
        if tries != 0:
179
 
            LOG.debug(_("Found iSCSI node %(mount_device)s "
180
 
                        "(after %(tries)s rescans)") %
181
 
                      locals())
182
 
 
183
 
        connection_info['data']['device_path'] = host_device
184
 
        sup = super(LibvirtISCSIVolumeDriver, self)
185
 
        return sup.connect_volume(connection_info, mount_device)
186
 
 
187
 
    @utils.synchronized('connect_volume')
188
 
    def disconnect_volume(self, connection_info, mount_device):
189
 
        """Detach the volume from instance_name"""
190
 
        sup = super(LibvirtISCSIVolumeDriver, self)
191
 
        sup.disconnect_volume(connection_info, mount_device)
192
 
        iscsi_properties = connection_info['data']
193
 
        # NOTE(vish): Only disconnect from the target if no luns from the
194
 
        #             target are in use.
195
 
        device_prefix = ("/dev/disk/by-path/ip-%s-iscsi-%s-lun-" %
196
 
                         (iscsi_properties['target_portal'],
197
 
                          iscsi_properties['target_iqn']))
198
 
        devices = self.connection.get_all_block_devices()
199
 
        devices = [dev for dev in devices if dev.startswith(device_prefix)]
200
 
        if not devices:
201
 
            self._iscsiadm_update(iscsi_properties, "node.startup", "manual",
202
 
                                  check_exit_code=[0, 255])
203
 
            self._run_iscsiadm(iscsi_properties, ("--logout",),
204
 
                               check_exit_code=[0, 255])
205
 
            self._run_iscsiadm(iscsi_properties, ('--op', 'delete'),
206
 
                               check_exit_code=[0, 21, 255])