Skip to content

Instantly share code, notes, and snippets.

@Funcan
Created September 17, 2014 17:11
Show Gist options
  • Select an option

  • Save Funcan/d325bd3f9f05d9df001a to your computer and use it in GitHub Desktop.

Select an option

Save Funcan/d325bd3f9f05d9df001a to your computer and use it in GitHub Desktop.
# Copyright 20141 Hewlett Packard. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
def __read_session_info(self):
"""
Get session info from iscsiadm
"""
cmd = CommandExecutor()
status = cmd.execute(['sudo', 'iscsiadm', '--mode', 'session', '-P',
'3'])
if status != 0:
self.log.error('Getting session information failed: status %d'
'stderr %s' % (status, cmd.stderr))
lines = cmd.stdout.split('\n')
return lines
def _count_leading_tabs(self, s):
"""
Count the number of leading tabs in s
"""
total = 0
for c in s:
if not c == '\t':
break
total += 1
return total
def get_iscsi_info(self, lines):
if lines == None:
lines = self.__read_session_info()
# Parse the result into a bunch of nested dictionaries...
# FIXME:Should make a helper function - we might want to check more
# properties elsewhere later.
# FIXME: Document this parsing state machine since it is a bit ugly
targets = {}
targetname = None
targetdetails = {}
state = 'initial'
while (len(lines) > 0):
line = lines.pop(0)
indent = self._count_leading_tabs(line)
line = line.strip()
if line.startswith('***'):
continue
if line == '':
continue
if state == 'initial':
if line.startswith('Target: '):
assert indent == 0
assert targetname == None
targetname = line.split(':')[1].strip()
state = 'parsing target'
elif state == 'parsing target':
assert targetname != None
if line == 'Interface:':
assert indent == 2
state = 'parsing interface'
continue
else:
assert indent == 1
key, value = (line.split(':')[0],
":".join(line.split(':')[1:]))
targetdetails[key.strip()] = value.strip()
elif state == 'parsing interface':
assert targetname != None
assert indent == 2
if line == 'Negotiated iSCSI params:':
state = 'parsing params'
continue
else:
key, value = (line.split(':')[0],
":".join(line.split(':')[1:]))
targetdetails[key.strip()] = value.strip()
elif state == 'parsing params':
assert targetname != None
assert indent == 2
if line == 'Attached SCSI devices:':
state = 'parsing devices'
continue
else:
key, value = (line.split(':')[0],
":".join(line.split(':')[1:]))
targetdetails[key.strip()] = value.strip()
elif state == 'parsing devices':
if indent == 0:
# New target
targets[targetname] = targetdetails
targetdetails = {}
state = 'parsing target'
targetname = line.split(':')[1].strip()
continue
# FIXME: This is probably wrong if we have multiple luns in one
# target, but I haven't got a machine set up like that to test
# at the moment
elif indent == 1:
# New persistant portal? Not sure what this looks like or
# how we should handle it... punt for now
raise Exception('Unhandled output from iscsiadm')
elif indent == 2:
# This would be important if we handled more than one
# lun... for now, skip it
continue
else:
assert indent == 3
assert line.startswith('Attached scsi disk')
device = line.split()[3]
devicestate = line.split()[5]
targetdetails['device'] = device
targetdetails['state'] = devicestate
continue
else:
raise Exception('get_device_name: Unknown state in parsing'
'state machine! Panic: state = %s' %
state)
# Last target found has not yet been saved...
targets[targetname] = targetdetails
return targets
def get_device_name(self, target, portal, lines=None):
"""
Get the device name for a target we are attached to
Raise an exception if we aren't attached to that target
"""
self.log.debug('get_device_name target %s portal %s' % (target,
portal))
targets = self.get_iscsi_info(lines)
try:
self.log.debug('Device returned is %s' %
targets[target]['device'])
return targets[target]['device']
except KeyError:
raise KeyError("ISCSI target not attached")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment