Skip to content

Commit

Permalink
c0appz: fix several local endpoints and proc fids
Browse files Browse the repository at this point in the history
In commit 9f3a3aa we introduced parameters names in the
startup config file, but broke the functionality when several
local endpoints and proc fids could be specified in it and
the needed one could be selected via the idx argument at
c0appz_init(idx).

Solution: 1) update local endpoint and proc fid parameters
names format in the config file to LOCAL_ENDPOINT_ADDR%d and
LOCAL_PROC_FID%d (where %d is the index starting from 0);
2) fix c0appz_init() to honour the idx parameter;
3) update sage-user-application-assignment script and add
to this repository for the convenience.
  • Loading branch information
andriytk committed Sep 16, 2020
1 parent 9f3a3aa commit 923080f
Show file tree
Hide file tree
Showing 3 changed files with 226 additions and 8 deletions.
18 changes: 10 additions & 8 deletions c0appz.c
Original file line number Diff line number Diff line change
Expand Up @@ -908,21 +908,23 @@ int c0appz_ex(uint64_t idhi, uint64_t idlo, struct m0_clovis_obj *obj_out)
return 1;
}

static int read_conf_params(const struct param params[], int n)
static int read_conf_params(int idx, const struct param params[], int n)
{
int i;
struct conf_params_to_read {
const char *name;
const char **conf_ptr;
} p[] = { { "LOCAL_ENDPOINT_ADDR", &clovis_conf.cc_local_addr },
{ "HA_ENDPOINT_ADDR", &clovis_conf.cc_ha_addr },
{ "PROFILE_FID", &clovis_conf.cc_profile },
{ "LOCAL_PROC_FID", &clovis_conf.cc_process_fid }, };
} p[] = { { "HA_ENDPOINT_ADDR", &clovis_conf.cc_ha_addr },
{ "PROFILE_FID", &clovis_conf.cc_profile },
{ "LOCAL_ENDPOINT_ADDR%d", &clovis_conf.cc_local_addr },
{ "LOCAL_PROC_FID%d", &clovis_conf.cc_process_fid }, };
char pname[256];

for (i = 0; i < ARRAY_SIZE(p); i++) {
*(p[i].conf_ptr) = param_get(p[i].name, params, n);
sprintf(pname, p[i].name, idx);
*(p[i].conf_ptr) = param_get(pname, params, n);
if (*(p[i].conf_ptr) == NULL) {
ERR("%s is not set at %s\n", p[i].name, c0rcfile);
ERR("%s is not set at %s\n", pname, c0rcfile);
return -EINVAL;
}
}
Expand Down Expand Up @@ -967,7 +969,7 @@ int c0appz_init(int idx)
return -EINVAL;
}

rc = read_conf_params(rc_params, rc_params_nr);
rc = read_conf_params(idx, rc_params, rc_params_nr);
if (rc != 0) {
ERR("failed to read conf parameters from %s\n", c0rcfile);
return rc;
Expand Down
6 changes: 6 additions & 0 deletions c0appz.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@
extern bool m0trace_on;
extern const char *c0appz_help_txt;

/**
* Initialise Object Store
*
* idx selects which local endpoint and proc fid to use from the
* startup configuration file at $HOME/.c0appz/ (starts from 0).
*/
int c0appz_init(int idx);
int c0appz_free(void);

Expand Down
210 changes: 210 additions & 0 deletions scripts/sage-user-application-assignment
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
#!/usr/bin/env python3
#
# Copyright (c) 2018-2020 Seagate Technology LLC and/or its Affiliates
#
# 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.
#
# For any questions about this software or licensing,
# please email [email protected] or [email protected].
#
# Original author: Maxim Medved <[email protected]>
# Original creation date: 31-Jan-2018

import sys
import json
import argparse
import subprocess


CONFIG_FILE = "/etc/sage/assignment.conf"


def parse_args():
parser = argparse.ArgumentParser(description="SAGE User/Application "
"Assignment")
parser.add_argument('user', action='store', nargs='?', default=None,
type=str, help="user name", metavar='user')
parser.add_argument('application', action='store', nargs='?', default=None,
type=str, help="application name",
metavar='application')
parser.add_argument('IP', action='store', nargs='?', default=None,
type=str, help="IP address", metavar='IP')
parser.add_argument('--no-ssh', action='store_true',
help="run hctl command locally")
parser.add_argument('--regenerate', action='store', nargs=1, default=None,
type=str, required=False,
help="regenerate assignments for the tier. "
"Should be done after every tier re-bootstrap",
metavar='tier', dest='tier')
parser.add_argument('--json', action='store_const', const=True,
default=False, required=False,
help="json output", metavar='json', dest='json')
parser.add_argument('--simple', action='store_const', const=True,
default=False, required=False,
help="simple output", metavar='simple', dest='simple')
args = parser.parse_args()
# print(args)
if len(sys.argv) < 3:
parser.print_help()
exit()
if args.user is not None and args.IP is None:
print("Please specify user, application and IP.")
print("Current situation: user={0}, application={1}, IP={2}".
format(args.user, args.application, args.IP))
parser.print_help()
exit()
return args


def read_config():
with open(CONFIG_FILE) as f:
config_file = f.readlines()
user_application_file = config_file[0].rstrip()
user_application_db = []
offset = 0
with open(user_application_file) as f:
for line in f.readlines():
if line.strip() == "":
continue
ua = line.split()
nr = int(ua[2]) if len(ua) > 2 else 1
user_application_db.append({'user': ua[0], 'application': ua[1],
'nr': nr, 'offset': offset})
offset += nr
tiers = {}
for line in config_file[1:]:
tier, client, filename = line.split()
tiers[tier] = {'client': client, 'filename': filename}
# print(user_application_db)
# print(tiers)
return user_application_db, tiers


def fid2str(fid):
return "0x{0:x}:0x{1:x}".format(fid['f_container'], fid['f_key'])


def regenerate(tier_name, tier_file, client, no_ssh):
# with open('/tmp/tier2.json') as f:
# tier_json = json.load(f)
hctl_mero_status = subprocess.check_output(
([] if no_ssh else ["ssh", client]) +
"hctl mero status --json".split())
tier_json = json.loads(hctl_mero_status)
clients = {h[1]['crnProcesses'][0][0]['r_endpoint'].split('@')[0]:
h[1]['crnProcesses']
for h in tier_json['csrHosts']
# for h in tier_json['csrHosts'] if "client" in h[0]
}
tier_data = {}
for ip in clients:
profile = tier_json['csrProfile']
ha_endpoint = [h[0]['r_endpoint']
for h in clients[ip]
if h[1]['cprType'].strip() == 'halon'][0]
applications = sorted([{'endpoint': h[0]['r_endpoint'],
'process_fid': h[0]['r_fid']}
for h in clients[ip]
if h[1]['cprType'] == 'clovis-app'],
key=lambda k: k['endpoint'])
tier_data[ip] = {'profile': profile,
'ha': ha_endpoint,
'applications': applications}
tier_data['pools'] = tier_json['csrSnsPools']
with open(tier_file, 'w') as f:
json.dump(tier_data, f)


def load_tier_data(tiers):
data = {}
for t in tiers:
with open(tiers[t]['filename']) as f:
tier_data = json.load(f)
data.update(tier_data)
return data


def format_simple(args, params):
# print("{0} {1}".format(args.user, args.application));
for p in params:
print("{0} {1} {2} {3}".format(p['endpoint'], p['ha'],
p['profile'], p['process_fid']))


def format_as_needed(args, params):
print(f'''#
# USER: {args.user}
# Application: {args.application}
#
HA_ENDPOINT_ADDR = {params[0]['ha']}
PROFILE_FID = {params[0]['profile']}
''')

for p in enumerate(params[0]['pools']):
print(f'M0_POOL_TIER{p[0]+1} = {p[1][0]} # {p[1][1]}')

for p in enumerate(params):
print(f'''
LOCAL_ENDPOINT_ADDR{p[0]} = {p[1]['endpoint']}
LOCAL_PROC_FID{p[0]} = {p[1]['process_fid']}''')


def main():
args = parse_args()
user_application_db, tiers = read_config()
if args.tier is not None:
for t in args.tier:
regenerate(t, tiers[t]['filename'], tiers[t]['client'],
args.no_ssh)
sys.exit(0)
data = load_tier_data(tiers)
for u in user_application_db:
if u['user'] == args.user and u['application'] == args.application:
break
else:
print("No such user='{0}' application='{1}' combination.".
format(args.user, args.application))
print("This is what we have:")
print(user_application_db)
exit(1)
IPs = sorted([ip for ip in data.keys() if ip != 'pools'])
if args.IP not in IPs:
print("No such IP the list of available IPs:")
print(IPs)
exit(1)
d = data[args.IP]
app_nr_max = len(d['applications'])
if app_nr_max < u['offset'] + u['nr']:
print("Only {0} applications can be run on the client {1}, but "
"user {2} with application {3} has offset {4} and requests {5}".
format(app_nr_max, args.IP, args.user, args.application,
u['offset'], u['nr']))
exit(1)
params = [{'ha': d['ha'],
'profile': d['profile'],
'endpoint': app['endpoint'],
'process_fid': app['process_fid'],
'pools': data['pools'],
}
for app in d['applications'][u['offset']:u['offset'] + u['nr']]]
if (args.json):
print(json.dumps(params))
elif (args.simple):
format_simple(args, params)
else:
format_as_needed(args, params)


if __name__ == '__main__':
main()

0 comments on commit 923080f

Please sign in to comment.