Esempio n. 1
0
static void ext_prog_failed(struct ticket_config *tk,
		int start_election)
{
	if (!is_manual(tk)) {
		/* Give it to somebody else.
	 	 * Just send a VOTE_FOR message, so the
		 * others can start elections. */
		if (leader_and_valid(tk)) {
			save_committed_tkt(tk);
			reset_ticket(tk);
			ticket_write(tk);	
			if (start_election) {
				ticket_broadcast(tk, OP_VOTE_FOR, OP_REQ_VOTE, RLT_SUCCESS, OR_LOCAL_FAIL);
			}
		}
	} else {
		/* There is not much we can do now because
		 * the manual ticket cannot be relocated.
		 * Just warn the user. */
		if (tk->leader == local) {
			save_committed_tkt(tk);
			reset_ticket(tk);
			ticket_write(tk);	
			log_error("external test failed on the specified machine, cannot acquire a manual ticket");
		}
	}
}
Esempio n. 2
0
File: raft.c Progetto: jnpkrn/booth
static int process_REVOKE (
		struct ticket_config *tk,
		struct booth_site *sender,
		struct booth_site *leader,
		struct boothc_ticket_msg *msg
	       )
{
	int rv;

	if (tk->state == ST_INIT && tk->leader == no_leader) {
		/* assume that our ack got lost */
		rv = send_msg(OP_ACK, tk, sender, msg);
	} else if (tk->leader != sender) {
		tk_log_error("%s wants to revoke ticket, "
				"but it is not granted there (ignoring)",
				site_string(sender));
		return 1;
	} else if (tk->state != ST_FOLLOWER) {
		tk_log_error("unexpected ticket revoke from %s "
				"(in state %s) (ignoring)",
				site_string(sender),
				state_to_string(tk->state));
		return 1;
	} else {
		tk_log_info("%s revokes ticket",
				site_string(tk->leader));
		save_committed_tkt(tk);
		reset_ticket(tk);
		set_leader(tk, no_leader);
		ticket_write(tk);
		rv = send_msg(OP_ACK, tk, sender, msg);
	}

	return rv;
}
Esempio n. 3
0
File: raft.c Progetto: jnpkrn/booth
static int process_UPDATE (
		struct ticket_config *tk,
		struct booth_site *sender,
		struct booth_site *leader,
		struct boothc_ticket_msg *msg
	       )
{
	if (is_owned(tk) && sender != tk->leader) {
		tk_log_warn("different leader %s wants to update "
				"our ticket, sending reject",
			site_string(leader));
		return send_reject(sender, tk, RLT_TERM_OUTDATED, msg);
	}

	tk_log_debug("leader %s wants to update our ticket",
			site_string(leader));

	become_follower(tk, msg);
	set_leader(tk, leader);
	ticket_write(tk);

	/* run ticket_cron if the ticket expires */
	set_ticket_wakeup(tk);

	return send_msg(OP_ACK, tk, sender, msg);
}
Esempio n. 4
0
static void start_revoke_ticket(struct ticket_config *tk)
{
	tk_log_info("revoking ticket");

	save_committed_tkt(tk);
	reset_ticket_and_set_no_leader(tk);
	ticket_write(tk);
	ticket_broadcast(tk, OP_REVOKE, OP_ACK, RLT_SUCCESS, OR_ADMIN);
}
Esempio n. 5
0
int chirp_acl_ticket_modify(const char *subject, const char *ticket_subject, const char *path, int flags)
{
	char ticket_filename[CHIRP_PATH_MAX];
	const char *digest;
	char *esubject;
	struct chirp_ticket ct;
	int status = 0;

	if(!chirp_ticket_isticketsubject(ticket_subject, &digest)) {
		errno = EINVAL;
		return -1;
	}
	/* Note about tickets making tickets:
	 * We check whether the ticket has the rights associated with the mask in
	 * the next line. So, a ticket can only make a ticket with rights it
	 * already has.
	 */
	if(!chirp_acl_check_dir(path, subject, flags))
		return -1;	/* you don't have the rights for the mask */
	if(!chirp_acl_whoami(subject, &esubject))
		return -1;

	chirp_ticket_filename(ticket_filename, ticket_subject, NULL);

	if(!ticket_read(ticket_filename, &ct)) {
		free(esubject);
		return -1;
	}

	if(strcmp(esubject, ct.subject) == 0 || strcmp(chirp_super_user, subject) == 0) {
		size_t n;
		int replaced = 0;
		for(n = 0; n < ct.nrights; n++) {
			if(strcmp(ct.rights[n].directory, path) == 0) {
				free(ct.rights[n].acl);
				ct.rights[n].acl = xxstrdup(chirp_acl_flags_to_text(flags));	/* replace old acl mask */
				replaced = 1;
			}
		}
		if(!replaced) {
			char directory[CHIRP_PATH_MAX];
			assert(strlen(path));
			ct.rights = xxrealloc(ct.rights, sizeof(*ct.rights) * (++ct.nrights) + 1);
			path_collapse(path, directory, 1);
			ct.rights[ct.nrights - 1].directory = xxstrdup(directory);
			ct.rights[ct.nrights - 1].acl = xxstrdup(chirp_acl_flags_to_text(flags));
		}
		status = ticket_write(ticket_filename, &ct);
	} else {
		errno = EACCES;
		status = -1;
	}
	chirp_ticket_free(&ct);
	free(esubject);
	return status;
}
Esempio n. 6
0
void update_ticket_state(struct ticket_config *tk, struct booth_site *sender)
{
	if (tk->state == ST_CANDIDATE) {
		tk_log_info("learned from %s about "
				"newer ticket, stopping elections",
				site_string(sender));
		/* there could be rejects coming from others; don't log
		 * warnings unnecessarily */
		tk->expect_more_rejects = 1;
	}

	if (tk->leader == local || tk->is_granted) {
		/* message from a live leader with valid ticket? */
		if (sender == tk->leader && term_time_left(tk)) {
			if (tk->is_granted) {
				tk_log_warn("ticket was granted here, "
						"but it's live at %s (revoking here)",
						site_string(sender));
			} else {
				tk_log_info("ticket live at %s",
						site_string(sender));
			}
			disown_ticket(tk);
			ticket_write(tk);
			set_state(tk, ST_FOLLOWER);
			set_next_state(tk, ST_FOLLOWER);
		} else {
			if (tk->state == ST_CANDIDATE) {
				set_state(tk, ST_FOLLOWER);
			}
			set_next_state(tk, ST_LEADER);
		}
	} else {
		if (!tk->leader || tk->leader == no_leader) {
			if (sender)
				tk_log_info("ticket is not granted");
			else
				tk_log_info("ticket is not granted (from CIB)");
			set_state(tk, ST_INIT);
		} else {
			if (sender)
				tk_log_info("ticket granted to %s (says %s)",
					site_string(tk->leader),
					tk->leader == sender ? "they" : site_string(sender));
			else
				tk_log_info("ticket granted to %s (from CIB)",
					site_string(tk->leader));
			set_state(tk, ST_FOLLOWER);
			/* just make sure that we check the ticket soon */
			set_next_state(tk, ST_FOLLOWER);
		}
	}
}
Esempio n. 7
0
File: raft.c Progetto: jnpkrn/booth
static int process_VOTE_FOR(
		struct ticket_config *tk,
		struct booth_site *sender,
		struct booth_site *leader,
		struct boothc_ticket_msg *msg
		)
{
	if (leader == no_leader) {
		/* leader wants to step down? */
		if (sender == tk->leader &&
			(tk->state == ST_FOLLOWER || tk->state == ST_CANDIDATE)) {
			tk_log_info("%s wants to give the ticket away (ticket release)",
				site_string(tk->leader));
			save_committed_tkt(tk);
			reset_ticket(tk);
			set_state(tk, ST_FOLLOWER);
			if (local->type == SITE) {
				ticket_write(tk);
				schedule_election(tk, OR_STEPDOWN);
			}
		} else {
			tk_log_info("%s votes for none, ignoring (duplicate ticket release?)",
				site_string(sender));
		}
		return 0;
	}

	if (tk->state != ST_CANDIDATE) {
		/* lost candidate status, somebody rejected our proposal */
		tk_log_info("candidate status lost, ignoring VtFr from %s",
			site_string(sender));
		return 0;
	}

	if (term_too_low(tk, sender, leader, msg))
		return 0;

	if (newer_term(tk, sender, leader, msg, 0)) {
		clear_election(tk);
	}

	record_vote(tk, sender, leader);

	/* only if all voted can we take the ticket now, otherwise
	 * wait for timeout in ticket_cron */
	if (!tk->acks_expected) {
		/* §5.2 */
		elections_end(tk);
	}

	return 0;
}
Esempio n. 8
0
File: raft.c Progetto: jnpkrn/booth
static void become_follower(struct ticket_config *tk,
		struct boothc_ticket_msg *msg)
{
	copy_ticket_from_msg(tk, msg);
	set_state(tk, ST_FOLLOWER);
	time_reset(&tk->delay_commit);
	tk->in_election = 0;
	/* if we're following and the ticket was granted here
	 * then commit to CIB right away (we're probably restarting)
	 */
	if (tk->is_granted) {
		disown_ticket(tk);
		ticket_write(tk);
	}
}
Esempio n. 9
0
static void ext_prog_failed(struct ticket_config *tk,
		int start_election)
{
	/* Give it to somebody else.
	 * Just send a VOTE_FOR message, so the
	 * others can start elections. */
	if (leader_and_valid(tk)) {
		save_committed_tkt(tk);
		reset_ticket(tk);
		ticket_write(tk);
		if (start_election) {
			ticket_broadcast(tk, OP_VOTE_FOR, OP_REQ_VOTE, RLT_SUCCESS, OR_LOCAL_FAIL);
		}
	}
}