Skip to content

Instantly share code, notes, and snippets.

@takekawa
Created November 16, 2012 06:02
Show Gist options
  • Save takekawa/4084670 to your computer and use it in GitHub Desktop.
Save takekawa/4084670 to your computer and use it in GitHub Desktop.
openstack nova essex-4でのvolume attachに関連するコード nova/nova/compute/manager.py 1656 def attach_volume(self, context, instance_uuid, volume_id, mountpoint): 1657 """Attach a volume to an instance.""" 1658 volume = self.volume_api.get(conte
nova/nova/compute/manager.py
1656 def attach_volume(self, context, instance_uuid, volume_id, mountpoint):
1657 """Attach a volume to an instance."""
1658 volume = self.volume_api.get(context, volume_id)
1659 context = context.elevated()
1660 instance_ref = self.db.instance_get_by_uuid(context, instance_uuid)
1661 instance_id = instance_ref['id']
1662 msg = _("instance %(instance_uuid)s: attaching volume %(volume_id)s"
1663 " to %(mountpoint)s")
1664 LOG.audit(_('Attaching volume %(volume_id)s to %(mountpoint)s'),
1665 locals(), context=context, instance=instance_ref)
1666 try:
1667 connector = self.driver.get_volume_connector(instance_ref)
1668 connection_info = self.volume_api.initialize_connection(context,
1669 volume,
1670 connector)
1671 except Exception: # pylint: disable=W0702
1672 with utils.save_and_reraise_exception():
1673 msg = _("instance %(instance_uuid)s: attach failed"
1674 " %(mountpoint)s, removing")
1675 LOG.exception(msg % locals(), context=context)
1676 self.volume_api.unreserve_volume(context, volume)
1677 try:
1678 self.driver.attach_volume(connection_info, #<-----ここでatttachしている
1679 instance_ref['name'],
1680 mountpoint)
1681 except Exception: # pylint: disable=W0702
1682 with utils.save_and_reraise_exception():
1683 LOG.exception(_('Attach failed %(mountpoint)s, removing'),
1684 locals(), context=context,
1685 instance=instance_ref)
1686 self.volume_api.terminate_connection(context,
1687 volume,
1688 connector)
1689
1690 self.volume_api.attach(context, volume, instance_id, mountpoint)
1691 values = {
1692 'instance_id': instance_id,
1693 'connection_info': utils.dumps(connection_info),
1694 'device_name': mountpoint,
1695 'delete_on_termination': False,
1696 'virtual_name': None,
1697 'snapshot_id': None,
1698 'volume_id': volume_id,
1699 'volume_size': None,
1700 'no_device': None}
1701 self.db.block_device_mapping_create(context, values)
1702 return True
nova/nova/virt/libvirt/connection.py
463 @exception.wrap_exception()
464 def attach_volume(self, connection_info, instance_name, mountpoint):
465 virt_dom = self._lookup_by_name(instance_name)
466 mount_device = mountpoint.rpartition("/")[2]
467 xml = self.volume_driver_method('connect_volume', #<----connect_volume でvolume情報を取得
468 connection_info,
469 mount_device)
470
471 if FLAGS.libvirt_type == 'lxc':
472 self._attach_lxc_volume(xml, virt_dom, instance_name)
473 else:
474 try:
475 virt_dom.attachDevice(xml) #<----ここでlibvirt経由でdeviceを追加している
476 except Exception, ex:
477 self.volume_driver_method('disconnect_volume',
478 connection_info,
479 mount_device)
480
481 if isinstance(ex, libvirt.libvirtError):
482 errcode = ex.get_error_code()
483 if errcode == libvirt.VIR_ERR_OPERATION_FAILED:
484 raise exception.DeviceIsBusy(device=mount_device)
485 raise
nova/nova/virt/libvirt/volume.py
106 @utils.synchronized('connect_volume')
107 def connect_volume(self, connection_info, mount_device):
108 """Attach the volume to instance_name"""
109 iscsi_properties = connection_info['data']
110 # NOTE(vish): If we are on the same host as nova volume, the
111 # discovery makes the target so we don't need to
112 # run --op new. Therefore, we check to see if the
113 # target exists, and if we get 255 (Not Found), then
114 # we run --op new. This will also happen if another
115 # volume is using the same target.
116 try:
117 self._run_iscsiadm(iscsi_properties, ())
118 except exception.ProcessExecutionError as exc:
119 # iscsiadm returns 21 for "No records found" after version 2.0-871
120 if exc.exit_code in [21, 255]:
121 self._run_iscsiadm(iscsi_properties, ('--op', 'new'))
122 else:
123 raise
124
125 if iscsi_properties.get('auth_method'):
126 self._iscsiadm_update(iscsi_properties,
127 "node.session.auth.authmethod",
128 iscsi_properties['auth_method'])
129 self._iscsiadm_update(iscsi_properties,
130 "node.session.auth.username",
131 iscsi_properties['auth_username'])
132 self._iscsiadm_update(iscsi_properties,
133 "node.session.auth.password",
134 iscsi_properties['auth_password'])
135
136 # NOTE(vish): If we have another lun on the same target, we may
137 # have a duplicate login
138 self._run_iscsiadm(iscsi_properties, ("--login",),
139 check_exit_code=[0, 255])
140
141 self._iscsiadm_update(iscsi_properties, "node.startup", "automatic")
142
143 host_device = ("/dev/disk/by-path/ip-%s-iscsi-%s-lun-%s" %
144 (iscsi_properties['target_portal'],
145 iscsi_properties['target_iqn'],
146 iscsi_properties.get('target_lun', 0)))
147
148 # The /dev/disk/by-path/... node is not always present immediately
149 # TODO(justinsb): This retry-with-delay is a pattern, move to utils?
150 tries = 0
151 while not os.path.exists(host_device):
152 if tries >= FLAGS.num_iscsi_scan_tries:
153 raise exception.Error(_("iSCSI device not found at %s") %
154 (host_device))
155
156 LOG.warn(_("ISCSI volume not yet found at: %(mount_device)s. "
157 "Will rescan & retry. Try number: %(tries)s") %
158 locals())
159
160 # The rescan isn't documented as being necessary(?), but it helps
161 self._run_iscsiadm(iscsi_properties, ("--rescan",))
162
163 tries = tries + 1
164 if not os.path.exists(host_device):
165 time.sleep(tries ** 2)
166
167 if tries != 0:
168 LOG.debug(_("Found iSCSI node %(mount_device)s "
169 "(after %(tries)s rescans)") %
170 locals())
171
172 connection_info['data']['device_path'] = host_device
173 sup = super(LibvirtISCSIVolumeDriver, self)
174 return sup.connect_volume(connection_info, mount_device)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment