def update_account(name, data): """Update account. """ data = dict((k, v) for k, v in data.items() if v) t_ret = (False, '') if not name: # <name> should be specified. return t_ret s_rsc = '{}/account/{}'.format(etcdc.prefix, name) try: r = etcdc.read(s_rsc) except etcd.EtcdKeyNotFound as e: log.error(e) t_ret = (False, e) return t_ret d = ast.literal_eval(r.value) # Get iso 8601 format datetime for modified timestamp s_modified = datetime.utcnow().isoformat() + 'Z' # Put s_modified into data dict. data['modifiedAt'] = s_modified d.update(data.items()) try: etcdc.write(s_rsc, d, prevExist=True) except etcd.EtcdKeyNotFound as e: log.error(e) t_ret = (False, e) else: t_ret = (True, 'user {} is updated.'.format(name)) finally: return t_ret
def create_account(data): """Create account. etcd_key: <ETCD_PREFIX>/account/<name> """ t_ret = (False, '') s_rsc = '' # Create uid(uuid) for account s_uuid = str(uuid.uuid4()) # Get iso 8601 format datetime for created timestamp s_created = datetime.utcnow().isoformat() + 'Z' # Put s_created into data dict. data['createdAt'] = s_created data['uid'] = s_uuid bytes_salt = bcrypt.gensalt() data['pass'] = bcrypt.hashpw(str.encode(data['pass']), bytes_salt).decode() data['salt'] = bytes_salt.decode() s_rsc = '{}/account/{}'.format(etcdc.prefix, data['name']) log.debug(data) try: etcdc.write(s_rsc, data, prevExist=False) except etcd.EtcdKeyAlreadyExist as e: log.error(e) t_ret = (False, e) else: t_ret = (True, 'user {} is created.'.format(data['name'])) finally: return t_ret
def update_catalog(name, data): """Update catalog catalogPatchSerializer """ data = dict((k, v) for k, v in data.items() if v) t_ret = (False, '') if not name: return t_ret s_rsc = '{}/catalog/{}'.format(etcdc.prefix, name) try: r = etcdc.read(s_rsc) except etcd.EtcdKeyNotFound as e: log.error(e) t_ret = (False, e) return t_ret d = ast.literal_eval(r.value) data['modifiedAt'] = datetime.utcnow().isoformat() + 'Z' d.update(data.items()) try: etcdc.write(s_rsc, d, prevExist=True) except etcd.EtcdKeyAlreadyExist as e: log.error(e) t_ret = (False, e) else: t_ret = (True, 'catalog {} is updated.'.format(name)) finally: return t_ret
def create_catalog(data): """Create catalog catalogPostSerializer """ if not data.get('name'): return (False, 'Catalog name should be specified.') t_ret = (False, '') s_uuid = str(uuid.uuid4()) s_created = datetime.utcnow().isoformat() + 'Z' data['createdAt'] = s_created data['uid'] = s_uuid log.debug(data) s_rsc = '{}/catalog/{}'.format(etcdc.prefix, data['name']) try: etcdc.write(s_rsc, data, prevExist=False) except etcd.EtcdKeyAlreadyExist as e: log.error(e) t_ret = (False, e) else: t_ret = (True, 'etcd {} is created.'.format(data['name'])) finally: return t_ret
def user_password_account(data): """Modify user account password. etcd_key: <ETCD_PREFIX>/account/<name> data: {'name': , 'pass': , 'pass1': , 'pass2': } """ t_ret = (False, '') s_rsc = '{}/account/{}'.format(etcdc.prefix, data['name']) try: r = etcdc.read(s_rsc) except etcd.EtcdKeyNotFound as e: log.error(e) return (False, 'EtcdKeyNotFound') d = ast.literal_eval(r.value) # check if data['pass'] == d['pass'] s_pass = bcrypt.hashpw(data['pass'].encode(), d['salt'].encode()).decode() if s_pass != d['pass']: # current password mismatch return (False, 'Current password is not matched.') # since data['pass'] is matched, overwrite data['pass1'] to data['pass'] # to validate new password. data['pass'] = data['pass1'] (b_ret, s_msg) = _pass_validate(data) if not b_ret: log.debug((b_ret, s_msg)) return (b_ret, s_msg) # password is okay. go head. new_data = dict() s_modified = datetime.utcnow().isoformat() + 'Z' data['modifiedAt'] = s_modified # Put d['pass'] to oldpass entry. if 'oldpass' in d: d['oldpass'].append(d['pass']) else: d['oldpass'] = [d['pass']] # Create new hashed password. bytes_salt = bytes(d['salt'], 'utf-8') d['pass'] = bcrypt.hashpw(str.encode(data['pass']), bytes_salt).decode() s_rsc = '{}/account/{}'.format(etcdc.prefix, data['name']) try: etcdc.write(s_rsc, d, prevExist=True) except etcd.EtcdKeyNotFound as e: log.error(e) t_ret = (False, e) else: t_ret = (True, 'user {} password is modified.'.format(data['name'])) finally: return t_ret
def create_app(data): """Create app appPostSerializer """ if not data.get('name'): return (False, 'App name should be specified.') t_ret = (False, '') s_uuid = str(uuid.uuid4()) s_created = datetime.utcnow().isoformat() + 'Z' data['createdAt'] = s_created data['uid'] = s_uuid # Get catalog information from data['catalog'] s_catalog_rsc = '{}/catalog/{}'.format(etcdc.prefix, data['catalog']) try: r = etcdc.read(s_catalog_rsc) except etcd.EtcdKeyNotFound as e: log.error(e) return t_ret else: if r.value is not None: d = ast.literal_eval(r.value) log.debug(d) data['cpu_spec'] = d['cpu_spec'] data['mem_spec'] = d['mem_spec'] data['disk_spec'] = d['disk_spec'] + 1 data['image_url'] = d['image_url'] # Get type(vm or container) from data['catalog'] s_cat_rsc = '{}/catalog/{}'.format(etcdc.prefix, data['catalog']) try: r = etcdc.read(s_cat_rsc) except etcd.EtcdKeyNotFound as e: log.error(e) return t_ret else: if r.value is not None: d = ast.literal_eval(r.value) log.debug(d) data['cat_type'] = d['type'] data['cat_name'] = d['name'] else: return t_ret # Get tenant from data['user'] s_user_rsc = '{}/account/{}'.format(etcdc.prefix, data['user']) try: r = etcdc.read(s_user_rsc) except etcd.EtcdKeyNotFound as e: log.error(e) return t_ret else: if r.value is not None: d = ast.literal_eval(r.value) data['tenant'] = d['tenant'] # Get edge from tenant s_tenant_rsc = '{}/tenant/{}'.format(etcdc.prefix, d['tenant']) try: r = etcdc.read(s_tenant_rsc) except etcd.EtcdKeyNotFound as e: log.error(e) return t_ret else: if r.value is not None: d = ast.literal_eval(r.value) log.debug(d) data['edge'] = d['edge'] # Get edge endpoint s_edge_rsc = '{}/edge/{}'.format(etcdc.prefix, data['edge']) try: r = etcdc.read(s_edge_rsc) except etcd.EtcdKeyNotFound as e: log.error(e) return t_ret else: if r.value is not None: d = ast.literal_eval(r.value) log.debug(d) data['endpoint'] = d['endpoint'] s_kubeconfig = PROJECT_ROOT + '/' + data['endpoint'] if data['cat_type'] == 'vm': # Create VM image == app name <username>-<catalog>-<4_random_strings> # create vm manifest s_out = render_template('vm.j2', d=data) s_tpl = '{}/{}_vm.yaml'.format(KUBEMANIFEST, data['name']) try: with open(s_tpl, 'w') as f: f.write(s_out) except Exception as e: log.error(e) return (False, 'Cannot create a manifest file - {}.'.format(s_tpl)) else: # Run kubectl apply s_cmd = '{} --kubeconfig={} '.format(KUBECTL, s_kubeconfig) + \ 'apply -f {}'.format(s_tpl) log.debug(s_cmd) Popen(s_cmd, shell=True) # create vm service manifest s_out = render_template('svc.j2', d=data) s_tpl = '{}/{}_svc.yaml'.format(KUBEMANIFEST, data['name']) try: with open(s_tpl, 'w') as f: f.write(s_out) except Exception as e: log.error(e) return (False, 'Cannot create a manifest file - {}.'.format(s_tpl)) else: # Run kubectl apply s_cmd = '{} --kubeconfig={} '.format(KUBECTL, s_kubeconfig) + \ 'apply -f {}'.format(s_tpl) Popen(s_cmd, shell=True) elif data['cat_type'] == 'container': # Install using helm s_cmd = '{}/{}.sh install {} {}'.\ format(BIN_DIR, data['cat_name'], s_kubeconfig, data['name']) log.debug(s_cmd) Popen(s_cmd, shell=True) s_rsc = '{}/app/{}'.format(etcdc.prefix, data['name']) try: etcdc.write(s_rsc, data, prevExist=False) except etcd.EtcdKeyAlreadyExist as e: log.error(e) t_ret = (False, e) else: t_ret = (True, 'App {} is created.'.format(data['name'])) finally: return t_ret
def cli(): """Management script for collector.""" while True: try: # Get the whole information on each edge. l_edge = list() s_rsc = '{}/edge'.format(etcdc.prefix) try: r = etcdc.read(s_rsc, recursive=True) except etcd.EtcdKeyNotFound as e: log.error(e) else: for child in r.children: l_app = list() d = ast.literal_eval(child.value) # get hosts print(PROJECT_ROOT + '/' + d['endpoint']) l_hosts = kube_list_node(PROJECT_ROOT + '/' + d['endpoint']) d['hosts'] = len(l_hosts) d_nodes = dict() # {'name': 'ip', ...} for item in l_hosts: d_nodes[item.metadata. name] = item.status.addresses[0].address # log.debug(d_nodes) # get # of tenants and apps l_tenants = get_tenant(d['name']) d['tenants'] = len(l_tenants) d['apps'] = 0 for e in l_tenants: if 'app' in e: d['apps'] += len(e['app']) d['cpu'] = 0 d['memory'] = 0 i_total_cores = 0 i_total_memory = 0 i_total_storage = 0 for h in l_hosts: i_total_cores += int(h.status.capacity['cpu']) i_total_memory += int( h.status.capacity['memory'].replace('Ki', '')) d['tot_cpu'] = i_total_cores d['tot_mem'] = int(i_total_memory / (1024 * 1024)) # Get loadavg and free mem if d['name'] == 'edge1': ssh_server = 'harden.iorchard.co.kr' elif d['name'] == 'edge2': ssh_server = 'durant.iorchard.co.kr' RSC = 'ssh -p42544 {} get_rsc.sh'.format(ssh_server) (b_res, s_out) = cmd(RSC, 3, False) l = s_out.split("\n") d['used_cpu'] = (float(l[0]) + float(l[1]) + float(l[2])) avail_mem = (int(l[3]) + int(l[4]) + int(l[5])) / (1024 * 1024) d['used_mem'] = d['tot_mem'] - avail_mem d['cpu'] = int(d['used_cpu'] / d['tot_cpu'] * 100) d['memory'] = int(d['used_mem'] / d['tot_mem'] * 100) # ceph storage CEPH = "kubectl --kubeconfig " + PROJECT_ROOT + '/' \ + d['endpoint'] + " -n rook-ceph exec -it " \ + "$(kubectl --kubeconfig " + PROJECT_ROOT + '/' \ + d['endpoint'] + " -n rook-ceph get po " \ + "-l app=rook-ceph-tools " \ + "-o jsonpath='{.items[0].metadata.name}') -- " \ + "ceph df --format json" (b_res, s_out) = cmd(CEPH, 3, False) print(s_out) d['status'] = 'Healthy' if b_res else 'Unhealthy' d_stor = ast.literal_eval(s_out) d['tot_stor'] = int(d_stor['stats']['total_bytes'] / pow(1024, 3)) d['used_stor'] = int(d_stor['stats']['total_used_bytes'] / pow(1024, 3)) d['storage'] = int(d['used_stor'] / d['tot_stor'] * 100) # Update etcd status try: s = '{}/edge/{}'.format(etcdc.prefix, d['name']) # log.debug(d) etcdc.write(s, d, prevExist=True) except etcd.EtcdKeyNotFound as e: log.error(e) # Update app status s_app = '{}/app'.format(etcdc.prefix) try: r_app = etcdc.read(s_app, recursive=True) except etcd.EtcdKeyNotFound as e: log.error(e) else: for app_child in r_app.children: if app_child.value is not None: d_app = dict() app = ast.literal_eval(app_child.value) if app['edge'] == d['name']: d_app['name'] = app['name'] d_app['username'] = GUAC_USER d_app['password'] = GUAC_PASS # Get catalog info. s_cat = '{}/catalog/{}'.format( etcdc.prefix, app['catalog']) try: r_cat = etcdc.read(s_cat) except etcd.EtcdKeyNotFound as e: log.error(e) else: cat = ast.literal_eval(r_cat.value) app['cat_type'] = cat['type'] app['cat_name'] = cat['name'] app['cat_logo'] = cat['logo'] # Get app status if app['cat_type'] == 'vm': # first, look at DataVolume status of app. CMD = "kubectl --kubeconfig " + PROJECT_ROOT + '/' \ + d['endpoint'] + ' get dv ' \ + app['name'] \ + " -o jsonpath='{range .status}{.phase},{.progress}{end}'" (b_res, s_out) = cmd(CMD, 5, False) l_out = s_out.split(',') if l_out[0] == 'Succeeded': # Get vm status of app CMD = "kubectl --kubeconfig " + PROJECT_ROOT \ + '/' \ + d['endpoint'] + ' get vm ' \ + app['name'] \ + " -o jsonpath='{.status.ready}'" (b_res, s_out) = cmd(CMD, 5, False) if b_res and s_out == 'true': # update app status 'running'. app.update({'status': 'running'}) if app['edge'] == d['name']: # Get where app is running. CMD = "kubectl --kubeconfig " \ + PROJECT_ROOT + '/' \ + d['endpoint'] + ' get vmi ' \ + app['name'] \ + " -o jsonpath='{.status.nodeName}'" (b_res, s_out) = cmd(CMD, 5, False) if b_res: d_app[ 'hostname'] = d_nodes[ s_out] # Get nodeport for app. CMD = "kubectl --kubeconfig " \ + PROJECT_ROOT + '/' \ + d['endpoint'] + ' get svc ' \ + app['name'] \ + " -o jsonpath='{.spec.ports[0].nodePort}'" (b_res, s_out) = cmd(CMD, 5, False) if b_res: d_app['port'] = s_out else: # update app status 'stopped' app.update({'status': 'stopped'}) elif l_out[0] == 'ImportInProgress': # update app status 'building' and app.update({ 'status': 'building ({})'.format(l_out[1]) }) elif app['cat_type'] == 'container': app.update({'status': 'running'}) try: s = '{}/app/{}'.format( etcdc.prefix, app['name']) # log.debug(app) etcdc.write(s, app, prevExist=True) except etcd.EtcdKeyNotFound as e: log.error(e) if 'port' in d_app: l_app.append(d_app) # render guac-config.j2 and copy it to guac broker server log.debug(l_app) template = env.get_template('broker.j2') s_out = template.render(l_app=l_app) s_tmp = '/tmp/{}.broker'.format(d['name']) try: with open(s_tmp, 'w') as f: f.write(s_out) except Exception as e: log.error(e) else: CMD = "scp " \ + "-P42544 {} {}".format(s_tmp, d['broker_ip']) \ + ":/etc/guacamole/noauth-config.xml" log.debug(CMD) (b_res, s_out) = cmd(CMD, 5, False) if b_res: d_app['port'] = s_out l_edge.append(d) # log.debug(l_edge) log.debug(l_app) time.sleep(1) except: log.error('unknown error')