示例#1
0
 def set_peers(self, peer_mat):
     if self.peer_mat is not None:
         raise Exception('validator configuration is static')
     self.peer_mat = AdjacencyMatrix(self.n_mag, peer_mat)
     mat = self.peer_mat.get_mat()
     for (nd_idx, nd) in enumerate(self.nodes):
         nd['Peers'] = []
         for (peer_idx, is_peer) in enumerate(mat[nd_idx]):
             if is_peer == 1 and peer_idx != nd_idx:
                 nd['Peers'].append(self.nodes[peer_idx]['NodeName'])
示例#2
0
 def set_quorum(self, quorum_mat):
     if self.quorum_mat is not None:
         raise Exception('validator configuration is static')
     self.quorum_mat = AdjacencyMatrix(self.n_mag, quorum_mat)
     mat = self.quorum_mat.get_mat()
     for (nd_idx, nd) in enumerate(self.nodes):
         nd['Quorum'] = []
         for (quorum_idx, in_quorum) in enumerate(mat[nd_idx]):
             if in_quorum == 1:
                 nd['Quorum'].append(self.nodes[quorum_idx]['NodeName'])
示例#3
0
 def set_nodes(self, node_mat):
     if self.node_mat is not None:
         raise Exception('validator configuration is static')
     self.node_mat = AdjacencyMatrix(self.n_mag, node_mat)
     mat = self.node_mat.get_mat()
     for (this_idx, this) in enumerate(self.nodes):
         this['Nodes'] = []
         for (other_idx, add_other) in enumerate(mat[this_idx]):
             if add_other == 1:
                 this['Nodes'].append(self._get_gossip_info(other_idx))
示例#4
0
 def set_blacklist(self, blacklist_mat=None):
     if self.blacklist_mat is not None:
         raise Exception('validator configuration is static')
     if blacklist_mat is None:
         assert self.peer_mat is not None
         blacklist_mat = self.peer_mat.negate()
     self.blacklist_mat = AdjacencyMatrix(self.n_mag, blacklist_mat)
     mat = self.blacklist_mat.get_mat()
     for (nd_idx, nd) in enumerate(self.nodes):
         nd['Blacklist'] = []
         for (exclude_idx, is_exclude) in enumerate(mat[nd_idx]):
             if is_exclude == 1:
                 exclude = self._get_gossip_info(exclude_idx)
                 nd['Blacklist'].append(exclude['Identifier'])
示例#5
0
 def set_quorum(self, quorum_mat):
     if self.quorum_mat is not None:
         raise Exception('validator configuration is static')
     self.quorum_mat = AdjacencyMatrix(self.n_mag, quorum_mat)
     mat = self.quorum_mat.get_mat()
     for (nd_idx, nd) in enumerate(self.nodes):
         nd['Quorum'] = []
         for (quorum_idx, in_quorum) in enumerate(mat[nd_idx]):
             if in_quorum == 1:
                 nd['Quorum'].append(self.nodes[quorum_idx]['NodeName'])
示例#6
0
 def set_peers(self, peer_mat):
     if self.peer_mat is not None:
         raise Exception('validator configuration is static')
     self.peer_mat = AdjacencyMatrix(self.n_mag, peer_mat)
     mat = self.peer_mat.get_mat()
     for (nd_idx, nd) in enumerate(self.nodes):
         nd['Peers'] = []
         for (peer_idx, is_peer) in enumerate(mat[nd_idx]):
             if is_peer == 1 and peer_idx != nd_idx:
                 nd['Peers'].append(self.nodes[peer_idx]['NodeName'])
示例#7
0
 def set_nodes(self, node_mat):
     if self.node_mat is not None:
         raise Exception('validator configuration is static')
     self.node_mat = AdjacencyMatrix(self.n_mag, node_mat)
     mat = self.node_mat.get_mat()
     for (this_idx, this) in enumerate(self.nodes):
         this['Nodes'] = []
         for (other_idx, add_other) in enumerate(mat[this_idx]):
             if add_other == 1:
                 this['Nodes'].append(self._get_gossip_info(other_idx))
示例#8
0
 def set_blacklist(self, blacklist_mat=None):
     if self.blacklist_mat is not None:
         raise Exception('validator configuration is static')
     if blacklist_mat is None:
         assert self.peer_mat is not None
         blacklist_mat = self.peer_mat.negate()
     self.blacklist_mat = AdjacencyMatrix(self.n_mag, blacklist_mat)
     mat = self.blacklist_mat.get_mat()
     for (nd_idx, nd) in enumerate(self.nodes):
         nd['Blacklist'] = []
         for (exclude_idx, is_exclude) in enumerate(mat[nd_idx]):
             if is_exclude == 1:
                 exclude = self._get_gossip_info(exclude_idx)
                 nd['Blacklist'].append(exclude['Identifier'])
示例#9
0
class NetworkConfig(object):
    @staticmethod
    def from_config_list(config_list):
        '''
        Creates a NetworkConfig from an existing list of config files by
        calling the constructor and then replacing the nodes
        Args:
            config_list: (list<dict>)
        Returns:
            net_cfg: (NetworkConfig)

        '''
        net_cfg = NetworkConfig({}, len(config_list))
        net_cfg.nodes = config_list
        return net_cfg

    def __init__(self,
                 n_mag,
                 overrides=None,
                 base_name='validator',
                 base_port=None,
                 base_http_port=None,
                 host=None,
                 endpoint_host=None,
                 provider=None):
        overrides = {} if overrides is None else overrides
        base_port = 9000 if base_port is None else base_port
        base_http_port = 8800 if base_http_port is None else base_http_port
        self.n_mag = n_mag
        self.provider = None
        if provider is not None:
            self.provider = provider
        # set up nodes
        self.nodes = []
        for idx in range(n_mag):
            node_name = "{0}-{1}".format(base_name, idx)
            # get base node configuration
            nd = None
            if self.provider is None:
                nd = OrderedDict()
                nd["NodeName"] = node_name
                key = generate_private_key()
                nd["SigningKey"] = key
                nd["Identifier"] = get_address_from_private_key_wif(key)
            else:
                nd = self.provider.provision_validator(node_name)
            # update basic configuration
            nd.update(overrides)
            nd["id"] = idx
            # ...networking information
            net_info = self.resolve_networking_info(host,
                                                    base_port + idx,
                                                    base_http_port + idx,
                                                    endpoint_host)
            nd.update(net_info)
            nd["Nodes"] = []
            nd["Peers"] = []
            nd["Blacklist"] = []
            # initial athourity
            nd["LedgerURL"] = []
            # aux information
            nd["Quorum"] = []
            self.nodes.append(nd)

        self.node_mat = None
        self.peer_mat = None
        self.quorum_mat = None
        self.blacklist_mat = None

    def resolve_networking_info(self, host, udp, http, endpoint):
        ret = {}
        ret['Host'] = 'localhost' if host is None else host
        ret["Port"] = udp
        ret["HttpPort"] = http
        ret['Listen'] = [
            '%s:%s/UDP gossip' % (ret['Host'], udp),
            '%s:%s/TCP http' % (ret['Host'], http),
        ]
        if endpoint is not None:
            ret['Endpoint'] = {
                "Host": endpoint,
                "Port": udp,
                "HttpPort": http,
            }
        return ret

    def set_ledger_url(self, node_index, ledger_node_indexes):
        self.nodes[node_index]['LedgerURL'] = [
            'http://%s:%s' % (nd['Host'], nd['HttpPort'])
            for (idx, nd) in enumerate(self.nodes)
            if idx in ledger_node_indexes
        ]

    def _get_gossip_info(self, idx):
        nd = self.nodes[idx]
        return {
            "NodeName": nd["NodeName"],
            "Identifier": nd["Identifier"],
            "Host": nd["Host"],
            "Port": nd["Port"],
            "HttpPort": nd["HttpPort"],
        }

    def set_nodes(self, node_mat):
        if self.node_mat is not None:
            raise Exception('validator configuration is static')
        self.node_mat = AdjacencyMatrix(self.n_mag, node_mat)
        mat = self.node_mat.get_mat()
        for (this_idx, this) in enumerate(self.nodes):
            this['Nodes'] = []
            for (other_idx, add_other) in enumerate(mat[this_idx]):
                if add_other == 1:
                    this['Nodes'].append(self._get_gossip_info(other_idx))

    def set_peers(self, peer_mat):
        if self.peer_mat is not None:
            raise Exception('validator configuration is static')
        self.peer_mat = AdjacencyMatrix(self.n_mag, peer_mat)
        mat = self.peer_mat.get_mat()
        for (nd_idx, nd) in enumerate(self.nodes):
            nd['Peers'] = []
            for (peer_idx, is_peer) in enumerate(mat[nd_idx]):
                if is_peer == 1 and peer_idx != nd_idx:
                    nd['Peers'].append(self.nodes[peer_idx]['NodeName'])

    def set_quorum(self, quorum_mat):
        if self.quorum_mat is not None:
            raise Exception('validator configuration is static')
        self.quorum_mat = AdjacencyMatrix(self.n_mag, quorum_mat)
        mat = self.quorum_mat.get_mat()
        for (nd_idx, nd) in enumerate(self.nodes):
            nd['Quorum'] = []
            for (quorum_idx, in_quorum) in enumerate(mat[nd_idx]):
                if in_quorum == 1:
                    nd['Quorum'].append(self.nodes[quorum_idx]['NodeName'])

    def set_blacklist(self, blacklist_mat=None):
        if self.blacklist_mat is not None:
            raise Exception('validator configuration is static')
        if blacklist_mat is None:
            assert self.peer_mat is not None
            blacklist_mat = self.peer_mat.negate()
        self.blacklist_mat = AdjacencyMatrix(self.n_mag, blacklist_mat)
        mat = self.blacklist_mat.get_mat()
        for (nd_idx, nd) in enumerate(self.nodes):
            nd['Blacklist'] = []
            for (exclude_idx, is_exclude) in enumerate(mat[nd_idx]):
                if is_exclude == 1:
                    exclude = self._get_gossip_info(exclude_idx)
                    nd['Blacklist'].append(exclude['Identifier'])

    def get_node_cfg(self, idx):
        ret = self.nodes[idx].copy()
        return ret

    def set_node_cfg(self, idx, cfg):
        self.nodes[idx] = cfg.copy()

    def write_node_cfg(self, idx, file_name=None):
        cfg = self.get_node_cfg(idx)
        if file_name is None:
            dir = cfg['ConfigDirectory']
            file_name = cfg['NodeName'] + '.json'
            file_name = os.path.join(dir, file_name)
        with open(file_name, 'w') as f:
            f.write(json.dumps(cfg, indent=4) + '\n')
        return file_name

    def get_config_list(self):
        return [self.get_node_cfg(i) for i in range(self.n_mag)]

    def print_config_list(self):
        val = self.get_config_list()
        print json.dumps(val, indent=4)
class NetworkConfig(object):
    def __init__(
        self,
        cfg,
        n_mag,
        use_genesis=True,
        base_host=None,
        base_name='validator',
        base_port=9000,
        base_http_port=8800,
    ):
        self.n_mag = n_mag
        self.use_genesis = use_genesis
        self.keys = [generate_private_key() for _ in range(n_mag)]
        self.nodes = []
        for (idx, wif) in enumerate(self.keys):
            nd = OrderedDict()
            nd.update(cfg)
            nd["id"] = idx
            nd["NodeName"] = "{0}-{1}".format(base_name, idx)
            nd["Identifier"] = get_address_from_private_key_wif(wif)
            nd['Host'] = "localhost"
            if base_host is not None:
                nd['Host'] = "%s-%s" % (base_host, idx)
            nd["Port"] = base_port + idx
            nd["HttpPort"] = base_http_port + idx
            nd["Nodes"] = []
            nd["Peers"] = []
            nd["Quorum"] = []
            nd['Listen'] = [
                '%s:%s/UDP gossip' % (nd['Host'], nd['Port']),
                '%s:%s/TCP http' % (nd['Host'], nd['HttpPort']),
            ]
            nd["LedgerURL"] = []
            nd["GenesisLedger"] = False
            if idx == 0 and use_genesis is True:
                nd["GenesisLedger"] = True
            self.nodes.append(nd)
        self.node_mat = None
        self.peer_mat = None
        self.quorum_mat = None
        self.blacklist_mat = None
        self.con_mat = AdjacencyMatrixAnimation(n_mag)

    def set_ledger_url(self, node_index, ledger_node_indexes):
        self.nodes[node_index]['LedgerURL'] = [
            'http://%s:%s' % (nd['Host'], nd['HttpPort'])
            for (idx, nd) in enumerate(self.nodes)
            if idx in ledger_node_indexes
        ]

    def _get_gossip_info(self, idx):
        nd = self.nodes[idx]
        return {
            "NodeName": nd["NodeName"],
            "Identifier": nd["Identifier"],
            "Host": nd["Host"],
            "Port": nd["Port"],
            "HttpPort": nd["HttpPort"],
        }

    def set_nodes(self, node_mat):
        if self.node_mat is not None:
            raise Exception('validator configuration is static')
        self.node_mat = AdjacencyMatrix(self.n_mag, node_mat)
        mat = self.node_mat.get_mat()
        for (this_idx, this) in enumerate(self.nodes):
            this['Nodes'] = []
            for (other_idx, add_other) in enumerate(mat[this_idx]):
                if add_other == 1:
                    this['Nodes'].append(self._get_gossip_info(other_idx))

    def set_peers(self, peer_mat):
        if self.peer_mat is not None:
            raise Exception('validator configuration is static')
        self.peer_mat = AdjacencyMatrix(self.n_mag, peer_mat)
        mat = self.peer_mat.get_mat()
        for (nd_idx, nd) in enumerate(self.nodes):
            nd['Peers'] = []
            for (peer_idx, is_peer) in enumerate(mat[nd_idx]):
                if is_peer == 1 and peer_idx != nd_idx:
                    nd['Peers'].append(self.nodes[peer_idx]['NodeName'])

    def set_quorum(self, quorum_mat):
        if self.quorum_mat is not None:
            raise Exception('validator configuration is static')
        self.quorum_mat = AdjacencyMatrix(self.n_mag, quorum_mat)
        mat = self.quorum_mat.get_mat()
        for (nd_idx, nd) in enumerate(self.nodes):
            nd['Quorum'] = []
            for (quorum_idx, in_quorum) in enumerate(mat[nd_idx]):
                if in_quorum == 1:
                    nd['Quorum'].append(self.nodes[quorum_idx]['NodeName'])

    def set_blacklist(self, blacklist_mat=None):
        if self.blacklist_mat is not None:
            raise Exception('validator configuration is static')
        if blacklist_mat is None:
            assert self.peer_mat is not None
            blacklist_mat = self.peer_mat.negate()
        self.blacklist_mat = AdjacencyMatrix(self.n_mag, blacklist_mat)
        mat = self.blacklist_mat.get_mat()
        for (nd_idx, nd) in enumerate(self.nodes):
            nd['Blacklist'] = []
            for (exclude_idx, is_exclude) in enumerate(mat[nd_idx]):
                if is_exclude == 1:
                    exclude = self._get_gossip_info(exclude_idx)
                    nd['Blacklist'].append(exclude['Identifier'])

    def get_node_cfg(self, idx):
        ret = self.nodes[idx].copy()
        ret["SigningKey"] = self.keys[idx]
        return ret

    def get_config_list(self):
        return [self.get_node_cfg(i) for i in range(self.n_mag)]

    def print_config_list(self):
        val = self.get_config_list()
        print json.dumps(val, indent=4)
示例#11
0
class NetworkConfig(object):
    def __init__(self, cfg, n_mag,
                 use_genesis=True,
                 base_host=None,
                 base_name='validator',
                 base_port=9000,
                 base_http_port=8800,
                 ):
        self.n_mag = n_mag
        self.use_genesis = use_genesis
        self.keys = [generate_private_key() for _ in range(n_mag)]
        self.nodes = []
        for (idx, wif) in enumerate(self.keys):
            nd = OrderedDict()
            nd.update(cfg)
            nd["id"] = idx
            nd["NodeName"] = "{0}-{1}".format(base_name, idx)
            nd["Identifier"] = get_address_from_private_key_wif(wif)
            nd['Host'] = "localhost"
            if base_host is not None:
                nd['Host'] = "%s-%s" % (base_host, idx)
            nd["Port"] = base_port + idx
            nd["HttpPort"] = base_http_port + idx
            nd["Nodes"] = []
            nd["Peers"] = []
            nd["Quorum"] = []
            nd['Listen'] = [
                '%s:%s/UDP gossip' % (nd['Host'], nd['Port']),
                '%s:%s/TCP http' % (nd['Host'], nd['HttpPort']),
            ]
            nd["LedgerURL"] = []
            nd["GenesisLedger"] = False
            if idx == 0 and use_genesis is True:
                nd["GenesisLedger"] = True
            self.nodes.append(nd)
        self.node_mat = None
        self.peer_mat = None
        self.quorum_mat = None
        self.blacklist_mat = None
        self.con_mat = AdjacencyMatrixAnimation(n_mag)

    def set_ledger_url(self, node_index, ledger_node_indexes):
        self.nodes[node_index]['LedgerURL'] = [
            'http://%s:%s' % (nd['Host'], nd['HttpPort'])
            for (idx, nd) in enumerate(self.nodes)
            if idx in ledger_node_indexes
        ]

    def _get_gossip_info(self, idx):
        nd = self.nodes[idx]
        return {
            "NodeName": nd["NodeName"],
            "Identifier": nd["Identifier"],
            "Host": nd["Host"],
            "Port": nd["Port"],
            "HttpPort": nd["HttpPort"],
        }

    def set_nodes(self, node_mat):
        if self.node_mat is not None:
            raise Exception('validator configuration is static')
        self.node_mat = AdjacencyMatrix(self.n_mag, node_mat)
        mat = self.node_mat.get_mat()
        for (this_idx, this) in enumerate(self.nodes):
            this['Nodes'] = []
            for (other_idx, add_other) in enumerate(mat[this_idx]):
                if add_other == 1:
                    this['Nodes'].append(self._get_gossip_info(other_idx))

    def set_peers(self, peer_mat):
        if self.peer_mat is not None:
            raise Exception('validator configuration is static')
        self.peer_mat = AdjacencyMatrix(self.n_mag, peer_mat)
        mat = self.peer_mat.get_mat()
        for (nd_idx, nd) in enumerate(self.nodes):
            nd['Peers'] = []
            for (peer_idx, is_peer) in enumerate(mat[nd_idx]):
                if is_peer == 1 and peer_idx != nd_idx:
                    nd['Peers'].append(self.nodes[peer_idx]['NodeName'])

    def set_quorum(self, quorum_mat):
        if self.quorum_mat is not None:
            raise Exception('validator configuration is static')
        self.quorum_mat = AdjacencyMatrix(self.n_mag, quorum_mat)
        mat = self.quorum_mat.get_mat()
        for (nd_idx, nd) in enumerate(self.nodes):
            nd['Quorum'] = []
            for (quorum_idx, in_quorum) in enumerate(mat[nd_idx]):
                if in_quorum == 1:
                    nd['Quorum'].append(self.nodes[quorum_idx]['NodeName'])

    def set_blacklist(self, blacklist_mat=None):
        if self.blacklist_mat is not None:
            raise Exception('validator configuration is static')
        if blacklist_mat is None:
            assert self.peer_mat is not None
            blacklist_mat = self.peer_mat.negate()
        self.blacklist_mat = AdjacencyMatrix(self.n_mag, blacklist_mat)
        mat = self.blacklist_mat.get_mat()
        for (nd_idx, nd) in enumerate(self.nodes):
            nd['Blacklist'] = []
            for (exclude_idx, is_exclude) in enumerate(mat[nd_idx]):
                if is_exclude == 1:
                    exclude = self._get_gossip_info(exclude_idx)
                    nd['Blacklist'].append(exclude['Identifier'])

    def get_node_cfg(self, idx):
        ret = self.nodes[idx].copy()
        ret["SigningKey"] = self.keys[idx]
        return ret

    def get_config_list(self):
        return [self.get_node_cfg(i) for i in range(self.n_mag)]

    def print_config_list(self):
        val = self.get_config_list()
        print json.dumps(val, indent=4)
示例#12
0
class NetworkConfig(object):
    @staticmethod
    def from_config_list(config_list):
        '''
        Creates a NetworkConfig from an existing list of config files by
        calling the constructor and then replacing the nodes
        Args:
            config_list: (list<dict>)
        Returns:
            net_cfg: (NetworkConfig)

        '''
        net_cfg = NetworkConfig({}, len(config_list))
        net_cfg.nodes = config_list
        return net_cfg

    def __init__(self,
                 n_mag,
                 overrides=None,
                 base_name='validator',
                 base_port=None,
                 base_http_port=None,
                 host=None,
                 endpoint_host=None,
                 provider=None):
        overrides = {} if overrides is None else overrides
        base_port = 9000 if base_port is None else base_port
        base_http_port = 8800 if base_http_port is None else base_http_port
        self.n_mag = n_mag
        self.provider = None
        if provider is not None:
            self.provider = provider
        # set up nodes
        self.nodes = []
        for idx in range(n_mag):
            node_name = "{0}-{1}".format(base_name, idx)
            # get base node configuration
            nd = None
            if self.provider is None:
                nd = OrderedDict()
                nd["NodeName"] = node_name
                key = generate_private_key()
                nd["SigningKey"] = key
                nd["Identifier"] = get_address_from_private_key_wif(key)
            else:
                nd = self.provider.provision_validator(node_name)
            # update basic configuration
            nd.update(overrides)
            nd["id"] = idx
            # ...networking information
            net_info = self.resolve_networking_info(host,
                                                    base_port + idx,
                                                    base_http_port + idx,
                                                    endpoint_host)
            nd.update(net_info)
            nd["Nodes"] = []
            nd["Peers"] = []
            nd["Blacklist"] = []
            # initial athourity
            nd["LedgerURL"] = []
            # aux information
            self.nodes.append(nd)

        self.node_mat = None
        self.peer_mat = None
        self.blacklist_mat = None

    def resolve_networking_info(self, host, udp, http, endpoint):
        ret = {}
        ret['Host'] = 'localhost' if host is None else host
        ret["Port"] = udp
        ret["HttpPort"] = http
        ret['Listen'] = [
            '%s:%s/UDP gossip' % (ret['Host'], udp),
            '%s:%s/TCP http' % (ret['Host'], http),
        ]
        if endpoint is not None:
            ret['Endpoint'] = {
                "Host": endpoint,
                "Port": udp,
                "HttpPort": http,
            }
        return ret

    def set_ledger_url(self, node_index, ledger_node_indexes):
        self.nodes[node_index]['LedgerURL'] = [
            'http://%s:%s' % (nd['Host'], nd['HttpPort'])
            for (idx, nd) in enumerate(self.nodes)
            if idx in ledger_node_indexes
        ]

    def _get_gossip_info(self, idx):
        nd = self.nodes[idx]
        return {
            "NodeName": nd["NodeName"],
            "Identifier": nd["Identifier"],
            "Host": nd["Host"],
            "Port": nd["Port"],
            "HttpPort": nd["HttpPort"],
        }

    def set_nodes(self, node_mat):
        if self.node_mat is not None:
            raise Exception('validator configuration is static')
        self.node_mat = AdjacencyMatrix(self.n_mag, node_mat)
        mat = self.node_mat.get_mat()
        for (this_idx, this) in enumerate(self.nodes):
            this['Nodes'] = []
            for (other_idx, add_other) in enumerate(mat[this_idx]):
                if add_other == 1:
                    this['Nodes'].append(self._get_gossip_info(other_idx))

    def set_peers(self, peer_mat):
        if self.peer_mat is not None:
            raise Exception('validator configuration is static')
        self.peer_mat = AdjacencyMatrix(self.n_mag, peer_mat)
        mat = self.peer_mat.get_mat()
        for (nd_idx, nd) in enumerate(self.nodes):
            nd['Peers'] = []
            for (peer_idx, is_peer) in enumerate(mat[nd_idx]):
                if is_peer == 1 and peer_idx != nd_idx:
                    nd['Peers'].append(self.nodes[peer_idx]['NodeName'])

    def set_blacklist(self, blacklist_mat=None):
        if self.blacklist_mat is not None:
            raise Exception('validator configuration is static')
        if blacklist_mat is None:
            assert self.peer_mat is not None
            blacklist_mat = self.peer_mat.negate()
        self.blacklist_mat = AdjacencyMatrix(self.n_mag, blacklist_mat)
        mat = self.blacklist_mat.get_mat()
        for (nd_idx, nd) in enumerate(self.nodes):
            nd['Blacklist'] = []
            for (exclude_idx, is_exclude) in enumerate(mat[nd_idx]):
                if is_exclude == 1:
                    exclude = self._get_gossip_info(exclude_idx)
                    nd['Blacklist'].append(exclude['Identifier'])

    def get_node_cfg(self, idx):
        ret = self.nodes[idx].copy()
        return ret

    def set_node_cfg(self, idx, cfg):
        self.nodes[idx] = cfg.copy()

    def write_node_cfg(self, idx, file_name=None):
        cfg = self.get_node_cfg(idx)
        if file_name is None:
            dir = cfg['ConfigDirectory']
            file_name = cfg['NodeName'] + '.json'
            file_name = os.path.join(dir, file_name)
        with open(file_name, 'w') as f:
            f.write(json.dumps(cfg, indent=4) + '\n')
        return file_name

    def get_config_list(self):
        return [self.get_node_cfg(i) for i in range(self.n_mag)]

    def print_config_list(self):
        val = self.get_config_list()
        print(json.dumps(val, indent=4))