def plugn_config(self, name, **args): """ Configure an LDMSD plugin Parameters: - The plugin name Keyword Parameters: - dictionary of plugin specific key/value pairs """ cfg_str = '' for key in args: if len(cfg_str): cfg_str += ' ' cfg_str += key + '=' + args[key] req = LDMSD_Request( command_id=LDMSD_Request.PLUGN_CONFIG, attrs=[ LDMSD_Req_Attr(attr_id=LDMSD_Req_Attr.NAME, value=name), LDMSD_Req_Attr(attr_id=LDMSD_Req_Attr.STRING, value=cfg_str) ]) try: req.send(self) resp = req.receive(self) return resp['errcode'], resp['msg'] except Exception: self.close() return errno.ENOTCONN, None
def updtr_prdcr_del(self, name, regex): """ Remove matching producers from an updater policy. The updater must be STOPPED. Parameters: - The updater name - A regular expression matching zero or more producers Returns: A tuple of status, data - status is an errno from the errno module - data is an error message if status != 0 or None """ req = LDMSD_Request( command_id=LDMSD_Request.UPDTR_PRDCR_DEL, attrs=[ LDMSD_Req_Attr(attr_id=LDMSD_Req_Attr.NAME, value=name), LDMSD_Req_Attr(attr_id=LDMSD_Req_Attr.REGEX, value=regex) ]) try: req.send(self) resp = req.receive(self) return resp['errcode'], resp['msg'] except Exception: self.close() return errno.ENOTCONN, None
def updtr_match_del(self, name, regex, match='schema'): """ Remove a match condition from an updater. The updater must be STOPPED. Parameters:: name - The update policy name regex - The regular expression string match - The value with which to compare; if match='inst' (default), the expression will match the set's instance name, if match='schema', the expression will match the set's schema name. Returns: A tuple of status, data - status is an errno from the errno module - data is an error message if status != 0 or None """ req = LDMSD_Request( command_id=LDMSD_Request.UPDTR_MATCH_DEL, attrs=[ LDMSD_Req_Attr(attr_id=LDMSD_Req_Attr.NAME, value=name), LDMSD_Req_Attr(attr_id=LDMSD_Req_Attr.REGEX, value=regex), LDMSD_Req_Attr(attr_id=LDMSD_Req_Attr.MATCH, value=match) ]) try: req.send(self) resp = req.receive(self) return resp['errcode'], resp['msg'] except Exception: self.close() return errno.ENOTCONN, None
def strgp_metric_add(self, name, metric_name): """ Add a metric name that will be stored. By default all metrics in the schema specified in strgp_add will be stored. Parameters:: - The update policy name - The name of the metric to store Returns: A tuple of status, data - status is an errno from the errno module - data is an error message if status != 0 or None """ req = LDMSD_Request( command_id=LDMSD_Request.STRGP_METRIC_ADD, attrs=[ LDMSD_Req_Attr(attr_id=LDMSD_Req_Attr.NAME, value=name), LDMSD_Req_Attr(attr_id=LDMSD_Req_Attr.METRIC, value=metric_name) ]) try: req.send(self) resp = req.receive(self) return resp['errcode'], resp['msg'] except Exception: self.close() return errno.ENOTCONN, None
def strgp_metric_del(self, name, metric_name): """ Remove a metric name from the storage policy. The storage policy must be STOPPED. Parameters: - The storage policy name - The metric name to remove Returns: A tuple of status, data - status is an errno from the errno module - data is an error message if status != 0 or None """ req = LDMSD_Request( command_id=LDMSD_Request.STRGP_METRIC_DEL, attrs=[ LDMSD_Req_Attr(attr_id=LDMSD_Req_Attr.NAME, value=name), LDMSD_Req_Attr(attr_id=LDMSD_Req_Attr.METRIC, value=metric_name) ]) try: req.send(self) resp = req.receive(self) return resp['errcode'], resp['msg'] except Exception: self.close() return errno.ENOTCONN, None
def strgp_prdcr_add(self, name, regex): """ Add matching producers to an storage policy. The storage policy must be STOPPED. Parameters: - The storage policy name - A regular expression matching zero or more producers Returns: A tuple of status, data - status is an errno from the errno module - data is an error message if status != 0 or None """ req = LDMSD_Request( command_id=LDMSD_Request.STRGP_PRDCR_ADD, attrs=[ LDMSD_Req_Attr(attr_id=LDMSD_Req_Attr.NAME, value=name), LDMSD_Req_Attr(attr_id=LDMSD_Req_Attr.REGEX, value=regex) ]) try: req.send(self) resp = req.receive(self) return resp['errcode'], resp['msg'] except Exception: self.close() return errno.ENOTCONN, None
def listen(self, xprt, port, host=None, auth=None): """ Add a listening endpoint Parameters: xprt - Transport name [sock, rdma, ugni] port - Port number [host] - Hostname [auth] - Authentication domain - If none, the default authentication given the command line (-a and -A) will be used """ attr_list = [ LDMSD_Req_Attr(attr_id=LDMSD_Req_Attr.XPRT, value=xprt), LDMSD_Req_Attr(attr_id=LDMSD_Req_Attr.PORT, value=port) ] req = LDMSD_Request( command='listen', attrs=attr_list ) try: req.send(self) resp = req.receive(self) return resp['errcode'], resp['msg'] except Exception as e: return errno.ENOTCONN, None
def strgp_add(self, name, plugin, container, schema, perm=0o600): """ Add a Storage Policy that will store metric set data when updates complete on a metric set. Parameters: name The unique storage policy name. plugin The name of the storage backend. container The storage backend container name. schema The schema name of the metric set to store. Keyword Parameters: perm The permission required to modify the storage policy, default perm=0o600 Returns: A tuple of status, data - status is an errno from the errno module - data is an error message if status != 0 or None """ attrs = [ LDMSD_Req_Attr(attr_id=LDMSD_Req_Attr.NAME, value=name), LDMSD_Req_Attr(attr_id=LDMSD_Req_Attr.PLUGIN, value=plugin), LDMSD_Req_Attr(attr_id=LDMSD_Req_Attr.CONTAINER, value=container), LDMSD_Req_Attr(attr_id=LDMSD_Req_Attr.SCHEMA, value=schema), LDMSD_Req_Attr(attr_id=LDMSD_Req_Attr.PERM, value=str(perm)) ] req = LDMSD_Request(command_id=LDMSD_Request.STRGP_ADD, attrs=attrs) try: req.send(self) resp = req.receive(self) return resp['errcode'], resp['msg'] except Exception: self.close() return errno.ENOTCONN, None
def prdcr_status(self, name = None): """ Query the LDMSD for the status of one or more producers. Keyword Parameters: name - If not None (default), the name of the producer to query. Returns: A tuple of status, data - status is an errno from the errno module - data is an error message if status != 0 or the object containing the producer status """ if name: attrs = [ attrs.append(LDMSD_Req_Attr(attr_id=LDMSD_Req_Attr.NAME, value=name)) ] else: attrs = None req = LDMSD_Request(command_id=LDMSD_Request.PRDCR_STATUS, attrs=attrs) try: req.send(self) resp = req.receive(self) err = resp['errcode'] except Exception: self.close() return errno.ENOTCONN, None if err == 0: status = json.loads(resp['msg']) else: status = None return err, status
def prdcr_subscribe(self, regex, stream): """ Subscribe to stream data from matching producers Parameters: - A regular expression matching producer names - The name of the stream Returns: A tuple of status, data - status is an errno from the errno module - data is an error message if status != 0 or None """ req = LDMSD_Request(command_id = LDMSD_Request.PRDCR_STREAM_SUBSCRIBE, attrs = [ LDMSD_Req_Attr(attr_id=LDMSD_Req_Attr.REGEX, value=regex), LDMSD_Req_Attr(attr_id=LDMSD_Req_Attr.STREAM, value=stream) ]) try: req.send(self) resp = req.receive(self) return resp['errcode'], resp['msg'] except Exception: self.close() return errno.ENOTCONN, None
def daemon_status(self): """Query the daemon's status""" req = LDMSD_Request(command_id=LDMSD_Request.DAEMON_STATUS) try: req.send(self) resp = req.receive(self) return resp['errcode'], resp['msg'] except Exception: self.close() return errno.ENOTCONN, None
def prdcr_add(self, name, ptype, xprt, host, port, reconnect, auth=None, perm=None): """ Add a producer. A producer is a peer to the LDMSD being configured. Once started, the LDSMD will attempt to connect to this peer periodically until the connection succeeds. A producer starts in the STOPPED state. Use the prdcr_start() function to start the producer. Parameters: - The name to give the producer. This name must be unique on the producer. - The type of the producer, one of 'passive', or 'active' - The transport type, one of 'sock', 'ugni', 'rdma', or 'fabric' - The hostname - The port number - The reconnect interval in microseconds Keyword Parameters: perm - The configuration client permission required to modify the producer configuration. Default is None. Returns: A tuple of status, data - status is an errno from the errno module - data is an error message if status != 0 or None """ attrs = [ LDMSD_Req_Attr(attr_id = LDMSD_Req_Attr.NAME, value=name), LDMSD_Req_Attr(attr_id = LDMSD_Req_Attr.TYPE, value=ptype), LDMSD_Req_Attr(attr_id = LDMSD_Req_Attr.XPRT, value=xprt), LDMSD_Req_Attr(attr_id = LDMSD_Req_Attr.HOST, value=host), LDMSD_Req_Attr(attr_id = LDMSD_Req_Attr.PORT, value=str(port)), LDMSD_Req_Attr(attr_id = LDMSD_Req_Attr.INTERVAL, value=str(reconnect)) ] if auth: attrs.append(LDMSD_Req_Attr(attr_id=LDMSD_Req_Attr.AUTH, value=auth)) if perm: attrs.append(LDMSD_Req_Attr(attr_id=LDMSD_Req_Attr.PERM, value=str(perm))) req = LDMSD_Request( command_id=LDMSD_Request.PRDCR_ADD, attrs=attrs) try: req.send(self) resp = req.receive(self) return resp['errcode'], resp['msg'] except Exception: self.close() return errno.ENOTCONN, None
def test_comm_1_level_agg(self): ctrl = ldmsdInbandConfig(host = self.AGG1_HOST, port = self.AGG1_PORT, xprt = self.AGG1_XPRT, auth = self.AUTH, auth_opt = self.AUTH_OPT) attr = LDMSD_Req_Attr(value = None, attr_id = LDMSD_Req_Attr.PATH) attr_term = LDMSD_Req_Attr() req = LDMSD_Request(command_id = LDMSD_Request.GREETING, attrs = [attr, attr_term]) req.send(ctrl) resp = req.receive(ctrl) ctrl.close() self.assertEqual(len(resp['attr_list']), 1) self.assertEqual(resp['attr_list'][0].attr_value, "{0}:{1}".format(self.SMP_NAME, self.AGG1_NAME)) self.assertTrue(self.smp.is_running()) self.assertTrue(self.agg1.is_running())
def thread_stats(self, reset=False): """Query the daemon's I/O thread utilization data""" req = LDMSD_Request( command_id=LDMSD_Request.THREAD_STATS, attrs=[ LDMSD_Req_Attr(attr_id=LDMSD_Req_Attr.RESET, value=str(reset)), ]) try: req.send(self) resp = req.receive(self) return resp['errcode'], resp['msg'] except Exception: self.close() return errno.ENOTCONN, None
def updtr_start(self, name, interval=None, auto=None): """ Start a STOPPED updater. Parameters: - The name of the updater to start. Keyword Parameters: interval - The update data collection interval. This is required if auto is False. auto - [True|False] If True, the updater will schedule set updates according to the update hint. The sets with no hints will not be updated. If False, the updater will schedule the set updates according to the given sample interval. The default is False. Returns: A tuple of status, data - status is an errno from the errno module - data is an error message if status != 0 or None """ attrs = [ LDMSD_Req_Attr(attr_id=LDMSD_Req_Attr.NAME, value=name), ] if interval: intrvl_us, offset_us = cvt_sample_intrvl_str_to_us(interval) if auto: return errno.EINVAL, "'auto' is incompatible with 'interval'" attrs += [ LDMSD_Req_Attr(attr_id=LDMSD_Req_Attr.INTERVAL, value=str(intrvl_us)), LDMSD_Req_Attr(attr_id=LDMSD_Req_Attr.OFFSET, value=str(offset_us)) ] elif auto: attrs += [ LDMSD_Req_Attr(attr_id=LDMSD_Req_Attr.AUTO_INTERVAL, value=str(auto)) ] req = LDMSD_Request(command_id=LDMSD_Request.UPDTR_START, attrs=attrs) try: req.send(self) resp = req.receive(self) return resp['errcode'], resp['msg'] except Exception: self.close() return errno.ENOTCONN, None
def prdcr_start(self, name, regex=True, reconnect=None): """ Start one or more STOPPED producers Parameters: - The name of the producer to start. If regex=True (default), this is a regular expression. Keyword Parameters: regex - True, the 'name' parameter is a regular expression. Default is False. reconnect - The reconnect interval in microseconds. If not None, this will override the interval specified when the producer was created. Default is None. Returns: A tuple of status, data - status is an errno from the errno module - data is an error message if status != 0 or None """ if regex: cmd_id = LDMSD_Request.PRDCR_START_REGEX name_id = LDMSD_Req_Attr.REGEX else: cmd_id = LDMSD_Request.PRDCR_START name_id = LDMSD_Req_Attr.NAME attrs = [ LDMSD_Req_Attr(attr_id = name_id, value=name), ] if reconnect: attrs.append(LDMSD_Req_Attr(attr_id = LDMSD_Req_Attr.INTERVAL, value = str(reconnect))) req = LDMSD_Request(command_id = cmd_id, attrs = attrs) try: req.send(self) resp = req.receive(self) return resp['errcode'], resp['msg'] except Exception: self.close() return errno.ENOTCONN, None
def smplr_start(self, name, interval_str): intrvl_us, offset_us = cvt_sample_intrvl_str_to_us(interval_str) req = LDMSD_Request( command_id = LDMSD_Request.PLUGN_START, attrs=[ LDMSD_Req_Attr(attr_id=LDMSD_Req_Attr.NAME, value=name), LDMSD_Req_Attr(attr_id=LDMSD_Req_Attr.INTERVAL, value=str(intrvl_us)), LDMSD_Req_Attr(attr_id=LDMSD_Req_Attr.OFFSET, value=str(offset_us)) ]) try: req.send(self) resp = req.receive(self) err = resp['errcode'] except Exception: self.close() return errno.ENOTCONN, None if err == 0 and resp['msg'] is not None: status = json.loads(resp['msg']) else: status = None return err, status
def plugn_stop(self, name): """ Stop a LDMSD Plugin Parameters: - The plugin name Returns: A tuple of status, data - status is an errno from the errno module - data is an error message if status != 0 or None """ req = LDMSD_Request( command_id=LDMSD_Request.PLUGN_STOP, attrs=[ LDMSD_Req_Attr(attr_id=LDMSD_Req_Attr.NAME, value=name) ]) try: req.send(self) resp = req.receive(self) return resp['errcode'], resp['msg'] except Exception as e: self.close() return errno.ENOTCONN, None
def plugn_load(self, name): """ Load an LDMSD plugin. Parameters:: name - The plugin name Returns: A tuple of status, data - status is an errno from the errno module - data is an error message if status != 0 or None """ req = LDMSD_Request( command_id=LDMSD_Request.PLUGN_LOAD, attrs=[ LDMSD_Req_Attr(attr_id=LDMSD_Req_Attr.NAME, value=name), ]) try: req.send(self) resp = req.receive(self) return resp['errcode'], resp['msg'] except Exception: return errno.ENOTCONN, None
def strgp_start(self, name): """ Start a STOPPED storage policy. Parameters: - The name of the storage policy to start. Returns: A tuple of status, data - status is an errno from the errno module - data is an error message if status != 0 or None """ attrs = [ LDMSD_Req_Attr(attr_id=LDMSD_Req_Attr.NAME, value=name), ] req = LDMSD_Request(command_id=LDMSD_Request.STRGP_START, attrs=attrs) try: req.send(self) resp = req.receive(self) return resp['errcode'], resp['msg'] except Exception: self.close() return errno.ENOTCONN, None
def req(self, cmd_line): """Form LDMSD_Request according to `cmd_line` and send. Returns the response received from the daemon. """ if not self._conn: raise RuntimeError("Error: no LDMS connection") verb, args = ( cmd_line.split(" ", 1) + [None] )[:2] attr_list = [] if args: attr_s = [] attr_str_list = args.split() for attr_str in attr_str_list: name = None value = None [name, value] = (attr_str.split("=", 1) + [None])[:2] if (verb == "config" and name != "name") or (verb == "env"): attr_s.append(attr_str) elif (verb == "auth_add" and name not in ["name", "plugin"]): attr_s.append(attr_str) else: try: attr = LDMSD_Req_Attr(value = value, attr_name = name) except KeyError: attr_s.append(attr_str) except Exception: raise else: attr_list.append(attr) if len(attr_s) > 0: attr_str = " ".join(attr_s) attr = LDMSD_Req_Attr(value = attr_str, attr_id = LDMSD_Req_Attr.STRING) attr_list.append(attr) request = LDMSD_Request(command = verb, attrs = attr_list) request.send(self) resp = request.receive(self) return resp
def prdcrset_status(self, name = None, instance = None, schema = None): """ Query the LDMSD for one or all producer's set status Keyword Parameters: name - If not None (default), the producer to query instance - If not None (default), the set's instance name schema - If not None (default), the set's schema name Returns: A tuple of status, data - status is an errno from the errno module - data is an error message if status != 0 or the object containing the producer sets status """ attrs = [] if name: attrs.append(attrs.append(LDMSD_Req_Attr(attr_id=LDMSD_Req_Attr.NAME, value=name))) if instance: attrs.append(attrs.append(LDMSD_Req_Attr(attr_id=LDMSD_Req_Attr.INSTANCE, value=instance))) if schema: attrs.append(attrs.append(LDMSD_Req_Attr(attr_id=LDMSD_Req_Attr.SCHEMA, value=schema))) if len(attrs) == 0: attrs = None req = LDMSD_Request(command_id=LDMSD_Request.PRDCR_SET_STATUS, attrs=attrs) try: req.send(self) resp = req.receive(self) except Exception: self.close() return errno.ENOTCONN, None err = resp['errcode'] if err == 0: status = json.loads(resp['msg']) else: status = None return err, status
def plugn_start(self, name, interval_us, offset_us=None): # If offset unspecified, start in non-synchronous mode req_attrs = [ LDMSD_Req_Attr(attr_id=LDMSD_Req_Attr.NAME, value=name), LDMSD_Req_Attr(attr_id=LDMSD_Req_Attr.INTERVAL, value=str(interval_us)) ] if offset_us != None: offset_us = check_offset(interval_us, offset_us) req_attrs.append(LDMSD_Req_Attr(attr_id=LDMSD_Req_Attr.OFFSET, value=str(offset_us))) req = LDMSD_Request( command_id = LDMSD_Request.PLUGN_START, attrs=req_attrs ) try: req.send(self) resp = req.receive(self) err = resp['errcode'] except Exception: self.close() return errno.ENOTCONN, None if err == 0 and resp['msg'] is not None: status = json.loads(resp['msg']) else: status = None return err, status
def updtr_stop(self, name): """ Stop a RUNNING updater. Parameters: - The name of the updater Returns: A tuple of status, data - status is an errno from the errno module - data is an error message if status != 0 or None """ req = LDMSD_Request( command_id=LDMSD_Request.UPDTR_STOP, attrs=[ LDMSD_Req_Attr(attr_id=LDMSD_Req_Attr.NAME, value=name) ]) try: req.send(self) resp = req.receive(self) return resp['errcode'], resp['msg'] except Exception: self.close() return errno.ENOTCONN, None
def prdcr_stop(self, name, regex=True): """ Stop one or more RUNNING producers Parameters: - The name of the producer to start. If regex=True (default), this is a regular expression. Keyword Parameters: regex - True, the 'name' parameter is a regular expression. Default is False. Returns: A tuple of status, data - status is an errno from the errno module - data is an error message if status != 0 or None """ if regex: cmd_id = LDMSD_Request.PRDCR_STOP_REGEX name_id = LDMSD_Req_Attr.REGEX else: cmd_id = LDMSD_Request.PRDCR_STOP name_id = LDMSD_Req_Attr.NAME attrs = [ LDMSD_Req_Attr(attr_id = name_id, value=name), ] req = LDMSD_Request(command_id = cmd_id, attrs = attrs) try: req.send(self) resp = req.receive(self) return resp['errcode'], resp['msg'] except Exception: self.close() return errno.ENOTCONN, None
def smplrset_status(self, name=None): """ Return the metric sets provided by a sampler plugin. Keyword Parameters: name - The name of the sampler to query. If None (default), all samplers are queried. Returns: A tuple of status, data - status is an errno from the errno module - data is an error message if status != 0 or the object containing the sampler set status """ if name: attrs = [ LDMSD_Req_Attr(attr_id=LDMSD_Req_Attr.NAME, value=name) ] else: attrs = None req = LDMSD_Request( command_id=LDMSD_Request.PLUGN_SETS, attrs=attrs ) try: req.send(self) resp = req.receive(self) err = resp['errcode'] except Exception: self.close() return errno.ENOTCONN, None if err == 0: status = json.loads(resp['msg']) else: status = None return err, status
def strgp_del(self, name): """ Delete a storage policy. The storage policy cannot be RUNNING. Parameters: name - The policy name Returns: A tuple of status, data - status is an errno from the errno module - data is an error message if status != 0 or None """ req = LDMSD_Request( command_id=LDMSD_Request.STRGP_DEL, attrs = [ LDMSD_Req_Attr(attr_id=LDMSD_Req_Attr.NAME, value=name) ]) try: req.send(self) resp = req.receive(self) return resp['errcode'], resp['msg'] except Exception: self.close() return errno.ENOTCONN, None
def auth_add(self, name, auth_opt=None): """ Add an authentication domain Parameters: name - The authentication domain name <plugin-specific attribute> e.g. conf=ldmsauth.conf """ attrs=[ LDMSD_Req_Attr(attr_id=LDMSD_Req_Attr.NAME, value=name) ] if auth_opt: if len(auth_opt.split('=')) > 1: attrs.append(LDMSD_Req_Attr(attr_id=LDMSD_Req_Attr.STRING, value=auth_opt)) else: auth_opt = 'conf='+auth_opt attrs.append(LDMSD_Req_Attr(attr_id=LDMSD_Req_Attr.STRING, value=auth_opt)) req = LDMSD_Request( command_id=LDMSD_Request.AUTH_ADD, attrs=attrs ) try: req.send(self) resp = req.receive(self) return resp['errcode'], resp['msg'] except Exception: return errno.ENOTCONN, None
def updtr_add(self, name, interval=None, push=None, auto=None, perm=None): """ Add an Updater that will periodically update Producer metric sets either by pulling the content or by registering for an update push. The default is to pull a set's contents. Parameters: name - The update policy name Keyword Parameters: interval - The update data collection interval. This is when the push argument is not given. push - [onchange|true] 'onchange' means the updater will receive updated set data the set sampler ends a transaction or explicitly pushes the update. 'true' means the updater will receive an update only when the set source explicitly pushes the update. If `push` is used, `auto_interval` cannot be `true`. auto - [True|False] If True, the updater will schedule set updates according to the update hint. The sets with no hints will not be updated. If False, the updater will schedule the set updates according to the given sample interval. The default is False. perm - The configuration client permission required to modify the updater configuration. Returns: A tuple of status, data - status is an errno from the errno module - data is an error message if status != 0 or None """ attrs = [ LDMSD_Req_Attr(attr_id=LDMSD_Req_Attr.NAME, value=name) ] if interval: intrvl_us, offset_us = cvt_sample_intrvl_str_to_us(interval) if push or auto: return errno.EINVAL, "EINVAL" attrs += [ LDMSD_Req_Attr(attr_id=LDMSD_Req_Attr.INTERVAL, value=str(intrvl_us)), LDMSD_Req_Attr(attr_id=LDMSD_Req_Attr.OFFSET, value=str(offset_us)) ] elif push: if auto: return errno.EINVAL, "EINVAL" if push != 'onchange' and push != True: return errno.EINVAL, "EINVAL" attrs += [ LDMSD_Req_Attr(attr_id=LDMSD_Req_Attr.PUSH, value=str(push)) ] else: if auto is None: return errno.EINVAL, "EINVAL" attrs += [ LDMSD_Req_Attr(attr_id=LDMSD_Req_Attr.AUTO_INTERVAL, value=str(auto)) ] if perm: attrs.append(LDMSD_Req_Attr(attr_id=LDMSD_Req_Attr.PERM, value=str(perm))) req = LDMSD_Request(command_id=LDMSD_Request.UPDTR_ADD, attrs=attrs) try: req.send(self) resp = req.receive(self) return resp['errcode'], resp['msg'] except Exception: self.close() return errno.ENOTCONN, None