2
0
mirror of https://github.com/xcat2/confluent.git synced 2025-01-16 20:57:53 +00:00

Merge branch 'master' into clustertime

This commit is contained in:
Jarrod Johnson 2018-04-17 11:09:59 -04:00
commit fa24622704
14 changed files with 129 additions and 18 deletions

View File

@ -763,7 +763,10 @@ def conserver_command(filehandle, localcommand):
def get_command_bytes(filehandle, localcommand, cmdlen):
while len(localcommand) < cmdlen:
ready, _, _ = select.select((filehandle,), (), (), 1)
try:
ready, _, _ = select.select((filehandle,), (), (), 1)
except select.error:
ready = ()
if ready:
localcommand += filehandle.read()
return localcommand
@ -776,7 +779,10 @@ def check_escape_seq(currinput, filehandle):
sys.stdout.flush()
return conserver_command(
filehandle, currinput[len(conserversequence):])
ready, _, _ = select.select((filehandle,), (), (), 3)
try:
ready, _, _ = select.select((filehandle,), (), (), 3)
except select.error:
ready = ()
if not ready: # 3 seconds of no typing
break
currinput += filehandle.read()
@ -866,8 +872,11 @@ def check_power_state():
while inconsole or not doexit:
if inconsole:
rdylist, _, _ = select.select(
(sys.stdin, session.connection), (), (), 10)
try:
rdylist, _, _ = select.select(
(sys.stdin, session.connection), (), (), 10)
except select.error:
rdylist = ()
for fh in rdylist:
if fh == session.connection:
# this only should get called in the

View File

@ -67,6 +67,8 @@ cfgpaths = {
'bmc.ipv4_gateway': (
'configuration/management_controller/net_interfaces/management',
'ipv4_gateway'),
'bmc.hostname': (
'configuration/management_controller/hostname', 'hostname'),
}
autodeps = {

View File

@ -86,7 +86,7 @@ def run():
desc = pipedesc[r]
node = desc['node']
data = True
while data and select.select([r], [], [], 0):
while data and select.select([r], [], [], 0)[0]:
data = r.readline()
if data:
if desc['type'] == 'stdout':

View File

@ -1 +0,0 @@
__version__ = "1.5.0.dev395.ggacb3a20"

View File

@ -1684,19 +1684,33 @@ def restore_db_from_directory(location, password):
if e.errno == 2:
raise Exception("Cannot restore without keys, this may be a "
"redacted dump")
try:
moreglobals = json.load(open(os.path.join(location, 'globals.json')))
for globvar in moreglobals:
set_global(globvar, moreglobals[globvar])
except IOError as e:
if e.errno != 2:
raise
with open(os.path.join(location, 'main.json'), 'r') as cfgfile:
cfgdata = cfgfile.read()
ConfigManager(tenant=None)._load_from_json(cfgdata)
def dump_db_to_directory(location, password, redact=None):
if not redact:
def dump_db_to_directory(location, password, redact=None, skipkeys=False):
if not redact and not skipkeys:
with open(os.path.join(location, 'keys.json'), 'w') as cfgfile:
cfgfile.write(_dump_keys(password))
cfgfile.write('\n')
with open(os.path.join(location, 'main.json'), 'w') as cfgfile:
cfgfile.write(ConfigManager(tenant=None)._dump_to_json(redact=redact))
cfgfile.write('\n')
bkupglobals = {}
for globvar in _cfgstore['globals']:
if globvar.endswith('_key'):
continue
bkupglobals[globvar] = _cfgstore['globals'][globvar]
if bkupglobals:
json.dump(bkupglobals, open(os.path.join(location, 'globals.json')))
try:
for tenant in os.listdir(
os.path.join(ConfigManager._cfgdir, '/tenants/')):

View File

@ -154,6 +154,10 @@ def _init_core():
'pluginattrs': ['hardwaremanagement.method'],
'default': 'ipmi',
}),
'hostname': PluginRoute({
'pluginattrs': ['hardwaremanagement.method'],
'default': 'ipmi',
}),
'identifier': PluginRoute({
'pluginattrs': ['hardwaremanagement.method'],
'default': 'ipmi',

View File

@ -85,6 +85,7 @@ import eventlet
import eventlet.greenpool
import eventlet.semaphore
autosensors = set()
class nesteddict(dict):
def __missing__(self, key):
@ -350,7 +351,28 @@ def _parameterize_path(pathcomponents):
return validselectors, keyparams, listrequested, childcoll
def handle_autosense_config(operation, inputdata):
autosense = cfm.get_global('discovery.autosense')
autosense = autosense or autosense is None
if operation == 'retrieve':
yield msg.KeyValueData({'enabled': autosense})
elif operation == 'update':
enabled = inputdata['enabled']
if type(enabled) in (unicode, str):
enabled = enabled.lower() in ('true', '1', 'y', 'yes', 'enable',
'enabled')
if autosense == enabled:
return
cfm.set_global('discovery.autosense', enabled)
if enabled:
start_autosense()
else:
stop_autosense()
def handle_api_request(configmanager, inputdata, operation, pathcomponents):
if pathcomponents == ['discovery', 'autosense']:
return handle_autosense_config(operation, inputdata)
if operation == 'retrieve':
return handle_read_api_request(pathcomponents)
elif (operation in ('update', 'create') and
@ -398,6 +420,7 @@ def handle_read_api_request(pathcomponents):
if len(pathcomponents) == 1:
dirlist = [msg.ChildCollection(x + '/') for x in sorted(list(subcats))]
dirlist.append(msg.ChildCollection('rescan'))
dirlist.append(msg.ChildCollection('autosense'))
return dirlist
if not coll:
return show_info(queryparms['by-mac'])
@ -695,6 +718,9 @@ def get_chained_smm_name(nodename, cfg, handler, nl=None, checkswitch=True):
smmaddr = cd[nodename]['hardwaremanagement.manager']['value']
pkey = cd[nodename].get('pubkeys.tls_hardwaremanager', {}).get(
'value', None)
if not pkey:
# We cannot continue through a break in the chain
return None, False
if pkey:
cv = util.TLSCertVerifier(
cfg, nodename, 'pubkeys.tls_hardwaremanager').verify_cert
@ -1075,12 +1101,14 @@ def newnodes(added, deleting, configmanager):
global attribwatcher
global needaddhandled
global nodeaddhandler
_map_unique_ids()
configmanager.remove_watcher(attribwatcher)
allnodes = configmanager.list_nodes()
attribwatcher = configmanager.watch_attributes(
allnodes, ('discovery.policy', 'net*.switch',
'hardwaremanagement.manager', 'net*.switchport', 'id.uuid',
'pubkeys.tls_hardwaremanager', 'net*.bootable'), _recheck_nodes)
'hardwaremanagement.manager', 'net*.switchport',
'id.uuid', 'pubkeys.tls_hardwaremanager',
'net*.bootable'), _recheck_nodes)
if nodeaddhandler:
needaddhandled = True
else:
@ -1126,14 +1154,23 @@ def start_detection():
'hardwaremanagement.manager', 'net*.switchport', 'id.uuid',
'pubkeys.tls_hardwaremanager'), _recheck_nodes)
cfg.watch_nodecollection(newnodes)
eventlet.spawn_n(slp.snoop, safe_detected)
eventlet.spawn_n(pxe.snoop, safe_detected)
autosense = cfm.get_global('discovery.autosense')
if autosense or autosense is None:
start_autosense()
if rechecker is None:
rechecktime = util.monotonic_time() + 900
rechecker = eventlet.spawn_after(900, _periodic_recheck, cfg)
# eventlet.spawn_n(ssdp.snoop, safe_detected)
def stop_autosense():
for watcher in list(autosensors):
watcher.kill()
autosensors.discard(watcher)
def start_autosense():
autosensors.add(eventlet.spawn(slp.snoop, safe_detected))
autosensors.add(eventlet.spawn(pxe.snoop, safe_detected))
nodes_by_fprint = {}

View File

@ -191,7 +191,6 @@ def _parse_ssdp(peer, rsp, peerdata):
_, code, _ = headlines[0].split(' ', 2)
except ValueError:
return
myurl = None
if code == '200':
if nid in peerdata:
peerdatum = peerdata[nid]
@ -208,7 +207,6 @@ def _parse_ssdp(peer, rsp, peerdata):
header = header.strip()
value = value.strip()
if header == 'AL' or header == 'LOCATION':
myurl = value
if 'urls' not in peerdatum:
peerdatum['urls'] = [value]
elif value not in peerdatum['urls']:

View File

@ -397,6 +397,9 @@ def get_input_message(path, operation, inputdata, nodes=None, multinode=False,
elif (path[:3] == ['configuration', 'management_controller', 'identifier']
and operation != 'retrieve'):
return InputMCI(path, nodes, inputdata)
elif (path[:3] == ['configuration', 'management_controller', 'hostname']
and operation != 'retrieve'):
return InputHostname(path, nodes, inputdata, configmanager)
elif (path[:4] == ['configuration', 'management_controller',
'net_interfaces', 'management'] and operation != 'retrieve'):
return InputNetworkConfiguration(path, nodes, inputdata,
@ -719,6 +722,25 @@ class InputBMCReset(ConfluentInputMessage):
return self.inputbynode[node]
class InputHostname(ConfluentInputMessage):
def __init__(self, path, nodes, inputdata, configmanager):
self.inputbynode = {}
self.stripped = False
if not inputdata or 'hostname' not in inputdata:
raise exc.InvalidArgumentException('missing hostname attribute')
if nodes is None:
raise exc.InvalidArgumentException(
'This only supports per-node input')
for expanded in configmanager.expand_attrib_expression(
nodes, inputdata['hostname']):
node, value = expanded
self.inputbynode[node] = value
def hostname(self, node):
return self.inputbynode[node]
class InputMCI(ConfluentInputMessage):
def __init__(self, path, nodes, inputdata):
self.inputbynode = {}
@ -1298,6 +1320,17 @@ class MCI(ConfluentMessage):
self.kvpairs = {name: kv}
class Hostname(ConfluentMessage):
def __init__(self, name=None, hostname=None):
self.notnode = name is None
self.desc = 'BMC hostname'
kv = {'hostname': {'value': hostname}}
if self.notnode:
self.kvpairs = kv
else:
self.kvpairs = {name: kv}
class DomainName(ConfluentMessage):
def __init__(self, name=None, dn=None):
self.notnode = name is None

View File

@ -344,7 +344,7 @@ def perform_request(operator, node, element,
cfg, results).handle_request()
except pygexc.IpmiException as ipmiexc:
excmsg = str(ipmiexc)
if excmsg == 'Session no longer connected':
if excmsg in ('Session no longer connected', 'timeout'):
results.put(msg.ConfluentTargetTimeout(node))
else:
results.put(msg.ConfluentNodeError(node, excmsg))
@ -518,6 +518,8 @@ class IpmiHandler(object):
return self.handle_reset()
elif self.element[1:3] == ['management_controller', 'identifier']:
return self.handle_identifier()
elif self.element[1:3] == ['management_controller', 'hostname']:
return self.handle_hostname()
elif self.element[1:3] == ['management_controller', 'domain_name']:
return self.handle_domain_name()
elif self.element[1:3] == ['management_controller', 'ntp']:
@ -986,6 +988,16 @@ class IpmiHandler(object):
self.ipmicmd.set_mci(mci)
return
def handle_hostname(self):
if 'read' == self.op:
hostname = self.ipmicmd.get_hostname()
self.output.put(msg.Hostname(self.node, hostname))
return
elif 'update' == self.op:
hostname = self.inputdata.hostname(self.node)
self.ipmicmd.set_hostname(hostname)
return
def handle_domain_name(self):
if 'read' == self.op:
dn = self.ipmicmd.get_domain_name()

View File

@ -12,7 +12,7 @@ Group: Development/Libraries
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-buildroot
Prefix: %{_prefix}
BuildArch: noarch
Requires: python-pyghmi >= 1.0.34, python-eventlet, python-greenlet, python-crypto >= 2.6.1, confluent_client, pyparsing, python-paramiko, python-dns, python-netifaces, python2-pyasn1 >= 0.2.3, python-pysnmp >= 4.3.4, python-pyte, python-lxml, python-eficompressor
Requires: python-pyghmi >= 1.0.34, python-eventlet, python-greenlet, python-crypto >= 2.6.1, confluent_client, python-pyparsing, python-paramiko, python-dns, python-netifaces, python2-pyasn1 >= 0.2.3, python-pysnmp >= 4.3.4, python-pyte, python-lxml, python-eficompressor
Vendor: Jarrod Johnson <jjohnson2@lenovo.com>
Url: http://xcat.sf.net/

View File

@ -6,4 +6,6 @@ if [ "$NUMCOMMITS" != "$VERSION" ]; then
fi
echo $VERSION > VERSION
sed -e "s/#VERSION#/$VERSION/" setup.py.tmpl > setup.py
echo '__version__ = "'$VERSION'"' > confluent/__init__.py
if [ -f confluent/client.py ]; then
echo '__version__ = "'$VERSION'"' > confluent/__init__.py
fi

View File

@ -17,7 +17,8 @@ setup(
'confluent/plugins/shell/',
'confluent/plugins/configuration/'],
install_requires=['paramiko', 'pycrypto>=2.6', 'confluent_client>=0.1.0', 'eventlet',
'pyghmi>=0.6.5'],
'dnspython', 'netifaces', 'pyte', 'pysnmp', 'pyparsing',
'pyghmi>=1.0.44'],
scripts=['bin/confluent', 'bin/confluentdbutil'],
data_files=[('/etc/init.d', ['sysvinit/confluent']),
('/usr/lib/sysctl.d', ['sysctl/confluent.conf']),