def composer_connection(opts, verbose=False): peer_namespace = get_namespace(opts, opts['peers']['msp']) ord_namespace = get_namespace(opts, opts['orderers']['msp']) # TODO: This could be a single function peer_ca = opts['peers']['ca'] peer_ca_msp = opts['cas'][peer_ca]['msp'] ingress_urls = ingress_read(peer_ca + '-hlf-ca', namespace=peer_namespace, verbose=verbose) peer_ca_url = ingress_urls[0] try: cm_read(opts['composer']['secret_connection'], peer_namespace, verbose=verbose) except ApiException: # Set up connection.json # TODO: Improve json_ct to work directly with opts structure cm_data = { 'connection.json': json_ct(opts['peers']['names'], opts['orderers']['names'], [ peer + '-hlf-peer.{ns}.svc.cluster.local'.format(ns=peer_namespace) for peer in opts['peers']['names'] ], [ orderer + '-hlf-ord.{ns}.svc.cluster.local'.format(ns=ord_namespace) for orderer in opts['orderers']['names'] ], peer_ca, peer_ca_url, 'AidTech', None, peer_ca_msp, opts['peers']['channel_name']) } cm_create(peer_namespace, opts['composer']['secret_connection'], cm_data)
def setup_nodes(opts, node_type, verbose=False): nodes = opts[node_type + 's'] msp_values = opts['msps'][nodes['msp']] node_namespace = get_namespace(opts, nodes['msp']) ca_namespace = get_namespace(opts, ca=opts['msps'][nodes['msp']]['ca']) for release in nodes['names']: # Create secret with Orderer credentials secret_name = 'hlf--{}-cred'.format(release) secret_data = credentials_secret(secret_name, node_namespace, username=release, verbose=verbose) # Register node register_node(ca_namespace, msp_values['ca'], node_type, secret_data['CA_USERNAME'], secret_data['CA_PASSWORD'], verbose=verbose) # Enroll node msp_path = enroll_node(opts, msp_values['ca'], secret_data['CA_USERNAME'], secret_data['CA_PASSWORD'], verbose=verbose) # Secrets id_to_secrets(namespace=node_namespace, msp_path=msp_path, user=release, verbose=verbose)
def setup_id(opts, msp_name, release, id_type, verbose=False): """Setup single ID by registering, enrolling, and saving ID to K8S secrets. Args: opts (dict): Nephos options dict. msp_name (str): Name of Membership Service Provider. release (str): Name of release/node. id_type (str): Type of ID we use. verbose (bool) Verbosity. False by default. """ msp_values = opts["msps"][msp_name] node_namespace = get_namespace(opts, msp_name) if opts["cas"]: ca_namespace = get_namespace(opts, ca=opts["msps"][msp_name]["ca"]) # Create secret with Orderer credentials secret_name = "hlf--{}-cred".format(release) secret_data = credentials_secret( secret_name, node_namespace, username=release, verbose=verbose ) # Register node register_id( ca_namespace, msp_values["ca"], secret_data["CA_USERNAME"], secret_data["CA_PASSWORD"], id_type, verbose=verbose, ) # Enroll node msp_path = enroll_id( opts, msp_values["ca"], secret_data["CA_USERNAME"], secret_data["CA_PASSWORD"], verbose=verbose, ) else: # Otherwise we are using Cryptogen glob_target = "{dir_crypto}/crypto-config/{node_type}Organizations/{ns}*/{node_type}s/{node_name}*/msp".format( dir_crypto=opts["core"]["dir_crypto"], node_type=id_type, node_name=release, ns=node_namespace, ) msp_path_list = glob(glob_target) if len(msp_path_list) == 1: msp_path = msp_path_list[0] else: raise ValueError( "MSP path list length is {} - {}".format( len(msp_path_list), msp_path_list ) ) # Secrets id_to_secrets( namespace=node_namespace, msp_path=msp_path, username=release, verbose=verbose )
def setup_ord(opts, upgrade=False): """Setup Orderer on K8S. Args: opts (dict): Nephos options dict. upgrade (bool): Do we upgrade the deployment? False by default. """ # Kafka if "kafka" in opts["ordering"]: # Kafka upgrade is risky, so we disallow it by default version = get_version(opts, "kafka") kafka_config = get_kafka_configs(opts=opts) ord_namespace = get_namespace(opts, msp=kafka_config["msp"]) config_yaml = f"{opts['core']['dir_values']}/{kafka_config['msp']}/kafka/{kafka_config['name']}.yaml" extra_vars = helm_extra_vars(version=version, config_yaml=config_yaml) helm_install( "incubator", "kafka", kafka_config["name"], ord_namespace, extra_vars=extra_vars, ) helm_check( "kafka", kafka_config["name"], ord_namespace, pod_num=kafka_config["pod_num"], ) for msp in get_msps(opts=opts): if not is_orderer_msp(opts=opts, msp=msp): continue ord_namespace = get_namespace(opts, msp=msp) version = get_version(opts, "hlf-ord") for release in get_orderers(opts=opts, msp=msp): # HL-Ord config_yaml = f'{opts["core"]["dir_values"]}/{msp}/hlf-ord/{release}.yaml' extra_vars = helm_extra_vars(version=version, config_yaml=config_yaml) if not upgrade: helm_install( opts["core"]["chart_repo"], "hlf-ord", release, ord_namespace, extra_vars=extra_vars, ) else: helm_upgrade( opts["core"]["chart_repo"], "hlf-ord", release, extra_vars=extra_vars, ) helm_check("hlf-ord", release, ord_namespace) # Check that Orderer is running check_ord(ord_namespace, release)
def create_channel(opts): """Create Channel for Peer. Args: opts (dict): Nephos options dict. """ ord_msp = get_an_orderer_msp(opts=opts) ord_namespace = get_namespace(opts, msp=ord_msp) ord_name = random.choice(list(get_orderers(opts=opts, msp=ord_msp))) cmd_suffix = peer_channel_suffix(opts, ord_msp, ord_name) for msp in get_msps(opts=opts): peer_namespace = get_namespace(opts, msp=msp) for channel in get_channels(opts=opts): channel_name = opts["channels"][channel]["channel_name"] secret_channel = opts["channels"][channel]["secret_channel"] if msp not in opts["channels"][channel]["msps"]: continue for index, release in enumerate(get_peers(opts=opts, msp=msp)): # Get peer pod pod_ex = get_helm_pod(peer_namespace, release, "hlf-peer") # Check if the file exists has_channel = False while not has_channel: has_channel = get_channel_block( pod_ex, ord_name, ord_namespace, channel_name, cmd_suffix ) if not has_channel: pod_ex.execute( ( "bash -c 'peer channel create " + f"-o {ord_name}-hlf-ord.{ord_namespace}.svc.cluster.local:7050 " + f"-c {channel_name} -f /hl_config/channel/{secret_channel}/{channel_name}.tx {cmd_suffix}'" ) ) res, _ = pod_ex.execute("peer channel list") channels = (res.split("Channels peers has joined: ")[1]).split() if channel_name not in channels: pod_ex.execute( ( "bash -c " + "'CORE_PEER_MSPCONFIGPATH=$ADMIN_MSP_PATH " + f"peer channel join -b /var/hyperledger/{channel_name}.block {cmd_suffix}'" ) )
def create_channel(opts, verbose=False): """Create Channel for Peer. Args: opts (dict): Nephos options dict. verbose (bool): Verbosity. False by default. """ peer_namespace = get_namespace(opts, opts["peers"]["msp"]) ord_namespace = get_namespace(opts, opts["orderers"]["msp"]) channel = opts["peers"]["channel_name"] # Get orderer TLS status ord_name = random.choice(opts["orderers"]["names"]) # TODO: This should be a function cmd_suffix = peer_channel_suffix(opts, ord_name, verbose=verbose) for index, release in enumerate(opts["peers"]["names"]): # Get peer pod pod_ex = get_pod(peer_namespace, release, "hlf-peer", verbose=verbose) # Check if the file exists has_channel = False while not has_channel: has_channel = get_channel_block( pod_ex, ord_name, ord_namespace, channel, cmd_suffix ) if not has_channel: pod_ex.execute( ( "bash -c 'peer channel create " + "-o {orderer}-hlf-ord.{ns}.svc.cluster.local:7050 " + "-c {channel} -f /hl_config/channel/{channel}.tx {cmd_suffix}'" ).format( orderer=ord_name, ns=ord_namespace, channel=opts["peers"]["channel_name"], cmd_suffix=cmd_suffix, ) ) res, _ = pod_ex.execute("peer channel list") channels = (res.split("Channels peers has joined: ")[1]).split() if opts["peers"]["channel_name"] not in channels: pod_ex.execute( ( "bash -c " + "'CORE_PEER_MSPCONFIGPATH=$ADMIN_MSP_PATH " + "peer channel join -b /var/hyperledger/{channel}.block {cmd_suffix}'" ).format(channel=opts["peers"]["channel_name"], cmd_suffix=cmd_suffix) )
def enroll_id(opts, ca, username, password): """Enroll an ID with a Fabric Certificate Authority Args: opts (dict): Nephos options dict. ca (str): K8S release name of CA. username (str): Username for identity. password (str): Password for identity. Returns: str: Path of the MSP directory where cryptographic data is saved. """ dir_crypto = opts["core"]["dir_crypto"] ca_namespace = get_namespace(opts, ca=ca) ingress_urls = ingress_read(ca + "-hlf-ca", namespace=ca_namespace) msp_dir = f"{username}_MSP" msp_path = join(dir_crypto, msp_dir) if not isdir(msp_path): # Enroll command = ( f'FABRIC_CA_CLIENT_HOME={dir_crypto} fabric-ca-client enroll ' + f'-u https://{username}:{password}@{ingress_urls[0]} -M {join(dir_crypto, msp_dir)} ' + f'--tls.certfiles {abspath(opts["cas"][ca]["tls_cert"])}') execute_until_success(command) return msp_path
def setup_card(opts, msp_path, user_name, roles, network=None, verbose=False): """Setup the Card for Hyperledger Composer. Args: opts (dict): Nephos options dict. msp_path (str): Path to the MSP on the Composer CLI. user_name (str): Name of user for identity card. network (str): Name of network for identity card. roles (Iterable): Roles to assign to identity card. verbose (bool): Verbosity. False by default. """ peer_namespace = get_namespace(opts, opts["peers"]["msp"]) hlc_cli_ex = get_helm_pod(peer_namespace, opts["composer"]["name"], "hl-composer") # Set up the PeerAdmin card ls_res, _ = hlc_cli_ex.execute( f"composer card list --card {user_name}@{network}") if roles: roles_string = "-r " + " -r ".join(roles) + " " else: roles_string = "" if not ls_res: hlc_cli_ex.execute( ("composer card create " + (f"-n {network} " if network else "") + "-p /hl_config/hlc-connection/connection.json " + f"-u {user_name} -c {msp_path}/signcerts/cert.pem " + f"-k {msp_path}/keystore/key.pem " + f"{roles_string}" + f"--file /home/composer/{user_name}@{network}")) hlc_cli_ex.execute("composer card import " + f"--file /home/composer/{user_name}@{network}.card")
def extract_crypto(opts, node_type, verbose=False): # Get chart type chart = NODE_MAPPER[node_type] node_namespace = get_namespace(opts, opts[node_type + 's']['msp']) for release in opts[node_type + 's']['names']: pod_ex = get_pod(node_namespace, release, chart) # Secrets crypto_info = [ CryptoInfo('idcert', 'signcerts', 'cert.pem', True), CryptoInfo('idkey', 'keystore', 'key.pem', True), CryptoInfo('cacert', 'cacerts', 'cacert.pem', True), CryptoInfo('caintcert', 'intermediatecerts', 'intermediatecacert.pem', False) ] for item in crypto_info: secret_name = 'hlf--{}-{}'.format(release, item.secret_type) try: secret_read(secret_name, node_namespace) if verbose: print('{} secret already exists'.format(secret_name)) except ApiException: command = "bash -c 'ls /var/hyperledger/msp/{}' | wc -l".format(item.subfolder) file_num = pod_ex.execute(command) if file_num.strip() != '1': if item.required: raise ValueError('We should only have 1 file in each of these folders') else: print('Wrong number of files in {} directory'.format(item.subfolder)) else: command = "bash -c 'cat /var/hyperledger/msp/{}/*'".format(item.subfolder) content = pod_ex.execute(command) secret_data = { item.key: content } secret_create(secret_data, secret_name, node_namespace, verbose=verbose)
def channel_tx(opts, verbose=False): """Create and save Channel Transaction to K8S. Args: opts (dict): Nephos options dict. verbose (bool) Verbosity. False by default. """ peer_namespace = get_namespace(opts, opts["peers"]["msp"]) # Change to blockchain materials directory chdir(opts["core"]["dir_config"]) # Create Channel Tx channel_key = "{channel}.tx".format(channel=opts["peers"]["channel_name"]) channel_file = join(opts["core"]["dir_crypto"], channel_key) if not exists(channel_file): # Channel transaction creation and storage execute( "configtxgen -profile {channel_profile} -channelID {channel} -outputCreateChannelTx {channel_file}".format( channel_profile=opts["peers"]["channel_profile"], channel=opts["peers"]["channel_name"], channel_file=channel_file, ), verbose=verbose, ) else: print("{} already exists".format(channel_file)) # Create the channel transaction secret secret_from_file( secret=opts["peers"]["secret_channel"], namespace=peer_namespace, key=channel_key, filename=channel_file, verbose=verbose, ) # Return to original directory chdir(PWD)
def composer_connection(opts, verbose=False): """Composer connection setup. This creates a ConfigMap on K8S with the Hyperledger Composer connection. Args: opts (dict): Nephos options dict. verbose (bool): Verbosity. False by default. """ peer_namespace = get_namespace(opts, opts["peers"]["msp"]) # TODO: This could be a single function peer_msp = opts["peers"]["msp"] peer_ca = opts["msps"][peer_msp]["ca"] ca_namespace = opts["cas"][peer_ca]["namespace"] ingress_urls = ingress_read(peer_ca + "-hlf-ca", namespace=ca_namespace) peer_ca_url = ingress_urls[0] try: cm_read(opts["composer"]["secret_connection"], peer_namespace) except ApiException: # Set up connection.json # TODO: Improve json_ct to work entirely with opts structure cm_data = { "connection.json": json_ct( opts, peer_ca, peer_ca_url, "AidTech", None, peer_msp, opts["peers"]["channel_name"], ) } cm_create(cm_data, opts["composer"]["secret_connection"], peer_namespace)
def setup_ca(opts, upgrade=False, verbose=False): for ca_name, ca_values in opts['cas'].items(): ca_namespace = get_namespace(opts, ca=ca_name) # Install Charts ca_chart(opts=opts, release=ca_name, upgrade=upgrade, verbose=verbose) # Obtain CA pod and Enroll pod_exec = get_pod(namespace=ca_namespace, release=ca_name, app='hlf-ca', verbose=verbose) ca_enroll(pod_exec) # Get CA Ingress and check it is running try: # Get ingress of CA ingress_urls = ingress_read(ca_name + '-hlf-ca', namespace=ca_namespace, verbose=verbose) except ApiException: print('No ingress found for CA') continue # Check the CA is running check_ca(ingress_host=ingress_urls[0], verbose=verbose)
def msp_secrets(opts, msp_name): """Process MSP and convert it to a set of secrets. Args: opts (dict): Nephos options dict. msp_name (str): Name of Membership Service Provider. """ # Relevant variables msp_namespace = get_namespace(opts, msp=msp_name) msp_values = opts["msps"][msp_name] if opts["cas"]: # If we have a CA, MSP was saved to dir_crypto msp_path = join(opts["core"]["dir_crypto"], msp_name) else: # Otherwise we are using Cryptogen glob_target = f"{opts['core']['dir_crypto']}/crypto-config/*Organizations/{msp_namespace}*/users/Admin*/msp" msp_path_list = glob(glob_target) if len(msp_path_list) == 1: msp_path = msp_path_list[0] else: raise ValueError( f"MSP path list length is {msp_path_list} - {msp_path_list}") # Copy cert to admincerts copy_secret(join(msp_path, "signcerts"), join(msp_path, "admincerts")) # Create ID secrets from Admin MSP id_to_secrets(msp_namespace, msp_path, msp_values["org_admin"]) # Create CA secrets from Admin MSP cacerts_to_secrets(msp_namespace, msp_path, msp_values["org_admin"])
def channel_tx(opts, verbose=False): peer_namespace = get_namespace(opts, opts['peers']['msp']) # Change to blockchain materials directory chdir(opts['core']['dir_config']) # Create Channel Tx channel_file = '{channel}.tx'.format(channel=opts['peers']['channel_name']) if not path.exists(channel_file): # Channel transaction creation and storage execute( 'configtxgen -profile {channel_profile} -channelID {channel} -outputCreateChannelTx {channel_file}' .format(channel_profile=opts['peers']['channel_profile'], channel=opts['peers']['channel_name'], channel_file=channel_file), verbose=verbose) else: print('{channel}.tx already exists'.format( channel=opts['peers']['channel_name'])) # Create the channel transaction secret secret_from_file(secret=opts['peers']['secret_channel'], namespace=peer_namespace, key=channel_file, filename=channel_file, verbose=verbose) # Return to original directory chdir(PWD)
def upgrade_network(opts, verbose=False): # Set up the PeerAdmin card hlc_cli_ex = get_pod(get_namespace(opts, opts['peers']['msp']), 'hlc', 'hl-composer', verbose=verbose) bna = hlc_cli_ex.execute('ls /hl_config/blockchain_network') bna_name, bna_rem = bna.split('_') bna_version, _ = bna_rem.split('.bna') peer_ca = opts['peers']['ca'] bna_admin = opts['cas'][peer_ca]['org-admin'] res = hlc_cli_ex.execute('composer network ping --card {bna_admin}@{bna_name}'.format( bna_admin=bna_admin, bna_name=bna_name)) curr_version = (res.split('Business network version: ')[1]).split()[0] print(curr_version) if curr_version != bna_version: hlc_cli_ex.execute( ('composer network install --card PeerAdmin@hlfv1 ' + '--archiveFile /hl_config/blockchain_network/{bna}').format(bna=bna)) hlc_cli_ex.execute( ('composer network upgrade ' + '--card PeerAdmin@hlfv1 ' + '--networkName {bna_name} --networkVersion {bna_version}').format( bna_name=bna_name, bna_version=bna_version ))
def setup_ord(opts, upgrade=False, verbose=False): ord_namespace = get_namespace(opts, opts['orderers']['msp']) # Kafka if 'kafka' in opts['orderers']: # Kafka upgrade is risky, so we disallow it by default helm_install('incubator', 'kafka', 'kafka-hlf', ord_namespace, config_yaml='{dir}/kafka/kafka-hlf.yaml'.format( dir=opts['core']['dir_values']), pod_num=opts['orderers']['kafka']['pod_num'], verbose=verbose) for release in opts['orderers']['names']: # HL-Ord if not upgrade: helm_install(opts['core']['chart_repo'], 'hlf-ord', release, ord_namespace, config_yaml='{dir}/hlf-ord/{name}.yaml'.format( dir=opts['core']['dir_values'], name=release), verbose=verbose) else: helm_upgrade(opts['core']['chart_repo'], 'hlf-ord', release, ord_namespace, config_yaml='{dir}/hlf-ord/{name}.yaml'.format( dir=opts['core']['dir_values'], name=release), verbose=verbose) # Check that Orderer is running check_ord(ord_namespace, release, verbose=verbose)
def msp_secrets(opts, msp_name, verbose=False): # Relevant variables msp_namespace = get_namespace(opts, msp=msp_name) msp_values = opts['msps'][msp_name] msp_path = path.join(opts['core']['dir_config'], msp_name) # Copy cert to admincerts signcert = path.join(msp_path, 'signcerts', 'cert.pem') admincert = path.join(msp_path, 'admincerts', 'cert.pem') if not path.isfile(admincert): admin_dir = path.split(admincert)[0] if not path.isdir(admin_dir): makedirs(admin_dir) shutil.copy(signcert, admincert) # Create ID secrets from Admin MSP id_to_secrets(msp_namespace, msp_path, msp_values['org_admin'], verbose=verbose) # Create CA secrets from Admin MSP cacerts_to_secrets(msp_namespace, msp_path, msp_values['org_admin'], verbose=verbose)
def setup_ca(opts, upgrade=False): """Setup CA. Setup involves enrolling the CA admin, checking the Ingress is responsive. Args: opts (dict): Nephos options dict. upgrade (bool): Do we upgrade the deployment? False by default. """ for ca_name, ca_values in opts["cas"].items(): ca_namespace = get_namespace(opts, ca=ca_name) # Install Charts ca_chart(opts=opts, release=ca_name, upgrade=upgrade) # Obtain CA pod and Enroll pod_exec = get_helm_pod(namespace=ca_namespace, release=ca_name, app="hlf-ca") ca_enroll(pod_exec) # Get CA Ingress and check it is running try: # Get ingress of CA ingress_urls = ingress_read(ca_name + "-hlf-ca", namespace=ca_namespace) except ApiException: logging.warning("No ingress found for CA") continue # Check the CA is running check_ca(ingress_host=ingress_urls[0], cacert=ca_values.get("tls_cert"))
def enroll_id(opts, ca, username, password, verbose=False): """Enroll an ID with a Fabric Certificate Authority Args: opts (dict): Nephos options dict. ca (str): K8S release name of CA. username (str): Username for identity. password (str): Password for identity. verbose (bool) Verbosity. False by default. Returns: str: Path of the MSP directory where cryptographic data is saved. """ dir_crypto = opts["core"]["dir_crypto"] ca_namespace = get_namespace(opts, ca=ca) ingress_urls = ingress_read(ca + "-hlf-ca", namespace=ca_namespace, verbose=verbose) msp_dir = "{}_MSP".format(username) msp_path = join(dir_crypto, msp_dir) if not isdir(msp_path): # Enroll command = ("FABRIC_CA_CLIENT_HOME={dir} fabric-ca-client enroll " + "-u https://{username}:{password}@{ingress} -M {msp_dir} " + "--tls.certfiles {ca_server_tls}").format( dir=dir_crypto, username=username, password=password, ingress=ingress_urls[0], msp_dir=join(dir_crypto, msp_dir), ca_server_tls=abspath(opts["cas"][ca]["tls_cert"]), ) execute_until_success(command) return msp_path
def genesis_block(opts, verbose=False): """Create and save Genesis Block to K8S. Args: opts (dict): Nephos options dict. verbose (bool) Verbosity. False by default. """ ord_namespace = get_namespace(opts, opts["orderers"]["msp"]) # Change to blockchain materials directory chdir(opts["core"]["dir_config"]) # Create the genesis block genesis_key = "genesis.block" genesis_file = join(opts["core"]["dir_crypto"], genesis_key) if not exists(genesis_file): # Genesis block creation and storage execute( "configtxgen -profile OrdererGenesis -outputBlock {genesis_file}". format(genesis_file=genesis_file), verbose=verbose, ) else: print("{} already exists".format(genesis_file)) # Create the genesis block secret secret_from_file( secret=opts["orderers"]["secret_genesis"], namespace=ord_namespace, key=genesis_key, filename=genesis_file, verbose=verbose, ) # Return to original directory chdir(PWD)
def deploy_composer(opts, upgrade=False, verbose=False): """Deploy Hyperledger Composer on K8S. We use the hl-composer Helm chart as a basis to deploying Composer on K8S. Please note that Composer is unmaintained and may eventually be deprecated from this repository as we migrate to raw Fabric. Args: opts (dict): Nephos options dict. upgrade (bool): Do we upgrade the deployment? False by default. verbose (bool): Verbosity. False by default. """ peer_namespace = get_namespace(opts, opts["peers"]["msp"]) # Ensure BNA exists secret_from_file( secret=opts["composer"]["secret_bna"], namespace=peer_namespace, verbose=verbose ) composer_connection(opts, verbose=verbose) # Start Composer if not upgrade: helm_install( opts["core"]["chart_repo"], "hl-composer", opts["composer"]["name"], peer_namespace, pod_num=3, config_yaml="{dir}/hl-composer/{release}.yaml".format( dir=opts["core"]["dir_values"], release=opts["composer"]["name"] ), verbose=verbose, ) else: # TODO: Implement upgrade: set $CA_USERNAME and $CA_PASSWORD pass
def setup_admin(opts, verbose=False): """Setup the Peer Admin for Hyperledger Composer. Args: opts (dict): Nephos options dict. verbose (bool): Verbosity. False by default. """ peer_namespace = get_namespace(opts, opts["peers"]["msp"]) hlc_cli_ex = get_pod(peer_namespace, opts["composer"]["name"], "hl-composer", verbose=verbose) # Set up the PeerAdmin card ls_res, _ = hlc_cli_ex.execute("composer card list --card PeerAdmin@hlfv1") if not ls_res: hlc_cli_ex.execute( ("composer card create " + "-p /hl_config/hlc-connection/connection.json " + "-u PeerAdmin -c /hl_config/admin/signcerts/cert.pem " + "-k /hl_config/admin/keystore/key.pem " + " -r PeerAdmin -r ChannelAdmin " + "--file /home/composer/PeerAdmin@hlfv1")) hlc_cli_ex.execute("composer card import " + "--file /home/composer/[email protected]")
def install_network(opts, verbose=False): """Install Hyperledger Composer network. Args: opts (dict): Nephos options dict. verbose (bool): Verbosity. False by default. """ peer_namespace = get_namespace(opts, opts["peers"]["msp"]) hlc_cli_ex = get_pod( peer_namespace, opts["composer"]["name"], "hl-composer", verbose=verbose ) # Install network # TODO: Getting BNA could be a helper function bna, _ = hlc_cli_ex.execute("ls /hl_config/blockchain_network") bna_name, bna_rem = bna.split("_") bna_version, _ = bna_rem.split(".bna") # TODO: This could be a single function peer_msp = opts["peers"]["msp"] bna_admin = opts["msps"][peer_msp]["org_admin"] admin_creds(opts, peer_msp, verbose=verbose) bna_pw = opts["msps"][peer_msp]["org_adminpw"] ls_res, _ = hlc_cli_ex.execute( "composer card list --card {bna_admin}@{bna_name}".format( bna_admin=bna_admin, bna_name=bna_name ) ) if not ls_res: hlc_cli_ex.execute( ( "composer network install --card PeerAdmin@hlfv1 " + "--archiveFile /hl_config/blockchain_network/{bna}" ).format(bna=bna) ) hlc_cli_ex.execute( ( "composer network start " + "--card PeerAdmin@hlfv1 " + "--networkName {bna_name} --networkVersion {bna_version} " + "--networkAdmin {bna_admin} --networkAdminEnrollSecret {bna_pw}" ).format( bna_name=bna_name, bna_version=bna_version, bna_admin=bna_admin, bna_pw=bna_pw, ) ) hlc_cli_ex.execute( "composer card import --file {bna_admin}@{bna_name}.card".format( bna_admin=bna_admin, bna_name=bna_name ) ) hlc_cli_ex.execute( "composer network ping --card {bna_admin}@{bna_name}".format( bna_admin=bna_admin, bna_name=bna_name ) )
def channel_tx(opts): """Create and save Channel Transaction to K8S. Args: opts (dict): Nephos options dict. """ peer_namespace = get_namespace(opts, opts["peers"]["msp"]) # Change to blockchain materials directory chdir(opts["core"]["dir_config"]) # Create Channel Tx channel_key = f"{opts['peers']['channel_name']}.tx" channel_file = join(opts["core"]["dir_crypto"], channel_key) if not exists(channel_file): # Channel transaction creation and storage execute( f"configtxgen -profile {opts['peers']['channel_profile']} -channelID {opts['peers']['channel_name']} -outputCreateChannelTx {channel_file}", ) else: logging.info(f"{channel_file} already exists") # Create the channel transaction secret secret_from_file( secret=opts["peers"]["secret_channel"], namespace=peer_namespace, key=channel_key, filename=channel_file, ) # Return to original directory chdir(PWD)
def genesis_block(opts): """Create and save Genesis Block to K8S. Args: opts (dict): Nephos options dict. """ ord_namespace = get_namespace(opts, opts["orderers"]["msp"]) # Change to blockchain materials directory chdir(opts["core"]["dir_config"]) # Create the genesis block genesis_key = "genesis.block" genesis_file = join(opts["core"]["dir_crypto"], genesis_key) if not exists(genesis_file): # Genesis block creation and storage execute( f"configtxgen -profile OrdererGenesis -outputBlock {genesis_file}", ) else: logging.info(f"{genesis_file} already exists") # Create the genesis block secret secret_from_file( secret=opts["orderers"]["secret_genesis"], namespace=ord_namespace, key=genesis_key, filename=genesis_file, ) # Return to original directory chdir(PWD)
def ca_chart(opts, release, upgrade=False, verbose=False): values_dir = opts['core']['dir_values'] repository = opts['core']['chart_repo'] ca_namespace = get_namespace(opts, ca=release) # PostgreSQL (Upgrades here are dangerous, deactivated by default) helm_install('stable', 'postgresql', '{}-pg'.format(release), ca_namespace, config_yaml='{dir}/postgres-ca/{name}-pg.yaml'.format( dir=values_dir, name=release), verbose=verbose) psql_secret = secret_read('{}-pg-postgresql'.format(release), ca_namespace, verbose=verbose) # Different key depending of PostgreSQL version psql_password = psql_secret.get( 'postgres-password') or psql_secret['postgresql-password'] env_vars = [('externalDatabase.password', psql_password)] # Fabric CA if not upgrade: helm_install(repository, 'hlf-ca', release, ca_namespace, config_yaml='{dir}/hlf-ca/{name}.yaml'.format( dir=values_dir, name=release), env_vars=env_vars, verbose=verbose) else: # TODO: Remove this try/catch once all CAs are updated try: preserve = (HelmPreserve('{}-hlf-ca'.format(release), 'CA_ADMIN', 'adminUsername'), HelmPreserve('{}-hlf-ca'.format(release), 'CA_PASSWORD', 'adminPassword')) helm_upgrade(repository, 'hlf-ca', release, ca_namespace, config_yaml='{dir}/hlf-ca/{name}.yaml'.format( dir=values_dir, name=release), env_vars=env_vars, preserve=preserve, verbose=verbose) except: preserve = (HelmPreserve('{}-hlf-ca--ca'.format(release), 'CA_ADMIN', 'adminUsername'), HelmPreserve('{}-hlf-ca--ca'.format(release), 'CA_PASSWORD', 'adminPassword')) helm_upgrade(repository, 'hlf-ca', release, ca_namespace, config_yaml='{dir}/hlf-ca/{name}.yaml'.format( dir=values_dir, name=release), env_vars=env_vars, preserve=preserve, verbose=verbose)
def setup_id(opts, msp_name, release, id_type): """Setup single ID by registering, enrolling, and saving ID to K8S secrets. Args: opts (dict): Nephos options dict. msp_name (str): Name of Membership Service Provider. release (str): Name of release/node. id_type (str): Type of ID we use. """ msp_values = opts["msps"][msp_name] node_namespace = get_namespace(opts, msp_name) if opts["cas"]: ca_namespace = get_namespace(opts, ca=opts["msps"][msp_name]["ca"]) # Create secret with Orderer credentials secret_name = f"hlf--{release}-cred" secret_data = credentials_secret(secret_name, node_namespace, username=release) # Register node register_id( ca_namespace, msp_values["ca"], secret_data["CA_USERNAME"], secret_data["CA_PASSWORD"], id_type, ) # Enroll node msp_path = enroll_id( opts, msp_values["ca"], secret_data["CA_USERNAME"], secret_data["CA_PASSWORD"], ) else: # Otherwise we are using Cryptogen glob_target = f"{opts['core']['dir_crypto']}/crypto-config/{id_type}Organizations/{node_namespace}*/{id_type}s/{release}*/msp" msp_path_list = glob(glob_target) if len(msp_path_list) == 1: msp_path = msp_path_list[0] else: raise ValueError( f"MSP path list length is {msp_path_list} - {msp_path_list}") # Secrets id_to_secrets(namespace=node_namespace, msp_path=msp_path, username=release)
def setup_ord(opts, upgrade=False, verbose=False): """Setup Orderer on K8S. Args: opts (dict): Nephos options dict. upgrade (bool): Do we upgrade the deployment? False by default. verbose (bool): Verbosity. False by default. """ ord_namespace = get_namespace(opts, opts["orderers"]["msp"]) # Kafka if "kafka" in opts["orderers"]: # Kafka upgrade is risky, so we disallow it by default version = get_version(opts, "kafka") config_yaml = "{dir}/kafka/{release}.yaml".format( dir=opts["core"]["dir_values"], release=opts["orderers"]["kafka"]["name"]) extra_vars = helm_extra_vars(version=version, config_yaml=config_yaml) helm_install( "incubator", "kafka", opts["orderers"]["kafka"]["name"], ord_namespace, extra_vars=extra_vars, verbose=verbose, ) helm_check( "kafka", opts["orderers"]["kafka"]["name"], ord_namespace, pod_num=opts["orderers"]["kafka"]["pod_num"], ) for release in opts["orderers"]["names"]: # HL-Ord version = get_version(opts, "hlf-ord") config_yaml = "{dir}/hlf-ord/{name}.yaml".format( dir=opts["core"]["dir_values"], name=release) extra_vars = helm_extra_vars(version=version, config_yaml=config_yaml) if not upgrade: helm_install( opts["core"]["chart_repo"], "hlf-ord", release, ord_namespace, extra_vars=extra_vars, verbose=verbose, ) else: helm_upgrade( opts["core"]["chart_repo"], "hlf-ord", release, extra_vars=extra_vars, verbose=verbose, ) helm_check("hlf-ord", release, ord_namespace) # Check that Orderer is running check_ord(ord_namespace, release, verbose=verbose)
def get_composer_data(opts, verbose=False): peer_namespace = get_namespace(opts, opts['peers']['msp']) composer_name = opts['composer']['name'] + '-hl-composer-rest' data = get_app_info(peer_namespace, composer_name, composer_name, secret_key='COMPOSER_APIKEY', verbose=verbose) return data
def ca_chart(opts, release, upgrade=False): """Deploy CA Helm chart to K8S. Args: opts (dict): Nephos options dict. release (str): Name of the Helm Chart release. upgrade (bool): Do we upgrade the deployment? False by default. """ values_dir = opts["core"]["dir_values"] repository = opts["core"]["chart_repo"] ca_namespace = get_namespace(opts, ca=release) # PostgreSQL (Upgrades here are dangerous, deactivated by default) # Upgrading database is risky, so we disallow it by default if not upgrade: version = get_version(opts, "postgresql") config_yaml = f"{values_dir}/postgres-ca/{release}-pg.yaml" extra_vars = helm_extra_vars(version=version, config_yaml=config_yaml) helm_install("stable", "postgresql", f"{release}-pg", ca_namespace, extra_vars=extra_vars) helm_check("postgresql", f"{release}-pg", ca_namespace) psql_secret = secret_read(f"{release}-pg-postgresql", ca_namespace) # Different key depending of PostgreSQL version psql_password = (psql_secret.get("postgres-password") or psql_secret["postgresql-password"]) # Fabric CA version = get_version(opts, "hlf-ca") env_vars = [("externalDatabase.password", psql_password)] config_yaml = f"{values_dir}/hlf-ca/{release}.yaml" if not upgrade: extra_vars = helm_extra_vars(version=version, config_yaml=config_yaml, env_vars=env_vars) helm_install(repository, "hlf-ca", release, ca_namespace, extra_vars=extra_vars) else: preserve = ( HelmPreserve(ca_namespace, f"{release}-hlf-ca--ca", "CA_ADMIN", "adminUsername"), HelmPreserve(ca_namespace, f"{release}-hlf-ca--ca", "CA_PASSWORD", "adminPassword"), ) extra_vars = helm_extra_vars( version=version, config_yaml=config_yaml, env_vars=env_vars, preserve=preserve, ) helm_upgrade(repository, "hlf-ca", release, extra_vars=extra_vars) helm_check("hlf-ca", release, ca_namespace)