mirror of
https://github.com/xcat2/confluent.git
synced 2025-02-16 18:49:04 +00:00
Merge branch 'master' of github.com:jjohnson42/confluent
This commit is contained in:
commit
b78266eff7
0
confluent_client/bin/collate
Normal file → Executable file
0
confluent_client/bin/collate
Normal file → Executable file
0
confluent_client/bin/nodebmcreset
Normal file → Executable file
0
confluent_client/bin/nodebmcreset
Normal file → Executable file
0
confluent_client/bin/nodeconfig
Normal file → Executable file
0
confluent_client/bin/nodeconfig
Normal file → Executable file
0
confluent_client/bin/nodedefine
Normal file → Executable file
0
confluent_client/bin/nodedefine
Normal file → Executable file
58
confluent_client/bin/nodegroupdefine
Executable file
58
confluent_client/bin/nodegroupdefine
Executable file
@ -0,0 +1,58 @@
|
||||
#!/usr/bin/env python
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
# Copyright 2017 Lenovo
|
||||
#
|
||||
# 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.
|
||||
|
||||
import optparse
|
||||
import os
|
||||
import signal
|
||||
import sys
|
||||
|
||||
try:
|
||||
signal.signal(signal.SIGPIPE, signal.SIG_DFL)
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
path = os.path.dirname(os.path.realpath(__file__))
|
||||
path = os.path.realpath(os.path.join(path, '..', 'lib', 'python'))
|
||||
if path.startswith('/opt'):
|
||||
sys.path.append(path)
|
||||
|
||||
import confluent.client as client
|
||||
|
||||
argparser = optparse.OptionParser(
|
||||
usage='''\n %prog noderange attribute1=value1 attribute2=value,...
|
||||
\n ''')
|
||||
(options, args) = argparser.parse_args()
|
||||
requestargs=None
|
||||
try:
|
||||
noderange = args[0]
|
||||
except IndexError:
|
||||
argparser.print_help()
|
||||
sys.exit(1)
|
||||
client.check_globbing(noderange)
|
||||
session = client.Command()
|
||||
exitcode = 0
|
||||
attribs = {'name': noderange}
|
||||
for arg in args[1:]:
|
||||
key, val = arg.split('=')
|
||||
attribs[key] = val
|
||||
for r in session.create('/nodegroups/', attribs):
|
||||
if 'error' in r:
|
||||
sys.stderr.write(r['error'] + '\n')
|
||||
exitcode |= 1
|
||||
if 'created' in r:
|
||||
print('{0}: created'.format(r['created']))
|
||||
sys.exit(exitcode)
|
52
confluent_client/bin/nodegroupremove
Executable file
52
confluent_client/bin/nodegroupremove
Executable file
@ -0,0 +1,52 @@
|
||||
#!/usr/bin/env python
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
# Copyright 2017 Lenovo
|
||||
#
|
||||
# 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.
|
||||
|
||||
import optparse
|
||||
import os
|
||||
import signal
|
||||
import sys
|
||||
|
||||
try:
|
||||
signal.signal(signal.SIGPIPE, signal.SIG_DFL)
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
path = os.path.dirname(os.path.realpath(__file__))
|
||||
path = os.path.realpath(os.path.join(path, '..', 'lib', 'python'))
|
||||
if path.startswith('/opt'):
|
||||
sys.path.append(path)
|
||||
|
||||
import confluent.client as client
|
||||
|
||||
argparser = optparse.OptionParser(
|
||||
usage='''\n %prog noderange
|
||||
\n ''')
|
||||
(options, args) = argparser.parse_args()
|
||||
if len(args) != 1:
|
||||
argparser.print_help()
|
||||
sys.exit(1)
|
||||
noderange = args[0]
|
||||
client.check_globbing(noderange)
|
||||
session = client.Command()
|
||||
exitcode = 0
|
||||
for r in session.delete('/nodegroups/{0}'.format(noderange)):
|
||||
if 'error' in r:
|
||||
sys.stderr.write(r['error'] + '\n')
|
||||
exitcode |= 1
|
||||
if 'deleted' in r:
|
||||
print('{0}: deleted'.format(r['deleted']))
|
||||
sys.exit(exitcode)
|
0
confluent_client/bin/noderemove
Normal file → Executable file
0
confluent_client/bin/noderemove
Normal file → Executable file
0
confluent_client/bin/nodereseat
Normal file → Executable file
0
confluent_client/bin/nodereseat
Normal file → Executable file
@ -15,17 +15,22 @@ export MANPATH
|
||||
# disabled in the parent shell. Instead, store the current command in a
|
||||
# variable and use that to check for misglobbed noderanges, which was the goal
|
||||
alias nodeattrib='CURRENT_CMDLINE=$(HISTTIMEFORMAT= builtin history 1); export CURRENT_CMDLINE; nodeattrib'
|
||||
alias nodebmcreset='CURRENT_CMDLINE=$(HISTTIMEFORMAT= builtin history 1); export CURRENT_CMDLINE; nodebmcreset'
|
||||
alias nodeboot='CURRENT_CMDLINE=$(HISTTIMEFORMAT= builtin history 1); export CURRENT_CMDLINE; nodeboot'
|
||||
alias nodeconfig='CURRENT_CMDLINE=$(HISTTIMEFORMAT= builtin history 1); export CURRENT_CMDLINE; nodeconfig'
|
||||
alias nodeconsole='CURRENT_CMDLINE=$(HISTTIMEFORMAT= builtin history 1); export CURRENT_CMDLINE; nodeconsole'
|
||||
alias nodedefine='CURRENT_CMDLINE=$(HISTTIMEFORMAT= builtin history 1); export CURRENT_CMDLINE; nodedefine'
|
||||
alias nodeeventlog='CURRENT_CMDLINE=$(HISTTIMEFORMAT= builtin history 1); export CURRENT_CMDLINE; nodeeventlog'
|
||||
alias nodefirmware='CURRENT_CMDLINE=$(HISTTIMEFORMAT= builtin history 1); export CURRENT_CMDLINE; nodefirmware'
|
||||
alias nodegroupattrib='CURRENT_CMDLINE=$(HISTTIMEFORMAT= builtin history 1); export CURRENT_CMDLINE; nodegroupattrib'
|
||||
alias nodegroupdefine='CURRENT_CMDLINE=$(HISTTIMEFORMAT= builtin history 1); export CURRENT_CMDLINE; nodegroupdefine'
|
||||
alias nodegroupremove='CURRENT_CMDLINE=$(HISTTIMEFORMAT= builtin history 1); export CURRENT_CMDLINE; nodegroupremove'
|
||||
alias nodehealth='CURRENT_CMDLINE=$(HISTTIMEFORMAT= builtin history 1); export CURRENT_CMDLINE; nodehealth'
|
||||
alias nodeidentify='CURRENT_CMDLINE=$(HISTTIMEFORMAT= builtin history 1); export CURRENT_CMDLINE; nodeidentify'
|
||||
alias nodeinventory='CURRENT_CMDLINE=$(HISTTIMEFORMAT= builtin history 1); export CURRENT_CMDLINE; nodeinventory'
|
||||
alias nodelist='CURRENT_CMDLINE=$(HISTTIMEFORMAT= builtin history 1); export CURRENT_CMDLINE; nodelist'
|
||||
alias nodepower='CURRENT_CMDLINE=$(HISTTIMEFORMAT= builtin history 1); export CURRENT_CMDLINE; nodepower'
|
||||
alias noderemove='CURRENT_CMDLINE=$(HISTTIMEFORMAT= builtin history 1); export CURRENT_CMDLINE; noderemove'
|
||||
alias nodereseat='CURRENT_CMDLINE=$(HISTTIMEFORMAT= builtin history 1); export CURRENT_CMDLINE; nodereseat'
|
||||
alias noderun='CURRENT_CMDLINE=$(HISTTIMEFORMAT= builtin history 1); export CURRENT_CMDLINE; noderun'
|
||||
alias nodesensors='CURRENT_CMDLINE=$(HISTTIMEFORMAT= builtin history 1); export CURRENT_CMDLINE; nodesensors'
|
||||
|
33
confluent_client/doc/man/nodeconfig.ronn
Normal file
33
confluent_client/doc/man/nodeconfig.ronn
Normal file
@ -0,0 +1,33 @@
|
||||
nodeconfig(8) -- Show or change node configuration
|
||||
==================================================
|
||||
|
||||
## SYNOPSIS
|
||||
|
||||
`nodecanfig <noderange> [<configuration>..]`
|
||||
`nodecanfig <noderange> [<configuration=value>..]`
|
||||
|
||||
## DESCRIPTION
|
||||
|
||||
**nodeconfig** manages the configuration of nodes managed by confluent.
|
||||
Rather than manipulating the confluent database, this actually modifies the
|
||||
running configuration on the node firmware. Calling without '=' will show the
|
||||
current value, and '=' will change the value. Network information can be
|
||||
given as a node expression, as documented in the man page for nodeattribexpressions(5).
|
||||
|
||||
## EXAMPLES
|
||||
* Showing the current IP configuration of noderange BMC/IMM/XCC:
|
||||
`# nodeconfig s3,s4 bmc`
|
||||
`s3: bmc.ipv4_address: 172.30.254.193/16`
|
||||
`s3: bmc.ipv4_method: DHCP`
|
||||
`s3: bmc.ipv4_gateway: 172.30.0.6`
|
||||
`s4: bmc.ipv4_address: 172.30.254.192/16`
|
||||
`s4: bmc.ipv4_method: DHCP`
|
||||
`s4: bmc.ipv4_gateway: 172.30.0.6`
|
||||
|
||||
* Changing nodes `s3` and `s4` to have the ip addressess 10.1.2.3 and 10.1.2.4 with a 16 bit subnet mask:
|
||||
`# nodeconfig s3,s4 bmc.ipv4_address=10.1.2.{n1}/16`
|
||||
|
||||
## SEE ALSO
|
||||
|
||||
nodeattribexpressions(5)
|
||||
|
28
confluent_client/doc/man/nodedefine.ronn
Normal file
28
confluent_client/doc/man/nodedefine.ronn
Normal file
@ -0,0 +1,28 @@
|
||||
nodedefine(8) -- Define new confluent nodes
|
||||
|
||||
## SYNOPSIS
|
||||
|
||||
`nodedefine <noderange> [nodeattribute1=value1> <nodeattribute2=value2> ...]`
|
||||
|
||||
## DESCRIPTION
|
||||
|
||||
`nodedefine` allows the definition of new nodes for the confluent management
|
||||
system. It has the same syntax as `nodeattrib(8)`, and the commands differ in
|
||||
that `nodeattrib(8)` will error if a node does not exist.
|
||||
|
||||
## EXAMPLES
|
||||
|
||||
* Define two racks of nodes, named r{rack}u{u}:
|
||||
`# nodedefine r1u1-r2u4`
|
||||
`r1u4: created`
|
||||
`r1u1: created`
|
||||
`r1u2: created`
|
||||
`r1u3: created`
|
||||
`r2u4: created`
|
||||
`r2u3: created`
|
||||
`r2u2: created`
|
||||
`r2u1: created`
|
||||
|
||||
## SEE ALSO
|
||||
|
||||
noderange(5), nodeattribexpressions(8)
|
23
confluent_client/doc/man/nodegroupdefine.ronn
Normal file
23
confluent_client/doc/man/nodegroupdefine.ronn
Normal file
@ -0,0 +1,23 @@
|
||||
nodegroupdefine(8) -- Define new confluent node group
|
||||
|
||||
## SYNOPSIS
|
||||
|
||||
`nodegroupdefine <groupname> [nodeattribute1=value1> <nodeattribute2=value2> ...]`
|
||||
|
||||
## DESCRIPTION
|
||||
|
||||
`nodegroupdefine` allows the definition of a new node for the confluent management
|
||||
service. It may only define a single group name at a time.
|
||||
It has the same syntax as `nodegroupattrib(8)`, and the commands differ in
|
||||
that `nodegroupattrib(8)` will error if a node group does not exist.
|
||||
|
||||
## EXAMPLES
|
||||
|
||||
* Create a group called `compute`:
|
||||
`# nodegroupdefine compute`
|
||||
`compute: created`
|
||||
|
||||
|
||||
## SEE ALSO
|
||||
|
||||
nodeattribexpressions(8), nodegroupattrib(8), nodegroupremove(8)
|
18
confluent_client/doc/man/nodegroupremove.ronn
Normal file
18
confluent_client/doc/man/nodegroupremove.ronn
Normal file
@ -0,0 +1,18 @@
|
||||
nodegroupremove(8) -- Remove a nodegroup from the confluent database
|
||||
====================================================================
|
||||
|
||||
## SYNOPSIS
|
||||
|
||||
`nodegroupremove <noderange>`
|
||||
|
||||
## DESCRIPTION
|
||||
|
||||
`nodegroupremove` simply removes the given single nodegroup from the confluent database.
|
||||
|
||||
|
||||
## EXAMPLES
|
||||
|
||||
* Remove group called testgroup
|
||||
`# nodegroupremove testgroup`
|
||||
`testgroup: deleted`
|
||||
|
25
confluent_client/doc/man/noderemove.ronn
Normal file
25
confluent_client/doc/man/noderemove.ronn
Normal file
@ -0,0 +1,25 @@
|
||||
noderemove(8) -- Remove nodes from the confluent management service
|
||||
===================================================================
|
||||
|
||||
## SYNOPSIS
|
||||
|
||||
`noderemove <noderange>`
|
||||
|
||||
## DESCRIPTION
|
||||
|
||||
`noderemove` simply removes the given noderange from the confluent database.
|
||||
|
||||
|
||||
## EXAMPLES
|
||||
|
||||
* Remove two racks each with 4 nodes:
|
||||
`# noderemove r1u1-r2u4`
|
||||
`r1u4: deleted`
|
||||
`r1u1: deleted`
|
||||
`r1u2: deleted`
|
||||
`r1u3: deleted`
|
||||
`r2u4: deleted`
|
||||
`r2u3: deleted`
|
||||
`r2u2: deleted`
|
||||
`r2u1: deleted`
|
||||
|
19
confluent_client/doc/man/nodereseat.ronn
Normal file
19
confluent_client/doc/man/nodereseat.ronn
Normal file
@ -0,0 +1,19 @@
|
||||
nodereseat(8) -- Request a reseat of a node
|
||||
============================================
|
||||
|
||||
## SYNOPSIS
|
||||
|
||||
`nodereseat <noderange>`
|
||||
|
||||
## DESCRIPTION
|
||||
|
||||
`nodereseat` requests the enclosure manager of the current node to reseat that
|
||||
node's slot. This should be equivalent to removing the system entirely from
|
||||
the chassis and putting it back in, but without actually having to do so.
|
||||
|
||||
## EXAMPLES
|
||||
|
||||
* Reseating the node `s1`:
|
||||
`# nodereseat s1`
|
||||
`s1: Reseat successful`
|
||||
|
@ -499,7 +499,7 @@ def handle_nodegroup_request(configmanager, inputdata,
|
||||
raise Exception("TODO")
|
||||
plugroute = routespec.routeinfo
|
||||
inputdata = msg.get_input_message(
|
||||
pathcomponents[2:], operation, inputdata, configmanager)
|
||||
pathcomponents[2:], operation, inputdata)
|
||||
if 'handler' in plugroute: # fixed handler definition
|
||||
hfunc = getattr(pluginmap[plugroute['handler']], operation)
|
||||
return hfunc(
|
||||
|
@ -634,7 +634,17 @@ def get_nodename(cfg, handler, info):
|
||||
_map_unique_ids()
|
||||
nodename = nodes_by_uuid.get(curruuid, None)
|
||||
if not nodename: # as a last resort, search switch for info
|
||||
nodename = macmap.find_node_by_mac(info['hwaddr'], cfg)
|
||||
nodename, macinfo = macmap.find_nodeinfo_by_mac(info['hwaddr'], cfg)
|
||||
if (nodename and
|
||||
not handler.discoverable_by_switch(macinfo['maccount'])):
|
||||
if handler.devname == 'SMM':
|
||||
errorstr = 'Attempt to discover SMM by switch, but chained ' \
|
||||
'topology or incorrect net attributes detected, ' \
|
||||
'which is not compatible with switch discovery ' \
|
||||
'of SMM, nodename would have been ' \
|
||||
'{0}'.format(nodename)
|
||||
log.log({'error': errorstr})
|
||||
return None
|
||||
return nodename
|
||||
|
||||
|
||||
|
@ -19,6 +19,10 @@ webclient = eventlet.import_patched('pyghmi.util.webclient')
|
||||
class NodeHandler(object):
|
||||
https_supported = True
|
||||
is_enclosure = False
|
||||
devname = ''
|
||||
maxmacs = 2 # reasonable default, allowing for common scenario of
|
||||
# shared nic in theory, but blocking enclosure managers
|
||||
# and uplink ports
|
||||
|
||||
def __init__(self, info, configmanager):
|
||||
self._certfailreason = None
|
||||
@ -50,9 +54,10 @@ class NodeHandler(object):
|
||||
def preconfig(self):
|
||||
return
|
||||
|
||||
@property
|
||||
def discoverable_by_switch(self):
|
||||
return True
|
||||
def discoverable_by_switch(self, macs):
|
||||
# Given the number of macs sharing the port, is this handler
|
||||
# appropriate?
|
||||
return macs <= self.maxmacs
|
||||
|
||||
def _savecert(self, certificate):
|
||||
self._fp = certificate
|
||||
|
@ -26,6 +26,7 @@ def fixuuid(baduuid):
|
||||
class NodeHandler(bmchandler.NodeHandler):
|
||||
is_enclosure = True
|
||||
devname = 'SMM'
|
||||
maxmacs = 5 # support an enclosure, but try to avoid catching daisy chain
|
||||
|
||||
def scan(self):
|
||||
# the UUID is in a weird order, fix it up to match
|
||||
|
@ -229,33 +229,32 @@ def _map_switch_backend(args):
|
||||
_macsbyswitch[switch][ifname] = [mac]
|
||||
nodename = _nodelookup(switch, ifname)
|
||||
if nodename is not None:
|
||||
if mac in _nodesbymac and _nodesbymac[mac] != nodename:
|
||||
if mac in _nodesbymac and _nodesbymac[mac][0] != nodename:
|
||||
# For example, listed on both a real edge port
|
||||
# and by accident a trunk port
|
||||
log.log({'error': '{0} and {1} described by ambiguous'
|
||||
' switch topology values'.format(nodename,
|
||||
_nodesbymac[mac]
|
||||
)})
|
||||
_nodesbymac[mac] = None
|
||||
' switch topology values'.format(
|
||||
nodename, _nodesbymac[mac][0])})
|
||||
_nodesbymac[mac] = (None, None)
|
||||
else:
|
||||
_nodesbymac[mac] = nodename
|
||||
_nodesbymac[mac] = (nodename, maccounts[ifname])
|
||||
|
||||
|
||||
switchbackoff = 30
|
||||
|
||||
|
||||
def find_node_by_mac(mac, configmanager):
|
||||
def find_nodeinfo_by_mac(mac, configmanager):
|
||||
now = util.monotonic_time()
|
||||
if vintage and (now - vintage) < 90 and mac in _nodesbymac:
|
||||
return _nodesbymac[mac]
|
||||
return _nodesbymac[mac][0], {'maccount': _nodesbymac[mac][1]}
|
||||
# do not actually sweep switches more than once every 30 seconds
|
||||
# however, if there is an update in progress, wait on it
|
||||
for _ in update_macmap(configmanager,
|
||||
vintage and (now - vintage) < switchbackoff):
|
||||
if mac in _nodesbymac:
|
||||
return _nodesbymac[mac]
|
||||
return _nodesbymac[mac][0], {'maccount': _nodesbymac[mac][1]}
|
||||
# If update_mac bailed out, still check one last time
|
||||
return _nodesbymac.get(mac, None)
|
||||
return _nodesbymac.get(mac, (None, {'maccount': 0}))
|
||||
|
||||
|
||||
mapupdating = eventlet.semaphore.Semaphore()
|
||||
@ -456,7 +455,7 @@ def dump_macinfo(macaddr):
|
||||
raise exc.NotFoundException(
|
||||
'{0} not found in mac table of '
|
||||
'any known switches'.format(macaddr))
|
||||
return _dump_locations(info, macaddr, _nodesbymac.get(macaddr, None))
|
||||
return _dump_locations(info, macaddr, _nodesbymac.get(macaddr, (None,))[0])
|
||||
|
||||
|
||||
def rescan(cfg):
|
||||
|
Loading…
x
Reference in New Issue
Block a user