mirror of
https://github.com/xcat2/confluent.git
synced 2026-09-02 07:26:04 +00:00
Merge pull request #278 from Obihoernchen/fix/configurable-endpoints
configurable sockapi path and ipmi port
This commit is contained in:
@@ -148,7 +148,11 @@ class Console(object):
|
||||
# some BMCs disagree on the endianness, so do both
|
||||
valid_ports = (self.port, struct.unpack(
|
||||
'<H', struct.pack('>H', self.port))[0])
|
||||
if (data[8] + (data[9] << 8)) not in valid_ports:
|
||||
solport = data[8] + (data[9] << 8)
|
||||
# A bmc behind a port forward answers with the port it listens on
|
||||
# rather than the one it was reached through; payloads ride the
|
||||
# session, never the advertised port.
|
||||
if solport not in valid_ports and self.port == 623:
|
||||
# TODO(jbjohnso): support atypical SOL port number
|
||||
raise NotImplementedError("Non-standard SOL Port Number")
|
||||
# ignore data[10:11] for now, the vlan detail, shouldn't matter to this
|
||||
|
||||
@@ -263,14 +263,37 @@ def get_conn_params(node, configdata):
|
||||
kg = configdata['secret.ipmikg']['value']
|
||||
else:
|
||||
kg = passphrase
|
||||
# TODO(jbjohnso): check if the end has some number after a : without []
|
||||
# for non default port
|
||||
# Read a port off the address, as the redfish plugin does. Brackets come
|
||||
# off, unlike there: this address goes to socket.getaddrinfo, which rejects
|
||||
# a bracketed literal, rather than into a URL where one is required.
|
||||
bmc = bmc.strip()
|
||||
port = 623
|
||||
if bmc.startswith('['):
|
||||
bracket_end = bmc.find(']')
|
||||
if bracket_end > 0:
|
||||
if len(bmc) > bracket_end + 1 and bmc[bracket_end + 1] == ':':
|
||||
try:
|
||||
port = int(bmc[bracket_end + 2:])
|
||||
except (ValueError, TypeError):
|
||||
pass
|
||||
bmc = bmc[1:bracket_end]
|
||||
elif bmc.count(':') == 1:
|
||||
hostpart, _, portstr = bmc.rpartition(':')
|
||||
try:
|
||||
port = int(portstr)
|
||||
except (ValueError, TypeError):
|
||||
pass
|
||||
bmc = hostpart
|
||||
if not 0 < port <= 65535:
|
||||
# NOTE: Fallback to 623 if port read is not valid
|
||||
port = 623
|
||||
|
||||
return {
|
||||
'username': username,
|
||||
'passphrase': passphrase,
|
||||
'kg': kg,
|
||||
'bmc': bmc,
|
||||
'port': 623,
|
||||
'port': port,
|
||||
}
|
||||
|
||||
|
||||
@@ -288,6 +311,11 @@ def _donothing(data):
|
||||
class IpmiConsole(conapi.Console):
|
||||
configattributes = frozenset(_configattributes)
|
||||
bmctonodemapping = {}
|
||||
# Whether this instance is the one that put its endpoint in the mapping
|
||||
# above. False until it does, so that an instance rejected as a duplicate,
|
||||
# or one that failed earlier in __init__, does not remove on the way out an
|
||||
# entry that belongs to the node holding the endpoint.
|
||||
claimedbmc = False
|
||||
|
||||
def __init__(self, node, config):
|
||||
self.error = None
|
||||
@@ -304,20 +332,26 @@ class IpmiConsole(conapi.Console):
|
||||
self.kg = connparams['kg']
|
||||
self.bmc = connparams['bmc']
|
||||
self.port = connparams['port']
|
||||
# The port is part of the identity: several bmcs may sit behind one
|
||||
# address on different ports, and they are distinct devices.
|
||||
self.bmckey = (self.bmc, self.port)
|
||||
self.connected = False
|
||||
# ok, is self.bmc unique among nodes already
|
||||
# ok, is this bmc unique among nodes already
|
||||
# Cannot actually create console until 'connect', when we get callback
|
||||
if (self.bmc in self.bmctonodemapping and
|
||||
self.bmctonodemapping[self.bmc] != node):
|
||||
if (self.bmckey in self.bmctonodemapping and
|
||||
self.bmctonodemapping[self.bmckey] != node):
|
||||
raise Exception(
|
||||
"Duplicate hardwaremanagement.manager attribute for {0} and {1}".format(
|
||||
node, self.bmctonodemapping[self.bmc]))
|
||||
self.bmctonodemapping[self.bmc] = node
|
||||
node, self.bmctonodemapping[self.bmckey]))
|
||||
self.bmctonodemapping[self.bmckey] = node
|
||||
self.claimedbmc = True
|
||||
|
||||
def __del__(self):
|
||||
self.solconnection = None
|
||||
if not self.claimedbmc:
|
||||
return
|
||||
try:
|
||||
del self.bmctonodemapping[self.bmc]
|
||||
del self.bmctonodemapping[self.bmckey]
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
|
||||
@@ -438,31 +438,40 @@ async def _tlsstartup(cnn):
|
||||
raise Exception('Unable to find workable SSL support')
|
||||
tasks.spawn(sessionhdl(cnn, authname, cert=cert))
|
||||
|
||||
def removesocket():
|
||||
default_socketpath = "/var/run/confluent/api.sock"
|
||||
|
||||
|
||||
def removesocket(socketpath=None):
|
||||
if socketpath is None:
|
||||
socketpath = default_socketpath
|
||||
try:
|
||||
os.remove("/var/run/confluent/api.sock")
|
||||
os.remove(socketpath)
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
async def _unixdomainhandler(bind_group=None, bind_perms=None):
|
||||
async def _unixdomainhandler(bind_group=None, bind_perms=None,
|
||||
socketpath=None):
|
||||
aloop = asyncio.get_running_loop()
|
||||
if not bind_perms:
|
||||
bind_perms = 0o666
|
||||
if socketpath is None:
|
||||
socketpath = default_socketpath
|
||||
unixsocket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
|
||||
unixsocket.settimeout(0)
|
||||
try:
|
||||
os.remove("/var/run/confluent/api.sock")
|
||||
os.remove(socketpath)
|
||||
except OSError: # if file does not exist, no big deal
|
||||
pass
|
||||
if not os.path.isdir("/var/run/confluent"):
|
||||
os.makedirs('/var/run/confluent', 0o755)
|
||||
socketdir = os.path.dirname(socketpath)
|
||||
if socketdir and not os.path.isdir(socketdir):
|
||||
os.makedirs(socketdir, 0o755)
|
||||
oldumask = os.umask(0o777 - bind_perms)
|
||||
unixsocket.bind("/var/run/confluent/api.sock")
|
||||
os.chmod("/var/run/confluent/api.sock", bind_perms)
|
||||
unixsocket.bind(socketpath)
|
||||
os.chmod(socketpath, bind_perms)
|
||||
if bind_group:
|
||||
shutil.chown("/var/run/confluent/api.sock", group=bind_group)
|
||||
shutil.chown(socketpath, group=bind_group)
|
||||
os.umask(oldumask)
|
||||
atexit.register(removesocket)
|
||||
atexit.register(removesocket, socketpath)
|
||||
unixsocket.listen(5)
|
||||
while True:
|
||||
cnn, addr = await aloop.sock_accept(unixsocket)
|
||||
@@ -491,13 +500,15 @@ async def _unixdomainhandler(bind_group=None, bind_perms=None):
|
||||
|
||||
|
||||
class SockApi(object):
|
||||
def __init__(self, bindhost=None, bindport=None, bindgroup=None, bindperms=None):
|
||||
def __init__(self, bindhost=None, bindport=None, bindgroup=None,
|
||||
bindperms=None, socketpath=None):
|
||||
self.tlsserver = None
|
||||
self.unixdomainserver = None
|
||||
self.bind_host = bindhost or '::'
|
||||
self.bind_port = bindport or 13001
|
||||
self.bind_group = bindgroup
|
||||
self.bind_perms = bindperms
|
||||
self.socketpath = socketpath or default_socketpath
|
||||
|
||||
async def start(self):
|
||||
global auditlog
|
||||
@@ -509,7 +520,8 @@ class SockApi(object):
|
||||
self.start_remoteapi()
|
||||
else:
|
||||
tasks.spawn(self.watch_for_cert())
|
||||
self.unixdomainserver = tasks.spawn_task(_unixdomainhandler(self.bind_group, self.bind_perms))
|
||||
self.unixdomainserver = tasks.spawn_task(_unixdomainhandler(
|
||||
self.bind_group, self.bind_perms, self.socketpath))
|
||||
|
||||
async def watch_for_cert(self):
|
||||
watcher = libc.inotify_init1(os.O_NONBLOCK)
|
||||
|
||||
Reference in New Issue
Block a user