2
0
mirror of https://github.com/xcat2/confluent.git synced 2026-01-12 02:52:30 +00:00

Merge branch 'master' of github.com:jjohnson42/confluent

This commit is contained in:
Jarrod Johnson
2018-10-29 14:56:37 -04:00
4 changed files with 217 additions and 16 deletions

View File

@@ -478,7 +478,8 @@ def createresource(args):
collection = targpath
else:
collection, _, resname = targpath.rpartition('/')
keydata['name'] = resname
if 'name' not in keydata:
keydata['name'] = resname
makecall(session.create, (collection, keydata))

View File

@@ -422,6 +422,9 @@ def get_input_message(path, operation, inputdata, nodes=None, multinode=False,
elif (path[:3] == ['configuration', 'storage', 'disks'] and
operation != 'retrieve'):
return InputDisk(path, nodes, inputdata)
elif (path[:3] == ['configuration', 'storage', 'volumes'] and
operation in ('update', 'create')):
return InputVolumes(path, nodes, inputdata)
elif 'inventory/firmware/updates/active' in '/'.join(path) and inputdata:
return InputFirmwareUpdate(path, nodes, inputdata)
elif '/'.join(path).startswith('media/detach'):
@@ -713,6 +716,60 @@ class InputDisk(ConfluentInputMessage):
keyname = 'state'
class InputVolumes(ConfluentInputMessage):
def __init__(self, path, nodes, inputdata):
self.inputbynode = {}
self.stripped = False
if not inputdata:
raise exc.InvalidArgumentException('missing input data')
if isinstance(inputdata, dict):
volnames = [None]
if len(path) == 6:
volnames = path[-1]
volnames = inputdata.get('name', volnames)
if not isinstance(volnames, list):
volnames = volnames.split(',')
sizes = inputdata.get('size', [None])
if not isinstance(sizes, list):
sizes = sizes.split(',')
disks = inputdata.get('disks', [])
if not disks:
raise exc.InvalidArgumentException(
'disks are currently required to create a volume')
raidlvl = inputdata.get('raidlevel', None)
inputdata = []
for size in sizes:
if volnames:
currname = volnames.pop(0)
else:
currname = None
inputdata.append(
{'name': currname, 'size': size,
'disks': disks,
'raidlevel': raidlvl})
for node in nodes:
self.inputbynode[node] = []
for input in inputdata:
volname = None
if len(path) == 6:
volname = path[-1]
volname = input.get('name', volname)
if not volname:
volname = None
volsize = input.get('size', None)
if isinstance(input['disks'], list):
disks = input['disks']
else:
disks = input['disks'].split(',')
raidlvl = input.get('raidlevel', None)
for node in nodes:
self.inputbynode[node].append({'name': volname,
'size': volsize,
'disks': disks,
'raidlevel': raidlvl,
})
class InputPowerMessage(ConfluentInputMessage):
valid_values = set([
'on',
@@ -1253,14 +1310,41 @@ class KeyValueData(ConfluentMessage):
else:
self.kvpairs = {name: kvdata}
class Array(ConfluentMessage):
def __init__(self, name, disks=None, raid=None, volumes=None,
id=None, capacity=None, available=None):
self.kvpairs = {
name: {
'disks': disks,
'raid': raid,
'id': id,
'volumes': volumes,
'capacity': capacity,
'available': available,
}
}
class Volume(ConfluentMessage):
def __init__(self, name, volname, size, state, array):
self.kvpairs = {
name: {
'name': volname,
'size': size,
'state': state,
'array': array,
}
}
class Disk(ConfluentMessage):
valid_states = set([
'jbod',
'unconfigured',
'hotspare',
'online',
])
state_aliases = {
'unconfigured good': 'unconfigured',
'global hot spare': 'hotspare',
}
def _normalize_state(self, instate):
@@ -1269,11 +1353,12 @@ class Disk(ConfluentMessage):
return newstate
elif newstate in self.state_aliases:
return self.state_aliases[newstate]
raise Exception("Unknown state")
raise Exception("Unknown state {0}".format(instate))
def __init__(self, name, label=None, description=None,
diskid=None, state=None, serial=None, fru=None):
diskid=None, state=None, serial=None, fru=None,
array=None):
state = self._normalize_state(state)
self.kvpairs = {
name: {
@@ -1283,6 +1368,7 @@ class Disk(ConfluentMessage):
'state': state,
'serial': serial,
'fru': fru,
'array': array,
}
}

View File

@@ -29,6 +29,7 @@ import eventlet.support.greendns
from fnmatch import fnmatch
import pyghmi.constants as pygconstants
import pyghmi.exceptions as pygexc
import pyghmi.storage as storage
console = eventlet.import_patched('pyghmi.ipmi.console')
ipmicommand = eventlet.import_patched('pyghmi.ipmi.command')
import socket
@@ -340,7 +341,7 @@ class IpmiConsole(conapi.Console):
self.solconnection.send_break()
def perform_requests(operator, nodes, element, cfg, inputdata):
def perform_requests(operator, nodes, element, cfg, inputdata, realop):
cryptit = cfg.decrypt
cfg.decrypt = True
configdata = cfg.get_node_attributes(nodes, _configattributes)
@@ -350,7 +351,7 @@ def perform_requests(operator, nodes, element, cfg, inputdata):
for node in nodes:
livingthreads.add(_ipmiworkers.spawn(
perform_request, operator, node, element, configdata, inputdata,
cfg, resultdata))
cfg, resultdata, realop))
while livingthreads:
try:
datum = resultdata.get(timeout=10)
@@ -376,10 +377,10 @@ def perform_requests(operator, nodes, element, cfg, inputdata):
def perform_request(operator, node, element,
configdata, inputdata, cfg, results):
configdata, inputdata, cfg, results, realop):
try:
return IpmiHandler(operator, node, element, configdata, inputdata,
cfg, results).handle_request()
cfg, results, realop).handle_request()
except pygexc.IpmiException as ipmiexc:
excmsg = str(ipmiexc)
if excmsg in ('Session no longer connected', 'timeout'):
@@ -391,8 +392,8 @@ def perform_request(operator, node, element,
results.put(msg.ConfluentTargetTimeout(node, str(tu)))
except ssl.SSLEOFError:
results.put(msg.ConfluentNodeError(
self.node, 'Unable to communicate with the https server on '
'the target BMC'))
node, 'Unable to communicate with the https server on '
'the target BMC'))
except exc.PubkeyInvalid:
results.put(msg.ConfluentNodeError(
node,
@@ -409,7 +410,8 @@ def perform_request(operator, node, element,
persistent_ipmicmds = {}
class IpmiHandler(object):
def __init__(self, operation, node, element, cfd, inputdata, cfg, output):
def __init__(self, operation, node, element, cfd, inputdata, cfg, output,
realop):
self.sensormap = {}
self.invmap = {}
self.output = output
@@ -423,6 +425,7 @@ class IpmiHandler(object):
self.node = node
self.element = element
self.op = operation
self.realop = realop
connparams = get_conn_params(node, self.cfg)
self.ipmicmd = None
self.inputdata = inputdata
@@ -936,6 +939,70 @@ class IpmiHandler(object):
if self.element[-1] == '':
self.element = self.element[:-1]
storelem = self.element[2:]
if 'read' == self.op:
return self._show_storage(storelem)
elif 'update' == self.realop:
return self._update_storage(storelem)
elif 'delete' == self.op:
return self._delete_storage(storelem)
elif 'create' == self.realop:
return self._create_storage(storelem)
def _delete_storage(self, storelem):
if len(storelem) < 2 or storelem[0] != 'volumes':
raise exc.InvalidArgumentException('Must target a specific volume')
volname = storelem[-1]
curr = self.ipmicmd.get_storage_configuration()
volumes = []
toremove = storage.ConfigSpec(arrays=[storage.Array(volumes=volumes)])
for pool in curr.arrays:
for vol in pool.volumes:
if simplify_name(vol.name) == volname:
volumes.append(vol)
self.ipmicmd.remove_storage_configuration(toremove)
self.output.put(msg.DeletedResource(volname))
def _create_storage(self, storelem):
if 'volumes' not in storelem:
raise exc.InvalidArgumentException('Can only create volumes')
vols = []
thedisks = None
currcfg = self.ipmicmd.get_storage_configuration()
disks = []
vols = []
vol = self.inputdata.inputbynode[self.node][0]
raidlvl = vol['raidlevel']
for disk in currcfg.disks:
if simplify_name(disk.name) in vol['disks']:
disks.append(disk)
elif (disk.status == 'Unconfigured Good' and
vol['disks'][0] in ('remainder', 'rest')):
disks.append(disk)
elif vol['disks'][0] == 'all':
disks.append(disk)
for vol in self.inputdata.inputbynode[self.node]:
if thedisks and thedisks != vol['disks']:
raise exc.InvalidArgumentException(
'Not currently supported to create multiple arrays '
'in a single request')
if raidlvl and vol['raidlevel'] != raidlvl:
raise exc.InvalidArgumentException('Cannot mix raid levels in '
'a single array')
vols.append(storage.Volume(name=vol['name'], size=vol['size']))
newcfg = storage.ConfigSpec(
arrays=(storage.Array(raid=raidlvl, disks=disks, volumes=vols),))
self.ipmicmd.apply_storage_configuration(newcfg)
return self._show_storage(storelem)
def _update_storage(self, storelem):
if storelem[0] == 'disks':
if len(storelem) == 1:
raise exc.InvalidArgumentException('Must target a disk')
self.set_disk(storelem[-1],
self.inputdata.inputbynode[self.node])
self._show_storage(storelem)
def _show_storage(self, storelem):
if storelem[0] == 'disks':
if len(storelem) == 1:
return self.list_disks()
@@ -973,6 +1040,15 @@ class IpmiHandler(object):
return True
return False
def set_disk(self, name, state):
scfg = self.ipmicmd.get_storage_configuration()
for disk in scfg.disks:
if (name == 'all' or simplify_name(disk.name) == name or
disk == name):
disk.status = state
self.ipmicmd.apply_storage_configuration(
storage.ConfigSpec(disks=scfg.disks))
def show_disk(self, name):
scfg = self.ipmicmd.get_storage_configuration()
for disk in scfg.disks:
@@ -982,12 +1058,24 @@ class IpmiHandler(object):
msg.Disk(self.node, disk.name, disk.description,
disk.id, disk.status, disk.serial,
disk.fru))
for arr in scfg.arrays:
arrname = '{0}-{1}'.format(*arr.id)
for disk in arr.disks:
if (name == 'all' or simplify_name(disk.name) == name or
disk == name):
self.output.put(
msg.Disk(self.node, disk.name, disk.description,
disk.id, disk.status, disk.serial,
disk.fru, arrname))
def list_disks(self):
scfg = self.ipmicmd.get_storage_configuration()
self.output.put(msg.ChildCollection('all'))
for disk in scfg.disks:
self.output.put(msg.ChildCollection(simplify_name(disk.name)))
for arr in scfg.arrays:
for disk in arr.disks:
self.output.put(msg.ChildCollection(simplify_name(disk.name)))
def list_arrays(self):
scfg = self.ipmicmd.get_storage_configuration()
@@ -995,6 +1083,30 @@ class IpmiHandler(object):
for arr in scfg.arrays:
self.output.put(msg.ChildCollection('{0}-{1}'.format(*arr.id)))
def show_array(self, name):
scfg = self.ipmicmd.get_storage_configuration()
for arr in scfg.arrays:
arrname = '{0}-{1}'.format(*arr.id)
if arrname == name:
vols = []
for vol in arr.volumes:
vols.append(simplify_name(vol.name))
disks = []
for disk in arr.disks:
disks.append(simplify_name(disk.name))
self.output.put(msg.Array(self.node, disks, arr.raid,
vols, arrname, arr.capacity,
arr.available_capacity))
def show_volume(self, name):
scfg = self.ipmicmd.get_storage_configuration()
for arr in scfg.arrays:
arrname = '{0}-{1}'.format(*arr.id)
for vol in arr.volumes:
if name == simplify_name(vol.name):
self.output.put(msg.Volume(self.node, vol.name, vol.size,
vol.status, arrname))
def list_volumes(self):
scfg = self.ipmicmd.get_storage_configuration()
self.output.put(msg.ChildCollection('all'))
@@ -1239,7 +1351,7 @@ def initthread():
_ipmithread = eventlet.spawn(_ipmi_evtloop)
def create(nodes, element, configmanager, inputdata):
def create(nodes, element, configmanager, inputdata, realop='create'):
initthread()
if element == ['_console', 'session']:
if len(nodes) > 1:
@@ -1247,12 +1359,12 @@ def create(nodes, element, configmanager, inputdata):
return IpmiConsole(nodes[0], configmanager)
else:
return perform_requests(
'update', nodes, element, configmanager, inputdata)
'update', nodes, element, configmanager, inputdata, realop)
def update(nodes, element, configmanager, inputdata):
initthread()
return create(nodes, element, configmanager, inputdata)
return create(nodes, element, configmanager, inputdata, 'update')
def retrieve(nodes, element, configmanager, inputdata):
@@ -1267,7 +1379,8 @@ def retrieve(nodes, element, configmanager, inputdata):
return firmwaremanager.list_updates(nodes, configmanager.tenant,
element, 'ffdc')
else:
return perform_requests('read', nodes, element, configmanager, inputdata)
return perform_requests('read', nodes, element, configmanager,
inputdata, 'read')
def delete(nodes, element, configmanager, inputdata):
initthread()
@@ -1281,4 +1394,5 @@ def delete(nodes, element, configmanager, inputdata):
return firmwaremanager.remove_updates(nodes, configmanager.tenant,
element, type='ffdc')
return perform_requests(
'delete', nodes, element, configmanager, inputdata)
'delete', nodes, element, configmanager, inputdata, 'delete')

View File

@@ -143,7 +143,7 @@ def sessionhdl(connection, authname, skipauth=False, cert=None):
cfm = authdata[1]
send_data(connection, {'authpassed': 1})
request = tlvdata.recv(connection)
if 'collective' in request and skipauth:
if request and 'collective' in request and skipauth:
if not libssl:
tlvdata.send(
connection,