示例#1
0
int
cib_process_upgrade(const char *op, int options, const char *section, xmlNode * req,
                    xmlNode * input, xmlNode * existing_cib, xmlNode ** result_cib,
                    xmlNode ** answer)
{
    int rc = 0;
    int new_version = 0;
    int current_version = 0;
    int max_version = 0;
    const char *max = crm_element_value(req, F_CIB_SCHEMA_MAX);
    const char *value = crm_element_value(existing_cib, XML_ATTR_VALIDATION);

    *answer = NULL;
    crm_trace("Processing \"%s\" event with max=%s", op, max);

    if (value != NULL) {
        current_version = get_schema_version(value);
    }

    if (max) {
        max_version = get_schema_version(max);
    }

    rc = update_validation(result_cib, &new_version, max_version, TRUE, TRUE);
    if (new_version > current_version) {
        cib_update_counter(*result_cib, XML_ATTR_GENERATION_ADMIN, FALSE);
        cib_update_counter(*result_cib, XML_ATTR_GENERATION, TRUE);
        cib_update_counter(*result_cib, XML_ATTR_NUMUPDATES, TRUE);
        return pcmk_ok;
    }

    return rc;
}
示例#2
0
enum cib_errors
cib_process_upgrade(const char *op, int options, const char *section, xmlNode * req,
                    xmlNode * input, xmlNode * existing_cib, xmlNode ** result_cib,
                    xmlNode ** answer)
{
    int rc = 0;
    int new_version = 0;
    int current_version = 0;

    const char *value = crm_element_value(existing_cib, XML_ATTR_VALIDATION);;

    *answer = NULL;
    crm_debug_2("Processing \"%s\" event", op);

    if (value != NULL) {
        current_version = get_schema_version(value);
    }

    rc = update_validation(result_cib, &new_version, TRUE, TRUE);
    if (new_version > current_version) {
        return cib_ok;
    }

    return rc;
}
示例#3
0
int
example_main(int argc, char **argv)
{
    /* Create a database with the current schema definition */
    db_t hdb = create_database( EXAMPLE_DATABASE, &v2_schema, init_data_cb );

    /* Create database with v1 schema */
    db_t hdb_upgrade = create_database( EXAMPLE_UPGRADE_DATABASE, &v1_schema, init_data_cb );

    /* Open database with v1 schema and upgrade to current schema */
    db_shutdown( hdb_upgrade, 0, NULL );
    hdb = open_database( EXAMPLE_UPGRADE_DATABASE, &v2_schema, &upgrade_schema_cb );

    if( hdb != NULL ) {
        int v = get_schema_version( hdb_upgrade );
        db_shutdown( hdb_upgrade, 0, NULL );
        db_shutdown( hdb, 0, NULL );
        if (v == v2_schema.version) {
            return EXIT_SUCCESS;
        }
    }
    db_shutdown( hdb_upgrade, 0, NULL );
    db_shutdown( hdb, 0, NULL );
    return EXIT_FAILURE;
}
示例#4
0
db_t
open_database(char* database_name, dbs_versioned_schema_def_t *versioned_schema, UpgradeCallback cb)
{
    db_t hdb;
    int version;
    int upgrade_rc = 0;

    /* Open an existing file storage database with default parameters. */
    hdb = db_open_file_storage(database_name, NULL);

    if (hdb == NULL) {
        return NULL;
    }

    db_begin_tx( hdb, DB_DEFAULT_ISOLATION | DB_LOCK_DEFAULT );
    version = get_schema_version( hdb );
    db_commit_tx( hdb, DB_DEFAULT_COMPLETION );

    if( version != versioned_schema->version
        && ( !cb
             || 0 != ( upgrade_rc = (*cb)( hdb, version, versioned_schema->version ) )
             )
        )
    {
        if( 1 == upgrade_rc ) {
            fprintf(
                stderr, "ITTIA evaluation mode can't be used to perform full upgrade actions set,\n"
                "  in this conditions we just suppose upgrade job is successfull\n"
                );
        }
        else {
            print_error_message( "Opened DB has wrong version and it couldn't be upgraded to version requiested", NULL );
            return NULL;
        }
    }

    if ( 0 == upgrade_rc && !dbs_check_schema(hdb, &versioned_schema->schema)) {
        fprintf(stderr, "WARNING: schema conflict in %s. Version: %d\n", database_name, versioned_schema->version );
        return NULL;
    }

    db_begin_tx( hdb, DB_DEFAULT_ISOLATION | DB_LOCK_DEFAULT );
    set_schema_version( hdb, versioned_schema->version );
    db_commit_tx( hdb, DB_DEFAULT_COMPLETION );

    //open_sequences(hdb);

    return hdb;
}
示例#5
0
int
cib_process_command(xmlNode * request, xmlNode ** reply, xmlNode ** cib_diff, gboolean privileged)
{
    xmlNode *input = NULL;
    xmlNode *output = NULL;
    xmlNode *result_cib = NULL;
    xmlNode *current_cib = NULL;

#if ENABLE_ACL
    xmlNode *filtered_current_cib = NULL;
#endif

    int call_type = 0;
    int call_options = 0;
    int log_level = LOG_DEBUG_4;

    const char *op = NULL;
    const char *section = NULL;

    int rc = pcmk_ok;
    int rc2 = pcmk_ok;

    gboolean send_r_notify = FALSE;
    gboolean global_update = FALSE;
    gboolean config_changed = FALSE;
    gboolean manage_counters = TRUE;

    CRM_ASSERT(cib_status == pcmk_ok);

    *reply = NULL;
    *cib_diff = NULL;
    current_cib = the_cib;

    /* Start processing the request... */
    op = crm_element_value(request, F_CIB_OPERATION);
    crm_element_value_int(request, F_CIB_CALLOPTS, &call_options);
    rc = cib_get_operation_id(op, &call_type);

    if (rc == pcmk_ok && privileged == FALSE) {
        rc = cib_op_can_run(call_type, call_options, privileged, global_update);
    }

    rc2 = cib_op_prepare(call_type, request, &input, &section);
    if (rc == pcmk_ok) {
        rc = rc2;
    }

    if (rc != pcmk_ok) {
        crm_trace("Call setup failed: %s", pcmk_strerror(rc));
        goto done;

    } else if (cib_op_modifies(call_type) == FALSE) {
#if ENABLE_ACL
        if (acl_enabled(config_hash) == FALSE
            || acl_filter_cib(request, current_cib, current_cib, &filtered_current_cib) == FALSE) {
            rc = cib_perform_op(op, call_options, cib_op_func(call_type), TRUE,
                                section, request, input, FALSE, &config_changed,
                                current_cib, &result_cib, NULL, &output);

        } else if (filtered_current_cib == NULL) {
            crm_debug("Pre-filtered the entire cib");
            rc = -EACCES;

        } else {
            crm_debug("Pre-filtered the queried cib according to the ACLs");
            rc = cib_perform_op(op, call_options, cib_op_func(call_type), TRUE,
                                section, request, input, FALSE, &config_changed,
                                filtered_current_cib, &result_cib, NULL, &output);
        }
#else
        rc = cib_perform_op(op, call_options, cib_op_func(call_type), TRUE,
                            section, request, input, FALSE, &config_changed,
                            current_cib, &result_cib, NULL, &output);

#endif

        CRM_CHECK(result_cib == NULL, free_xml(result_cib));
        goto done;
    }

    /* Handle a valid write action */
    global_update = crm_is_true(crm_element_value(request, F_CIB_GLOBAL_UPDATE));
    if (global_update) {
        manage_counters = FALSE;
        call_options |= cib_force_diff;

        CRM_CHECK(call_type == 3 || call_type == 4, crm_err("Call type: %d", call_type);
                  crm_log_xml_err(request, "bad op"));
    }
#ifdef SUPPORT_PRENOTIFY
    if ((call_options & cib_inhibit_notify) == 0) {
        cib_pre_notify(call_options, op, the_cib, input);
    }
#endif

    if (rc == pcmk_ok) {
        if (call_options & cib_inhibit_bcast) {
            /* skip */
            crm_trace("Skipping update: inhibit broadcast");
            manage_counters = FALSE;
        }

        rc = cib_perform_op(op, call_options, cib_op_func(call_type), FALSE,
                            section, request, input, manage_counters, &config_changed,
                            current_cib, &result_cib, cib_diff, &output);

#if ENABLE_ACL
        if (acl_enabled(config_hash) == TRUE
            && acl_check_diff(request, current_cib, result_cib, *cib_diff) == FALSE) {
            rc = -EACCES;
        }
#endif

        if (rc == pcmk_ok && config_changed) {
            time_t now;
            char *now_str = NULL;
            const char *validation = crm_element_value(result_cib, XML_ATTR_VALIDATION);

            if (validation) {
                int current_version = get_schema_version(validation);
                int support_version = get_schema_version("pacemaker-1.1");

                /* Once the later schemas support the "update-*" attributes, change "==" to ">=" -- Changed */
                if (current_version >= support_version) {
                    const char *origin = crm_element_value(request, F_ORIG);

                    crm_xml_replace(result_cib, XML_ATTR_UPDATE_ORIG,
                                    origin ? origin : cib_our_uname);
                    crm_xml_replace(result_cib, XML_ATTR_UPDATE_CLIENT,
                                    crm_element_value(request, F_CIB_CLIENTNAME));
#if ENABLE_ACL
                    crm_xml_replace(result_cib, XML_ATTR_UPDATE_USER,
                                    crm_element_value(request, F_CIB_USER));
#endif
                }
            }

            now = time(NULL);
            now_str = ctime(&now);
            now_str[24] = EOS;  /* replace the newline */
            crm_xml_replace(result_cib, XML_CIB_ATTR_WRITTEN, now_str);
        }

        if (manage_counters == FALSE) {
            config_changed = cib_config_changed(current_cib, result_cib, cib_diff);
        }

        /* Always write to disk for replace ops,
         * this negates the need to detect ordering changes
         */
        if (config_changed == FALSE && crm_str_eq(CIB_OP_REPLACE, op, TRUE)) {
            config_changed = TRUE;
        }
    }

    if (rc == pcmk_ok && (call_options & cib_dryrun) == 0) {
        rc = activateCibXml(result_cib, config_changed, op);
        if (rc == pcmk_ok && cib_internal_config_changed(*cib_diff)) {
            cib_read_config(config_hash, result_cib);
        }

        if (crm_str_eq(CIB_OP_REPLACE, op, TRUE)) {
            if (section == NULL) {
                send_r_notify = TRUE;

            } else if (safe_str_eq(section, XML_TAG_CIB)) {
                send_r_notify = TRUE;

            } else if (safe_str_eq(section, XML_CIB_TAG_NODES)) {
                send_r_notify = TRUE;

            } else if (safe_str_eq(section, XML_CIB_TAG_STATUS)) {
                send_r_notify = TRUE;
            }

        } else if (crm_str_eq(CIB_OP_ERASE, op, TRUE)) {
            send_r_notify = TRUE;
        }

    } else if (rc == -pcmk_err_dtd_validation) {
        if (output != NULL) {
            crm_log_xml_info(output, "cib:output");
            free_xml(output);
        }
#if ENABLE_ACL
        {
            xmlNode *filtered_result_cib = NULL;

            if (acl_enabled(config_hash) == FALSE
                || acl_filter_cib(request, current_cib, result_cib,
                                  &filtered_result_cib) == FALSE) {
                output = result_cib;

            } else {
                crm_debug("Filtered the result cib for output according to the ACLs");
                output = filtered_result_cib;
                if (result_cib != NULL) {
                    free_xml(result_cib);
                }
            }
        }
#else
        output = result_cib;
#endif

    } else {
        free_xml(result_cib);
    }

    if ((call_options & cib_inhibit_notify) == 0) {
        const char *call_id = crm_element_value(request, F_CIB_CALLID);
        const char *client = crm_element_value(request, F_CIB_CLIENTNAME);

#ifdef SUPPORT_POSTNOTIFY
        cib_post_notify(call_options, op, input, rc, the_cib);
#endif
        cib_diff_notify(call_options, client, call_id, op, input, rc, *cib_diff);
    }

    if (send_r_notify) {
        const char *origin = crm_element_value(request, F_ORIG);

        cib_replace_notify(origin, the_cib, rc, *cib_diff);
    }

    if (rc != pcmk_ok) {
        log_level = LOG_DEBUG_4;
        if (rc == -pcmk_err_dtd_validation && global_update) {
            log_level = LOG_WARNING;
            crm_log_xml_info(input, "cib:global_update");
        }

    } else if (config_changed) {
        log_level = LOG_DEBUG_3;
        if (cib_is_master) {
            log_level = LOG_NOTICE;
        }

    } else if (cib_is_master) {
        log_level = LOG_DEBUG_2;
    }

    log_xml_diff(log_level, *cib_diff, "cib:diff");

  done:
    if ((call_options & cib_discard_reply) == 0) {
        *reply = cib_construct_reply(request, output, rc);
        crm_log_xml_trace(*reply, "cib:reply");
    }
#if ENABLE_ACL
    if (filtered_current_cib != NULL) {
        free_xml(filtered_current_cib);
    }
#endif

    if (call_type >= 0) {
        cib_op_cleanup(call_type, call_options, &input, &output);
    }
    return rc;
}
示例#6
0
int proxy_db_open_with_version(pool *p, const char *table_path,
    const char *schema_name, unsigned int schema_version, int flags) {
  pool *tmp_pool;
  int res, xerrno = 0;
  unsigned int current_version = 0;

  res = proxy_db_open(p, table_path, schema_name);
  if (res < 0) {
    return -1;
  }

  tmp_pool = make_sub_pool(p);
  res = get_schema_version(tmp_pool, schema_name, &current_version);
  if (res < 0) {
    xerrno = errno;

    destroy_pool(tmp_pool);
    errno = xerrno;
    return -1;
  }

  if (current_version >= schema_version) {
    pr_trace_msg(trace_channel, 11,
      "schema version %u >= desired version %u for schema '%s'",
      current_version, schema_version, schema_name);
    return 0;
  }

  if (flags & PROXY_DB_OPEN_FL_ERROR_ON_SCHEMA_VERSION_SKEW) {
    pr_trace_msg(trace_channel, 5,
      "schema version %u < desired version %u for schema '%s', failing",
      current_version, schema_version, schema_name);
    destroy_pool(tmp_pool);
    errno = EPERM;
    return -1;
  }

  proxy_db_close(p, schema_name);
  if (unlink(table_path) < 0) {
    pr_log_pri(PR_LOG_NOTICE, MOD_PROXY_VERSION
      ": error deleting '%s': %s", table_path, strerror(errno));
  }

  res = proxy_db_open(p, table_path, schema_name);
  if (res < 0) {
    xerrno = errno;

    destroy_pool(tmp_pool);
    errno = xerrno;
    return -1;
  }

  res = set_schema_version(tmp_pool, schema_name, schema_version);
  xerrno = errno;

  destroy_pool(tmp_pool);

  if (res < 0) {
    errno = xerrno;
    return -1;
  }

  return 0;
}
示例#7
0
int
cib_process_upgrade_server(const char *op, int options, const char *section, xmlNode * req, xmlNode * input,
                           xmlNode * existing_cib, xmlNode ** result_cib, xmlNode ** answer)
{
#ifdef CIBPIPE
    return -EINVAL;
#else
    int rc = pcmk_ok;

    *answer = NULL;

    if(crm_element_value(req, F_CIB_SCHEMA_MAX)) {
        return cib_process_upgrade(
            op, options, section, req, input, existing_cib, result_cib, answer);

    } else {
        int new_version = 0;
        int current_version = 0;
        xmlNode *scratch = copy_xml(existing_cib);
        const char *host = crm_element_value(req, F_ORIG);
        const char *value = crm_element_value(existing_cib, XML_ATTR_VALIDATION);

        crm_trace("Processing \"%s\" event", op);
        if (value != NULL) {
            current_version = get_schema_version(value);
        }

        rc = update_validation(&scratch, &new_version, 0, TRUE, TRUE);
        if (new_version > current_version) {
            xmlNode *up = create_xml_node(NULL, __FUNCTION__);

            rc = pcmk_ok;
            crm_notice("Upgrade request from %s verified", host);

            crm_xml_add(up, F_TYPE, "cib");
            crm_xml_add(up, F_CIB_OPERATION, CIB_OP_UPGRADE);
            crm_xml_add(up, F_CIB_SCHEMA_MAX, get_schema_name(new_version));
            crm_xml_add(up, F_CIB_DELEGATED, host);
            crm_xml_add(up, F_CIB_CLIENTID, crm_element_value(req, F_CIB_CLIENTID));
            crm_xml_add(up, F_CIB_CALLOPTS, crm_element_value(req, F_CIB_CALLOPTS));
            crm_xml_add(up, F_CIB_CALLID, crm_element_value(req, F_CIB_CALLID));

            if (cib_legacy_mode() && cib_is_master) {
                rc = cib_process_upgrade(
                    op, options, section, up, input, existing_cib, result_cib, answer);

            } else {
                send_cluster_message(NULL, crm_msg_cib, up, FALSE);
            }

            free_xml(up);

        } else if(rc == pcmk_ok) {
            rc = -pcmk_err_schema_unchanged;
        }

        free_xml(scratch);
    }
    return rc;
#endif
}