# Copyright [2018] [Alejandro Vicente Grabovetsky via AID:Tech]
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at#
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import random
from time import sleep
from nephos.fabric.ord import check_ord_tls
from nephos.fabric.settings import get_namespace, get_version
from nephos.fabric.utils import get_helm_pod
from nephos.helpers.helm import (
HelmPreserve,
helm_check,
helm_extra_vars,
helm_install,
helm_upgrade,
)
[docs]def check_peer(namespace, release, verbose=False):
"""Check if Peer is running.
Args:
namespace: Namespace where Peer is located.
release: Name of Peer Helm release.
verbose (bool): Verbosity. False by default.
Returns:
bool: True once Peer is correctly running.
"""
pod_exec = get_helm_pod(
namespace=namespace, release=release, app="hlf-peer", verbose=verbose
)
res = pod_exec.logs(1000)
if "Received block" in res:
return True
while True:
if "Starting peer" in res or "Sleeping" in res:
return True
else:
sleep(15)
res = pod_exec.logs(1000)
# TODO: Split CouchDB creation from Peer creation
[docs]def setup_peer(opts, upgrade=False, verbose=False):
"""Setup Peer on K8S.
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"])
for release in opts["peers"]["names"]:
# Deploy the CouchDB instances
version = get_version(opts, "hlf-couchdb")
config_yaml = "{dir}/hlf-couchdb/cdb-{name}.yaml".format(
dir=opts["core"]["dir_values"], name=release
)
if not upgrade:
extra_vars = helm_extra_vars(version=version, config_yaml=config_yaml)
helm_install(
opts["core"]["chart_repo"],
"hlf-couchdb",
"cdb-{}".format(release),
peer_namespace,
extra_vars=extra_vars,
verbose=verbose,
)
else:
preserve = (
HelmPreserve(
peer_namespace,
"cdb-{}-hlf-couchdb".format(release),
"COUCHDB_USERNAME",
"couchdbUsername",
),
HelmPreserve(
peer_namespace,
"cdb-{}-hlf-couchdb".format(release),
"COUCHDB_PASSWORD",
"couchdbPassword",
),
)
extra_vars = helm_extra_vars(
version=version, config_yaml=config_yaml, preserve=preserve
)
helm_upgrade(
opts["core"]["chart_repo"],
"hlf-couchdb",
"cdb-{}".format(release),
extra_vars=extra_vars,
verbose=verbose,
)
helm_check("hlf-couchdb", "cdb-{}".format(release), peer_namespace)
# Deploy the HL-Peer charts
version = get_version(opts, "hlf-peer")
config_yaml = "{dir}/hlf-peer/{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-peer",
release,
peer_namespace,
extra_vars=extra_vars,
verbose=verbose,
)
else:
helm_upgrade(
opts["core"]["chart_repo"],
"hlf-peer",
release,
extra_vars=extra_vars,
verbose=verbose,
)
helm_check("hlf-peer", release, peer_namespace)
# Check that peer is running
check_peer(peer_namespace, release, verbose=verbose)
[docs]def peer_channel_suffix(opts, ord_name, verbose=False):
"""Get command suffix for "peer channel" commands, as they involve speaking with Orderer.
Args:
opts (dict): Nephos options dict.
ord_name (str): Orderer we wish to speak to.
verbose (bool): Verbosity. False by default.
Returns:
str: Command suffix we need to use in "peer channel" commands.
"""
ord_tls = check_ord_tls(opts, verbose=verbose)
if ord_tls:
cmd_suffix = (
"--tls "
+ "--ordererTLSHostnameOverride {orderer}-hlf-ord "
+ "--cafile $(ls ${{ORD_TLS_PATH}}/*.pem)"
).format(orderer=ord_name)
else:
cmd_suffix = ""
return cmd_suffix
[docs]def get_channel_block(peer_ex, ord_name, ord_namespace, channel, cmd_suffix):
"""Get channel block from Peer.
Args:
peer_ex (Executor): A Pod Executor representing a Peer.
ord_name (str): Name of the orderer we wish to communicate with.
ord_namespace (str): Namespace where the orderer resides.
channel (str): Name of the channel we with to retrieve.
cmd_suffix (str): Suffix to the "peer channel fetch" command.
Returns:
bool: Were we able to fetch the channel?
"""
channel_file = "/var/hyperledger/{channel}.block".format(channel=channel)
channel_block, _ = peer_ex.execute("ls {}".format(channel_file))
if not channel_block:
res, err = peer_ex.execute(
(
"bash -c 'peer channel fetch 0 {channel_file} "
+ "-c {channel} "
+ "-o {orderer}-hlf-ord.{ord_ns}.svc.cluster.local:7050 {cmd_suffix}'"
).format(
channel_file=channel_file,
channel=channel,
orderer=ord_name,
ord_ns=ord_namespace,
cmd_suffix=cmd_suffix,
)
)
if err:
return False
return True
# TODO: Split channel creation from channel joining
[docs]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_helm_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)
)