Skip to content

Commit

Permalink
mon: add the erasure-code-profile {set,get,rm,ls} MonCommand
Browse files Browse the repository at this point in the history
"erasure-code-profile set" parses the key=value pairs given in argument
and stores them in OSDMap::erasure_code_profiles. The
"erasure-code-profile get" supports plain text display if the Formatter
is not set (or invalid).

  erasure-code-profile set myprofile a=b c=d

is stored as

  OSDMap::erasure_code_profile["myprofile"] = {"a":"b", "c":"d"}

"erasure-code-profile ls" displays a list of the profile names from
OSDMap::erasure_code_profiles

"erasure-code-profile rm" removes a profile, if it exists. Displays a
message and succeeds if it does not exist.

Signed-off-by: Loic Dachary <[email protected]>
  • Loading branch information
Loic Dachary committed Mar 17, 2014
1 parent 1a451f2 commit 04d2fd1
Show file tree
Hide file tree
Showing 6 changed files with 384 additions and 4 deletions.
16 changes: 16 additions & 0 deletions src/mon/MonCommands.h
Original file line number Diff line number Diff line change
Expand Up @@ -455,6 +455,22 @@ COMMAND("osd setmaxosd " \
"set new maximum osd value", "osd", "rw", "cli,rest")
COMMAND("osd pause", "pause osd", "osd", "rw", "cli,rest")
COMMAND("osd unpause", "unpause osd", "osd", "rw", "cli,rest")
COMMAND("osd erasure-code-profile set " \
"name=name,type=CephString,goodchars=[A-Za-z0-9-_.] " \
"name=profile,type=CephString,n=N,req=false,goodchars=[A-Za-z0-9-_.=]", \
"create erasure code profile <name> with [<key[=value]> ...] pairs. Add a --force at the end to override an existing profile (VERY DANGEROUS)", \
"osd", "rw", "cli,rest")
COMMAND("osd erasure-code-profile get " \
"name=name,type=CephString,goodchars=[A-Za-z0-9-_.]", \
"get erasure code profile <name>", \
"osd", "r", "cli,rest")
COMMAND("osd erasure-code-profile rm " \
"name=name,type=CephString,goodchars=[A-Za-z0-9-_.]", \
"remove erasure code profile <name>", \
"osd", "rw", "cli,rest")
COMMAND("osd erasure-code-profile ls", \
"list all erasure code profiles", \
"osd", "r", "cli,rest")
COMMAND("osd set " \
"name=key,type=CephChoices,strings=pause|noup|nodown|noout|noin|nobackfill|norecover|noscrub|nodeep-scrub|notieragent", \
"set <key>", "osd", "rw", "cli,rest")
Expand Down
139 changes: 135 additions & 4 deletions src/mon/OSDMonitor.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2636,6 +2636,52 @@ bool OSDMonitor::preprocess_command(MMonCommand *m)
f->flush(rs);
rs << "\n";
rdata.append(rs.str());
} else if (prefix == "osd erasure-code-profile ls") {
const map<string,map<string,string> > &profiles =
osdmap.get_erasure_code_profiles();
if (f)
f->open_array_section("erasure-code-profiles");
for(map<string,map<string,string> >::const_iterator i = profiles.begin();
i != profiles.end();
i++) {
if (f)
f->dump_string("profile", i->first.c_str());
else
rdata.append(i->first + "\n");
}
if (f) {
f->close_section();
ostringstream rs;
f->flush(rs);
rs << "\n";
rdata.append(rs.str());
}
} else if (prefix == "osd erasure-code-profile get") {
string name;
cmd_getval(g_ceph_context, cmdmap, "name", name);
if (!osdmap.has_erasure_code_profile(name)) {
ss << "unknown erasure code profile '" << name << "'";
r = -ENOENT;
goto reply;
}
const map<string,string> &profile = osdmap.get_erasure_code_profile(name);
if (f)
f->open_object_section("profile");
for (map<string,string>::const_iterator i = profile.begin();
i != profile.end();
i++) {
if (f)
f->dump_string(i->first.c_str(), i->second.c_str());
else
rdata.append(i->first + "=" + i->second + "\n");
}
if (f) {
f->close_section();
ostringstream rs;
f->flush(rs);
rs << "\n";
rdata.append(rs.str());
}
} else {
// try prepare update
return false;
Expand Down Expand Up @@ -2904,10 +2950,28 @@ int OSDMonitor::check_cluster_features(uint64_t features,
return 0;
}

int OSDMonitor::prepare_pool_properties(const unsigned pool_type,
const vector<string> &properties,
map<string,string> *properties_map,
stringstream &ss)
bool OSDMonitor::erasure_code_profile_in_use(const map<int64_t, pg_pool_t> &pools,
const string &profile,
ostream &ss)
{
bool found = false;
for (map<int64_t, pg_pool_t>::const_iterator p = pools.begin();
p != pools.end();
++p) {
if (p->second.erasure_code_profile == profile) {
ss << osdmap.pool_name[p->first] << " ";
found = true;
}
}
if (found) {
ss << "pool(s) are using the erasure code profile '" << profile << "'";
}
return found;
}

int OSDMonitor::parse_erasure_code_profile(const vector<string> &erasure_code_profile,
map<string,string> *erasure_code_profile_map,
stringstream &ss)
{
if (pool_type == pg_pool_t::TYPE_ERASURE) {
int r = get_str_map(g_conf->osd_pool_default_erasure_code_properties,
Expand Down Expand Up @@ -3889,6 +3953,73 @@ bool OSDMonitor::prepare_command_impl(MMonCommand *m,
get_last_committed() + 1));
return true;

} else if (prefix == "osd erasure-code-profile rm") {
string name;
cmd_getval(g_ceph_context, cmdmap, "name", name);

if (erasure_code_profile_in_use(pending_inc.new_pools, name, ss))
goto wait;

if (erasure_code_profile_in_use(osdmap.pools, name, ss)) {
err = -EBUSY;
goto reply;
}

if (osdmap.has_erasure_code_profile(name) ||
pending_inc.new_erasure_code_profiles.count(name)) {
if (osdmap.has_erasure_code_profile(name)) {
pending_inc.old_erasure_code_profiles.push_back(name);
} else {
dout(20) << "erasure code profile rm " << name << ": creation canceled" << dendl;
pending_inc.new_erasure_code_profiles.erase(name);
}

getline(ss, rs);
wait_for_finished_proposal(new Monitor::C_Command(mon, m, 0, rs,
get_last_committed() + 1));
return true;
} else {
ss << "erasure-code-profile " << name << " does not exist";
err = 0;
goto reply;
}

} else if (prefix == "osd erasure-code-profile set") {
string name;
cmd_getval(g_ceph_context, cmdmap, "name", name);
vector<string> profile;
cmd_getval(g_ceph_context, cmdmap, "profile", profile);
bool force;
if (profile.size() > 0 && profile.back() == "--force") {
profile.pop_back();
force = true;
} else {
force = false;
}
map<string,string> profile_map;
err = parse_erasure_code_profile(profile, &profile_map, ss);
if (err)
goto reply;

if (osdmap.has_erasure_code_profile(name) && !force) {
err = -EPERM;
ss << "will not override erasure code profile " << name;
goto reply;
}

if (pending_inc.has_erasure_code_profile(name)) {
dout(20) << "erasure code profile " << name << " try again" << dendl;
goto wait;
} else {
dout(20) << "erasure code profile " << name << " set" << dendl;
pending_inc.set_erasure_code_profile(name, profile_map);
}

getline(ss, rs);
wait_for_finished_proposal(new Monitor::C_Command(mon, m, 0, rs,
get_last_committed() + 1));
return true;

} else if (prefix == "osd crush rule create-erasure") {
err = check_cluster_features(CEPH_FEATURE_CRUSH_V2, ss);
if (err == -EAGAIN)
Expand Down
6 changes: 6 additions & 0 deletions src/mon/OSDMonitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,12 @@ class OSDMonitor : public PaxosService {
const map<string,string> &properties,
int *crush_ruleset,
stringstream &ss);
bool erasure_code_profile_in_use(const map<int64_t, pg_pool_t> &pools,
const string &profile,
ostream &ss);
int parse_erasure_code_profile(const vector<string> &erasure_code_profile,
map<string,string> *erasure_code_profile_map,
stringstream &ss);
int prepare_pool_size(const unsigned pool_type,
const map<string,string> &properties,
unsigned *size,
Expand Down
1 change: 1 addition & 0 deletions src/test/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,7 @@ check_SCRIPTS += \
test/mon/osd-pool-create.sh \
test/mon/misc.sh \
test/mon/osd-crush.sh \
test/mon/osd-erasure-code-profile.sh \
test/mon/mkfs.sh \
test/ceph-disk.sh \
test/mon/mon-handle-forward.sh \
Expand Down
177 changes: 177 additions & 0 deletions src/test/mon/osd-erasure-code-profile.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
#!/bin/bash
#
# Copyright (C) 2014 Cloudwatt <[email protected]>
#
# Author: Loic Dachary <[email protected]>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU Library Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Library Public License for more details.
#
source test/mon/mon-test-helpers.sh

function run() {
local dir=$1

export CEPH_ARGS
CEPH_ARGS+="--fsid=$(uuidgen) --auth-supported=none "
CEPH_ARGS+="--mon-host=127.0.0.1 "

local id=a
call_TEST_functions $dir $id --public-addr 127.0.0.1 || return 1
}

function SHARE_MON_TEST_set() {
local dir=$1
local id=$2

local profile=myprofile
#
# no key=value pairs : use the default configuration
#
./ceph osd erasure-code-profile set $profile 2>&1 || return 1
./ceph osd erasure-code-profile get $profile | \
grep plugin=jerasure || return 1
./ceph osd erasure-code-profile rm $profile
#
# key=value pairs override the default
#
./ceph osd erasure-code-profile set $profile \
key=value plugin=example || return 1
./ceph osd erasure-code-profile get $profile | \
grep -e key=value -e plugin=example || return 1
#
# --force is required to override an existing profile
#
! ./ceph osd erasure-code-profile set $profile > $dir/out 2>&1 || return 1
grep 'will not override' $dir/out || return 1
./ceph osd erasure-code-profile set $profile key=other --force || return 1
./ceph osd erasure-code-profile get $profile | \
grep key=other || return 1

./ceph osd erasure-code-profile rm $profile # cleanup
}

function SHARE_MON_TEST_set_pending() {
local dir=$1
local id=$2

# try again if the profile is pending
local profile=profile
# add to the pending OSD map without triggering a paxos proposal
result=$(echo '{"prefix":"osdmonitor_prepare_command","prepare":"osd erasure-code-profile set","name":"'$profile'"}' | nc -U $dir/$id/ceph-mon.$id.asok | cut --bytes=5-)
test $result = true || return 1
./ceph osd erasure-code-profile set $profile --force || return 1
grep "$profile try again" $dir/$id/log || return 1

./ceph osd erasure-code-profile rm $profile # cleanup
}

function SHARE_MON_TEST_ls() {
local dir=$1
local id=$2

local profile=myprofile
! ./ceph osd erasure-code-profile ls | grep $profile || return 1
./ceph osd erasure-code-profile set $profile 2>&1 || return 1
./ceph osd erasure-code-profile ls | grep $profile || return 1
./ceph --format xml osd erasure-code-profile ls | \
grep "<profile>$profile</profile>" || return 1

./ceph osd erasure-code-profile rm $profile # cleanup
}

function SHARE_MON_TEST_rm() {
local dir=$1
local id=$2

local profile=myprofile
./ceph osd erasure-code-profile set $profile 2>&1 || return 1
./ceph osd erasure-code-profile ls | grep $profile || return 1
./ceph osd erasure-code-profile rm $profile || return 1
! ./ceph osd erasure-code-profile ls | grep $profile || return 1
./ceph osd erasure-code-profile rm WRONG 2>&1 | \
grep "WRONG does not exist" || return 1

./ceph osd erasure-code-profile set $profile || return 1
./ceph osd pool create poolname 12 12 erasure $profile || return 1
! ./ceph osd erasure-code-profile rm $profile > $dir/out 2>&1 || return 1
grep "poolname.*using.*$profile" $dir/out || return 1
./ceph osd pool delete poolname poolname --yes-i-really-really-mean-it || return 1
./ceph osd erasure-code-profile rm $profile || return 1

./ceph osd erasure-code-profile rm $profile # cleanup
}

function SHARE_MON_TEST_rm_pending() {
local dir=$1
local id=$2

# try again if the profile is pending
local profile=myprofile
# add to the pending OSD map without triggering a paxos proposal
result=$(echo '{"prefix":"osdmonitor_prepare_command","prepare":"osd erasure-code-profile set","name":"'$profile'"}' | nc -U $dir/$id/ceph-mon.$id.asok | cut --bytes=5-)
test $result = true || return 1
./ceph osd erasure-code-profile rm $profile || return 1
grep "$profile: creation canceled" $dir/$id/log || return 1
}

function SHARE_MON_TEST_get() {
local dir=$1
local id=$2

local default_profile=default
./ceph osd erasure-code-profile get $default_profile | \
grep plugin=jerasure || return 1
./ceph --format xml osd erasure-code-profile get $default_profile | \
grep '<plugin>jerasure</plugin>' || return 1
! ./ceph osd erasure-code-profile get WRONG > $dir/out 2>&1 || return 1
grep -q "unknown erasure code profile 'WRONG'" $dir/out || return 1
}

function TEST_format_invalid() {
local dir=$1

local profile=profile
# osd_pool_default_erasure-code-profile is
# valid JSON but not of the expected type
run_mon $dir a --public-addr 127.0.0.1 \
--osd_pool_default_erasure-code-profile 1
! ./ceph osd erasure-code-profile set $profile > $dir/out 2>&1 || return 1
cat $dir/out
grep 'must be a JSON object' $dir/out || return 1
}

function TEST_format_json() {
local dir=$1

# osd_pool_default_erasure-code-profile is JSON
expected='"plugin":"example"'
run_mon $dir a --public-addr 127.0.0.1 \
--osd_pool_default_erasure-code-profile "{$expected}"
./ceph --format json osd erasure-code-profile get default | \
grep "$expected" || return 1
}

function TEST_format_plain() {
local dir=$1

# osd_pool_default_erasure-code-profile is plain text
expected='"plugin":"example"'
run_mon $dir a --public-addr 127.0.0.1 \
--osd_pool_default_erasure-code-profile "plugin=example"
./ceph --format json osd erasure-code-profile get default | \
grep "$expected" || return 1
}

main osd-erasure-code-profile

# Local Variables:
# compile-command: "cd ../.. ; make -j4 && test/mon/osd-erasure-code-profile.sh"
# End:
Loading

0 comments on commit 04d2fd1

Please sign in to comment.