Start config generation
parent
47c185538b
commit
7875441ad4
|
@ -0,0 +1,241 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
# Generate Hyperledger Fabric Network docker-compose.yaml files
|
||||||
|
# base on input parameters
|
||||||
|
# github.com/yeasy/docker-compose
|
||||||
|
|
||||||
|
# tested with version 0.15.3
|
||||||
|
from ruamel.yaml import YAML
|
||||||
|
import argparse
|
||||||
|
import copy
|
||||||
|
import collections
|
||||||
|
|
||||||
|
DOCKER_COMPOSER_VERSION='2.0'
|
||||||
|
DEFAULT_CONFIG_FILE = 'network_config.json'
|
||||||
|
PEER_TEMPLATE_FILE = 'peer.yaml'
|
||||||
|
ORDERER_TEMPLATE_FILE = 'orderer.yaml'
|
||||||
|
RESULT_FILE = '{}orgs-{}peers-{}.yaml'
|
||||||
|
|
||||||
|
# Orderer
|
||||||
|
# consensus_mode, org_name, node_name
|
||||||
|
ORDERER_GB_VOLUME = './{}/channel-artifacts/orderer.genesis.block'
|
||||||
|
ORDERER_GB_PATH = '/var/hyperledger/orderer/orderer.genesis.block'
|
||||||
|
ORDERER_MSP_VOLUME = './{}/crypto-config/ordererOrganizations/{}/orderers/{}/msp'
|
||||||
|
ORDERER_TLS_VOLUME = './{}/crypto-config/ordererOrganizations/{}/orderers/{}/tls'
|
||||||
|
ORDERER_MSP_PATH = '/var/hyperledger/orderer/msp'
|
||||||
|
ORDERER_TLS_PATH = '/var/hyperledger/orderer/tls'
|
||||||
|
|
||||||
|
# PEER
|
||||||
|
# consensus_mode, org_name, node_name
|
||||||
|
PEER_MSP_VOLUME = './{}/crypto-config/peerOrganizations/{}/peers/{}/msp'
|
||||||
|
PEER_TLS_VOLUME = './{}/crypto-config/peerOrganizations/{}/peers/{}/tls'
|
||||||
|
PEER_MSP_PATH = '/etc/hyperledger/fabric/msp'
|
||||||
|
PEER_TLS_PATH = '/etc/hyperledger/fabric/tls'
|
||||||
|
|
||||||
|
|
||||||
|
yaml = YAML()
|
||||||
|
|
||||||
|
|
||||||
|
def list_to_dict(l, sep=':'):
|
||||||
|
"""
|
||||||
|
Convert list to dict with order
|
||||||
|
:param l: list
|
||||||
|
:param sep: separator
|
||||||
|
:return: dicted result
|
||||||
|
|
||||||
|
>>> list_to_dict(['a=1','b=2'], '=')
|
||||||
|
OrderedDict([('a', '1'), ('b', '2')])
|
||||||
|
>>> list_to_dict(['a:1','b:2'])
|
||||||
|
OrderedDict([('a', '1'), ('b', '2')])
|
||||||
|
"""
|
||||||
|
result = collections.OrderedDict()
|
||||||
|
for x in l:
|
||||||
|
k, v = x.split(sep, 2)
|
||||||
|
result[k] = v
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def dict_to_list(d, sep=':'):
|
||||||
|
"""
|
||||||
|
Convert the given dict to list
|
||||||
|
:param d: dict
|
||||||
|
:param sep: separator
|
||||||
|
:return:
|
||||||
|
|
||||||
|
|
||||||
|
>>> dict_to_list({'a': '1', 'b': '2'})
|
||||||
|
['a:1', 'b:2']
|
||||||
|
"""
|
||||||
|
result = list()
|
||||||
|
for k,v in d.items():
|
||||||
|
result.append('{}{}{}'.format(k, sep, v))
|
||||||
|
return result
|
||||||
|
|
||||||
|
def parse_args():
|
||||||
|
"""
|
||||||
|
Parse the args
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument('-f', "--config_file", help="Path to the config file",
|
||||||
|
type=str, default=DEFAULT_CONFIG_FILE)
|
||||||
|
args = parser.parse_args()
|
||||||
|
print(args.config_file)
|
||||||
|
|
||||||
|
|
||||||
|
def gen_peer(template, org_name, org_msp, node_name, consensus_mode):
|
||||||
|
"""
|
||||||
|
Generate peer for given org and name
|
||||||
|
:param template: Template to use
|
||||||
|
:param org_name: Name of org,
|
||||||
|
:param org_msp: MSP ID of the org,
|
||||||
|
:param node_name: Name of the peer
|
||||||
|
:param consensus_mode: Mode of consensus
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
node = copy.deepcopy(template)
|
||||||
|
addr = node_name # e.g., peer0.org1.example.com
|
||||||
|
node['container_name'] = addr
|
||||||
|
node['hostname'] = addr
|
||||||
|
|
||||||
|
# update environments part
|
||||||
|
environment = list_to_dict(node['environment'], '=')
|
||||||
|
environment['CORE_PEER_ID'] = addr # peer id
|
||||||
|
environment['CORE_PEER_ADDRESS'] = addr+':7051' # peer grpc port
|
||||||
|
environment['CORE_PEER_CHAINCODELISTENADDRESS'] = addr+':7052' # chaincode
|
||||||
|
environment['CORE_PEER_GOSSIP_EXTERNALENDPOINT'] = addr+':7051' # gossip
|
||||||
|
environment['CORE_PEER_LOCALMSPID'] = org_msp # org msp name
|
||||||
|
node['environment'] = dict_to_list(environment, '=')
|
||||||
|
|
||||||
|
# replace volumes part
|
||||||
|
volumes = {
|
||||||
|
PEER_MSP_VOLUME.format(consensus_mode, org_name, node_name):
|
||||||
|
PEER_MSP_PATH,
|
||||||
|
PEER_TLS_VOLUME.format(consensus_mode, org_name, node_name):
|
||||||
|
PEER_TLS_PATH,
|
||||||
|
}
|
||||||
|
node['volumes'] = dict_to_list(volumes, ':')
|
||||||
|
|
||||||
|
return node
|
||||||
|
|
||||||
|
|
||||||
|
def gen_peers(org_name='org1.example.com', org_msp='Org1MSP', num=2,
|
||||||
|
consensus_mode='solo'):
|
||||||
|
"""
|
||||||
|
Generate given num peers for Organization org_msp
|
||||||
|
:param org_name: Name of the org,
|
||||||
|
:param org_msp: MSP of the organization that peer belongs to
|
||||||
|
:param num: Number of peer nodes to generate
|
||||||
|
:param consensus_mode: Mode of consensus
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
c = yaml.load(open(PEER_TEMPLATE_FILE, 'r'))
|
||||||
|
peer = c['services']['peer']
|
||||||
|
result_peers = dict()
|
||||||
|
for i in range(num):
|
||||||
|
name = 'peer{}.{}'.format(i, org_name) # peer0.org1.example.com
|
||||||
|
result_peers[name] = gen_peer(peer, org_name, org_msp, name,
|
||||||
|
consensus_mode)
|
||||||
|
return result_peers
|
||||||
|
|
||||||
|
|
||||||
|
def gen_app_orgs(orgs=2, peers=2, consensus_mode='solo'):
|
||||||
|
"""
|
||||||
|
Generate peer orgs with given number
|
||||||
|
:param orgs: Number of app orgs to generate
|
||||||
|
:param peers: Peers number for each org
|
||||||
|
:param consensus_mode: Mode of consensus
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
services = dict()
|
||||||
|
for i in range(orgs):
|
||||||
|
org_name = 'org{}.example.com'.format(i+1) # match crypto-config.yaml
|
||||||
|
org_msp = 'Org{}MSP'.format(i+1)
|
||||||
|
services.update(gen_peers(org_name, org_msp, peers, consensus_mode))
|
||||||
|
return services
|
||||||
|
|
||||||
|
|
||||||
|
def gen_orderer(template, org_name, node_name, consensus_mode):
|
||||||
|
"""
|
||||||
|
Generate peer for given org and name
|
||||||
|
:param template: Template to use
|
||||||
|
:param org_name: Name of org,
|
||||||
|
:param org_msp: MSP ID of the org,
|
||||||
|
:param node_name: Name of the node
|
||||||
|
:param consensus_mode: Mode of consensus
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
node = copy.deepcopy(template)
|
||||||
|
addr = node_name # e.g., orderer0.orderer.example.com
|
||||||
|
node['container_name'] = addr
|
||||||
|
node['hostname'] = addr
|
||||||
|
|
||||||
|
# replace volumes part
|
||||||
|
volumes = {
|
||||||
|
ORDERER_GB_VOLUME.format(consensus_mode): ORDERER_GB_PATH,
|
||||||
|
ORDERER_MSP_VOLUME.format(consensus_mode, org_name, node_name):
|
||||||
|
ORDERER_MSP_PATH,
|
||||||
|
ORDERER_TLS_VOLUME.format(consensus_mode, org_name, node_name):
|
||||||
|
ORDERER_TLS_PATH,
|
||||||
|
}
|
||||||
|
node['volumes'] = dict_to_list(volumes, ':')
|
||||||
|
|
||||||
|
return node
|
||||||
|
|
||||||
|
|
||||||
|
def gen_orderers(org_name='orderer.example.com', num=2, consensus_mode='solo'):
|
||||||
|
"""
|
||||||
|
Generate given num peers for Organization org_msp
|
||||||
|
:param org_name: Name of the org,
|
||||||
|
:param num: Number of peer nodes to generate
|
||||||
|
:param consensus_mode: Mode of consensus
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
c = yaml.load(open(ORDERER_TEMPLATE_FILE, 'r'))
|
||||||
|
orderer = c['services']['orderer-{}'.format(consensus_mode)]
|
||||||
|
result_nodes = dict()
|
||||||
|
for i in range(num):
|
||||||
|
name = 'orderer.example.com'
|
||||||
|
#name = 'orderer{}.{}'.format(i, org_name)
|
||||||
|
result_nodes[name] = gen_orderer(orderer, org_name, name,
|
||||||
|
consensus_mode)
|
||||||
|
return result_nodes
|
||||||
|
except Exception as e:
|
||||||
|
print("Failed to gen_orderers with {}:{}".format(PEER_TEMPLATE_FILE, e))
|
||||||
|
return dict()
|
||||||
|
|
||||||
|
|
||||||
|
def gen_orderer_orgs(orderers=1, consensus_mode='solo'):
|
||||||
|
"""
|
||||||
|
Generate peer orgs with given number
|
||||||
|
:param orderers: Orderers number for each org
|
||||||
|
:param consensus_mode: Mode of consensus
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
services = dict()
|
||||||
|
org_name = 'example.com' # match crypto-config.yaml
|
||||||
|
services.update(gen_orderers(org_name, orderers, consensus_mode))
|
||||||
|
return services
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
import doctest
|
||||||
|
doctest.testmod()
|
||||||
|
|
||||||
|
parse_args()
|
||||||
|
|
||||||
|
# network topology config
|
||||||
|
app_org_num = 2
|
||||||
|
app_org_size = 2
|
||||||
|
orderer_org_size = 1
|
||||||
|
consensus_mode = 'solo'
|
||||||
|
|
||||||
|
network = dict([('version','2.0'), ('services', dict())])
|
||||||
|
network['services'].update(gen_orderer_orgs(orderer_org_size,
|
||||||
|
consensus_mode))
|
||||||
|
network['services'].update(gen_app_orgs(app_org_num, app_org_size,
|
||||||
|
consensus_mode))
|
||||||
|
|
||||||
|
with open(RESULT_FILE.format(app_org_num, app_org_num*app_org_size,
|
||||||
|
'solo'), 'w') as f:
|
||||||
|
yaml.dump(network, f)
|
|
@ -0,0 +1,36 @@
|
||||||
|
# All elements in this file should depend on the base.yaml
|
||||||
|
# Provided fabric orderer node in solo and kafka modes
|
||||||
|
|
||||||
|
version: '2' # v3 does not support 'extends' yet
|
||||||
|
|
||||||
|
services:
|
||||||
|
orderer-solo: # orderer in solo mode
|
||||||
|
extends:
|
||||||
|
file: base.yaml
|
||||||
|
service: orderer-base
|
||||||
|
container_name: orderer.example.com
|
||||||
|
hostname: orderer.example.com
|
||||||
|
expose:
|
||||||
|
- "7050"
|
||||||
|
volumes:
|
||||||
|
- ./solo/channel-artifacts/orderer.genesis.block:/var/hyperledger/orderer/orderer.genesis.block
|
||||||
|
- ./solo/crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/msp:/var/hyperledger/orderer/msp
|
||||||
|
- ./solo/crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/tls/:/var/hyperledger/orderer/tls
|
||||||
|
|
||||||
|
orderer-kafka: # orderer in kafka mode
|
||||||
|
extends:
|
||||||
|
file: base.yaml
|
||||||
|
service: orderer-base
|
||||||
|
container_name: orderer.example.com
|
||||||
|
hostname: orderer.example.com
|
||||||
|
expose:
|
||||||
|
- "7050"
|
||||||
|
environment:
|
||||||
|
# Kafka related configurations
|
||||||
|
- ORDERER_KAFKA_RETRY_SHORTINTERVAL=1s
|
||||||
|
- ORDERER_KAFKA_RETRY_SHORTTOTAL=30s
|
||||||
|
- ORDERER_KAFKA_VERBOSE=true
|
||||||
|
volumes:
|
||||||
|
- ./kafka/channel-artifacts/orderer.genesis.block:/var/hyperledger/orderer/orderer.genesis.block
|
||||||
|
- ./kafka/crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/msp:/var/hyperledger/orderer/msp
|
||||||
|
- ./kafka/crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/tls/:/var/hyperledger/orderer/tls
|
|
@ -0,0 +1,26 @@
|
||||||
|
# All elements in this file should depend on the base.yaml
|
||||||
|
# Provided fabric peer node
|
||||||
|
|
||||||
|
version: '2.0'
|
||||||
|
|
||||||
|
services:
|
||||||
|
peer: # peer node
|
||||||
|
extends:
|
||||||
|
file: base.yaml
|
||||||
|
service: peer-base
|
||||||
|
container_name: peer0.org1.example.com # will generated automatically
|
||||||
|
hostname: peer0.org1.example.com # will generated automatically
|
||||||
|
environment:
|
||||||
|
- CORE_PEER_ID=peer0.org1.example.com
|
||||||
|
- CORE_PEER_ADDRESS=peer0.org1.example.com:7051 # grpc
|
||||||
|
- CORE_PEER_CHAINCODELISTENADDRESS=peer0.org1.example.com:7052 # chaincode
|
||||||
|
- CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer0.org1.example.com:7051 # gossip
|
||||||
|
- CORE_PEER_LOCALMSPID=Org1MSP
|
||||||
|
- CORE_PEER_TLS_ENABLED=true
|
||||||
|
volumes:
|
||||||
|
- ./solo/crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/msp:/etc/hyperledger/fabric/msp
|
||||||
|
- ./solo/crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls:/etc/hyperledger/fabric/tls
|
||||||
|
expose:
|
||||||
|
- 7051
|
||||||
|
- 7052
|
||||||
|
- 7053
|
Loading…
Reference in New Issue