def _do_setup(self, cfg, node_count=5):
     # give defaults to teardown vars
     self._node_ctrl = None
     print 'creating', str(self.__class__.__name__)
     # set up our nodes (suite-internal interface)
     self._node_ctrl = WrappedNodeController(SubprocessNodeController())
     temp_dir = self._node_ctrl.get_data_dir()
     file_name = os.path.join(temp_dir, "config.js")
     with open(file_name, 'w') as config:
         config.write(json.dumps(cfg))
     self._nodes = [
         NodeArguments('v%s' % i,
                       8800 + i,
                       9000 + i,
                       config_files=[file_name],
                       ledger_type=cfg["LedgerType"])
         for i in range(node_count)
     ]
     # set up our urls (external interface)
     self.urls = ['http://localhost:%s' % x.http_port for x in self._nodes]
     # Make genesis block
     print 'creating genesis block...'
     self._nodes[0].genesis = True
     self._node_ctrl.create_genesis_block(self._nodes[0])
     # Launch network (node zero will trigger bootstrapping)
     print 'launching network...'
     for x in self._nodes:
         self._node_ctrl.start(x)
Example #2
0
def do_cluster_extend(args):
    state = load_state()

    node_controller = get_node_controller(state, args)
    node_command_generator = SimpleNodeCommandGenerator()
    vnm = ValidatorNetworkManager(
        node_controller=node_controller,
        node_command_generator=node_command_generator)

    existing_nodes = state["Nodes"]

    desired_stated = state["DesiredState"]

    if desired_stated != "Running":
        raise CliException(
            "You must have a running network.\n" +
            "Use the cluster start command to start a validator network.")

    print("Extending network by {} nodes.".format(args.count))

    index_offset = len(existing_nodes)

    for i in xrange(0, args.count):
        j = i + index_offset
        node_name = "validator-{:0>3}".format(j)

        if node_name in existing_nodes and vnm.is_running(node_name):
            print("Already running: {}".format(node_name))
            continue

        # genesis is true for the first node
        genesis = (j == 0)
        gossip_port = 5500 + j
        http_port = 8800 + j

        node_args = NodeArguments(node_name,
                                  http_port=http_port,
                                  gossip_port=gossip_port,
                                  genesis=genesis)
        node_command_generator.start(node_args)

        state["Nodes"][node_name] = {
            "Status": "Running",
            "Index": i,
            "HttpPort": str(http_port),
            "GossipPort": str(gossip_port)
        }

    save_state(state)

    try:
        vnm.update()
    except ManagementError as e:
        raise CliException(str(e))
Example #3
0
 def _do_setup(self):
     # give defaults to teardown vars
     self._node_ctrl = None
     print 'creating', str(self.__class__.__name__)
     # set up our nodes (suite-internal interface)
     self._nodes = [
         NodeArguments('v%s' % i, 8800 + i, 9000 + i) for i in range(2)
     ]
     # set up our urls (external interface)
     self.urls = ['http://localhost:%s' % x.http_port for x in self._nodes]
     # Make genesis block
     print 'creating genesis block...'
     self._nodes[0].genesis = True
     self._node_ctrl = WrappedNodeController(SubprocessNodeController())
     self._node_ctrl.create_genesis_block(self._nodes[0])
     # Launch network (node zero will trigger bootstrapping)
     print 'launching network...'
     for x in self._nodes:
         self._node_ctrl.start(x)
Example #4
0
def main():
    node_ctrl = None
    try:
        opts = configure(sys.argv[1:])
    except Exception as e:
        print(str(e), file=sys.stderr)
        sys.exit(1)

    try:
        count = opts['count']

        # log_config = NEED
        currency_home = opts['data_dir']
        http_port = int(opts['http_port'])
        gossip_port = int(opts['port'])
        try:
            ledger_type = opts["validator_config"]["LedgerType"]
        except KeyError:
            # None defaults to poet1
            ledger_type = None
        node_ctrl = WrappedNodeController(SubprocessNodeController(),
                                          data_dir=currency_home)
        nodes = []
        for idx in range(count):
            node = NodeArguments("validator-{:0>3}".format(idx),
                                 http_port=http_port + idx,
                                 gossip_port=gossip_port + idx,
                                 ledger_type=ledger_type)
            nodes.append(node)
        currency_home = node_ctrl.get_data_dir()
        if opts['log_config_dict']:
            file_name = 'launcher_cli_global_log_config.js'
            full_name = '{}/etc/{}'.format(currency_home, file_name)
            with open(full_name, 'w') as f:
                f.write(json.dumps(opts['log_config_dict'], indent=4))
            opts['validator_config']['LogConfigFile'] = full_name
        if opts['validator_config']:
            file_name = 'launcher_cli_global_validator_config.js'
            with open('{}/etc/{}'.format(currency_home, file_name), 'w') as f:
                f.write(json.dumps(opts['validator_config'], indent=4))
            for nd in nodes:
                nd.config_files.append(file_name)
        # set up our urls (external interface)
        urls = ['http://localhost:%s' % x.http_port for x in nodes]
        # Make genesis block
        print('creating genesis block...')
        nodes[0].genesis = True
        node_ctrl.create_genesis_block(nodes[0])
        # Launch network (node zero will trigger bootstrapping)
        batch_size = 8
        print('staged-launching network (batch_size: {})...'
              .format(batch_size))
        lower_bound = 0
        while lower_bound < count:
            upper_bound = lower_bound + min(count - lower_bound, batch_size)
            for idx in range(lower_bound, upper_bound):
                print("launching {}".format(nodes[idx].node_name))
                node_ctrl.start(nodes[idx])
            _poll_for_convergence(urls[lower_bound:upper_bound])
            lower_bound = upper_bound
        run_stats(urls[0])
    except KeyboardInterrupt:
        print("\nExiting")
    except ExitError as e:
        # this is an expected error/exit, don't print stack trace -
        # the code raising this exception is expected to have printed the error
        # details
        print("\nFailed!\nExiting: {}".format(e))
    except:
        traceback.print_exc()
        print("\nFailed!\nExiting: {}".format(sys.exc_info()[0]))

    finally:
        if node_ctrl is not None:
            # stop all nodes
            for node_name in node_ctrl.get_node_names():
                node_ctrl.stop(node_name)
            with Progress("terminating network") as p:
                to = TimeOut(16)
                while len(node_ctrl.get_node_names()) > 0:
                    if to.is_timed_out():
                        break
                    time.sleep(1)
                    p.step()
            # force kill anything left over
            for node_name in node_ctrl.get_node_names():
                print("%s still 'up'; sending kill..." % node_name)
                node_ctrl.kill(node_name)
            node_ctrl.archive('launcher')
            node_ctrl.clean()
Example #5
0
    def extend_genesis_util(self, overrides):
        print()
        vnm = None
        try:
            self._node_ctrl = None
            print('creating', str(self.__class__.__name__))
            # set up our nodes (suite-internal interface)
            self._node_ctrl = WrappedNodeController(SubprocessNodeController())
            cfg = overrides
            temp_dir = self._node_ctrl.get_data_dir()
            file_name = os.path.join(temp_dir, "config.js")
            with open(file_name, 'w') as config:
                config.write(json.dumps(cfg))
            data_dir = os.path.join(temp_dir, "data")
            gblock_file = genesis_info_file_name(data_dir)

            self._nodes = [
                NodeArguments('v%s' % i, 8800 + i, 9000 + i,
                              config_files=[file_name],
                              ledger_type=overrides["LedgerType"])
                for i in range(2)]
            # set up our urls (external interface)
            self.urls = [
                'http://localhost:%s' % x.http_port for x in self._nodes]
            # Make genesis block
            print('creating genesis block...')
            self.assertFalse(os.path.exists(gblock_file))
            self._nodes[0].genesis = True
            self._node_ctrl.create_genesis_block(self._nodes[0])

            # Test genesis util
            self.assertTrue(os.path.exists(gblock_file))
            genesis_dat = None
            with open(gblock_file, 'r') as f:
                genesis_dat = json.load(f)
            self.assertTrue('GenesisId' in genesis_dat.keys())
            head = genesis_dat['GenesisId']
            # Verify genesis tool efficacy on a minimal network
            # Launch network (node zero will trigger bootstrapping)
            print('launching network...')
            for x in self._nodes:
                self._node_ctrl.start(x)

            # ...verify validator is extending tgt_block
            to = TimeOut(64)
            blk_lists = None
            prog_str = 'testing root extension (expect root: %s)' % head
            with Progress(prog_str) as p:
                print()
                while not to.is_timed_out() and blk_lists is None:
                    try:
                        blk_lists = get_blocklists(['http://localhost:8800'])
                        print('block_lists: %s' % blk_lists)
                        if len(blk_lists) < 1 or len(blk_lists[0]) < 2:
                            blk_lists = None
                    except MessageException as e:
                        pass
                    time.sleep(2)
                    p.step()
            self.assertIsNotNone(blk_lists)
            root = blk_lists[0][0]
            self.assertEqual(head, root)
            # ...verify general convergence
            to = TimeOut(32)
            with Progress('testing root convergence') as p:
                print()
                while (is_convergent(self.urls, tolerance=1, standard=1)
                       is False and not to.is_timed_out()):
                    time.sleep(2)
                    p.step()
            # ...verify convergence on the genesis block
            blk_lists = get_blocklists(['http://localhost:8800'])
            root = blk_lists[0][0]
            self.assertEqual(head, root)
            print('network converged on root: %s' % root)
        finally:
            print('destroying', str(self.__class__.__name__))
            if hasattr(self, '_node_ctrl') and self._node_ctrl is not None:
                # Shut down the network
                with Progress("terminating network") as p:
                    for node_name in self._node_ctrl.get_node_names():
                        self._node_ctrl.stop(node_name)
                    to = TimeOut(16)
                    while len(self._node_ctrl.get_node_names()) > 0:
                        if to.is_timed_out():
                            break
                        time.sleep(1)
                        p.step()
                # force kill anything left over
                for node_name in self._node_ctrl.get_node_names():
                    try:
                        print("%s still 'up'; sending kill..." % node_name)
                        self._node_ctrl.kill(node_name)
                    except Exception as e:
                        print(e.message)
                self._node_ctrl.archive(self.__class__.__name__)
                self._node_ctrl.clean()
Example #6
0
def do_cluster_start(args):
    state = load_state(start=True)

    # Check State for Running validators, if stopped clear out nodes.
    if state["DesiredState"] == "Stopped":
        state["Nodes"] = {}

    manage_type = DEFAULT_MANAGE if args.manage is None else args.manage

    if "Manage" not in state or state["DesiredState"] == "Stopped":
        state['Manage'] = manage_type
    elif args.manage is not None and state['Manage'] != args.manage\
            and state["DesiredState"] == "Running":
        raise CliException('Cannot use two different Manage types.'
                           ' Already running {}'.format(state["Manage"]))

    state["DesiredState"] = "Running"

    if state["Manage"] in TNG_MANAGE:
        if args.processors is None:
            raise CliException("Use -P to specify one or more processors")
        state['Processors'] = args.processors

    node_controller = get_node_controller(state, args)
    node_command_generator = SimpleNodeCommandGenerator()
    vnm = ValidatorNetworkManager(
        node_controller=node_controller,
        node_command_generator=node_command_generator)

    try:
        existing_nodes = vnm.get_node_names()
    except ManagementError as e:
        raise CliException(str(e))

    # Check for runnings nodes. If found, raise exception with message to use
    # sawtooth cluster extend command to add nodes to running network.
    for i in xrange(0, args.count):
        node_name = "validator-{:0>3}".format(i)
        if node_name in existing_nodes and vnm.is_running(node_name):
            print("Already running: {}".format(node_name))
            raise CliException("Please use 'sawtooth cluster extend'\
             to add more nodes.")

    for i in xrange(0, args.count):
        node_name = "validator-{:0>3}".format(i)

        if node_name in existing_nodes and vnm.is_running(node_name):
            print("Already running: {}".format(node_name))
            continue

        # genesis is true for the first node
        genesis = (i == 0)
        gossip_port = 5500 + i
        http_port = 8800 + i

        node_args = NodeArguments(node_name,
                                  http_port=http_port,
                                  gossip_port=gossip_port,
                                  genesis=genesis)

        if node_args.genesis is True:
            node_controller.create_genesis_block(node_args)

        print("Starting: {}".format(node_name))
        node_command_generator.start(node_args)

        state["Nodes"][node_name] = {
            "Status": "Running",
            "Index": i,
            "HttpPort": str(http_port),
            "GossipPort": str(gossip_port)
        }

    save_state(state)

    try:
        vnm.update()
    except ManagementError as e:
        raise CliException(str(e))

    node_names = state['Nodes'].keys()

    if state["Manage"] in SUBPROCESS_MANAGE:
        try:
            while True:
                time.sleep(128)
        except KeyboardInterrupt:
            print()
            ns = Namespace(cluster_command='stop',
                           command='cluster',
                           node_names=node_names,
                           verbose=None)
            do_cluster_stop(ns)
Example #7
0
def do_cluster_start(args):
    state = load_state(start=True)

    # Check State for Running validators, if stopped clear out nodes.
    if state["DesiredState"] == "Stopped":
        state["Nodes"] = {}

    if "Manage" not in state or state["DesiredState"] == "Stopped":
        if args.manage == "subprocess" or args.manage is None:
            state["Manage"] = "subprocess"
        elif args.manage == "docker":
            state["Manage"] = "docker"
        elif args.manage == "daemon":
            state["Manage"] = "daemon"
        elif args.manage == "docker-tng":
            state["Manage"] = "docker-tng"
    elif args.manage is not None and state['Manage'] != args.manage\
            and state["DesiredState"] == "Running":
        raise CliException('Cannot use two different Manage types.'
                           ' Already running {}'.format(state["Manage"]))

    state["DesiredState"] = "Running"

    if state["Manage"] == 'docker-tng':
        state['Processors'] = args.processors

    node_controller = get_node_controller(state, args)
    node_command_generator = SimpleNodeCommandGenerator()
    vnm = ValidatorNetworkManager(
        node_controller=node_controller,
        node_command_generator=node_command_generator)

    try:
        existing_nodes = vnm.get_node_names()
    except ManagementError as e:
        raise CliException(str(e))

    for i in xrange(0, args.count):
        node_name = "validator-{:0>3}".format(i)

        if node_name in existing_nodes and vnm.is_running(node_name):
            print "Already running: {}".format(node_name)
            continue

        # genesis is true for the first node
        genesis = (i == 0)
        gossip_port = 5500 + i
        http_port = 8800 + i

        node_args = NodeArguments(node_name,
                                  http_port=http_port,
                                  gossip_port=gossip_port,
                                  genesis=genesis)
        if node_args.genesis is True:
            node_controller.create_genesis_block(node_args)
        print "Starting: {}".format(node_name)
        node_command_generator.start(node_args)

        state["Nodes"][node_name] = {"Status": "Running", "Index": i}

    save_state(state)

    try:
        vnm.update()
    except ManagementError as e:
        raise CliException(str(e))

    if state["Manage"] == 'subprocess':
        try:
            while True:
                time.sleep(128)
        except KeyboardInterrupt:
            print
            ns = Namespace(cluster_command='stop',
                           command='cluster',
                           node_names=[],
                           verbose=None)
            do_cluster_stop(ns)