示例#1
0
def auth_account(data):
    """Auth account.
    data = {'name':, 'pass'}
    """
    b_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 b_ret

    d = ast.literal_eval(r.value)
    # check state.
    if d.get('state') and d.get('state') == 'Disabled':
        return (False, 'Disabled')
    elif d.get('state') and d.get('state') == 'Locked':
        return (False, 'Locked')
    elif 'state' not in d or d.get('state') != 'Enabled':
        return (False, 'UnknownError')
    # check expireAt
    if datetime.utcnow().isoformat() > d.get('expireAt'):
        return (False, 'Expired')

    s_pass = bcrypt.hashpw(data['pass'].encode(), 
                           d['salt'].encode()).decode()

    if s_pass != d['pass']:
        return (False, 'PasswordMismatch')

    s_role = d['role'] if 'role' in d else 'user'

    return (True, s_role)
示例#2
0
def admin_auth_account(data):
    """Authenticate admin account.
    data = {'name':, 'pass':}
    """
    b_ret = False
    s_rsc = '{}/account/{}'.format(etcdc.prefix, data['name'])
    try:
        r = etcdc.read(s_rsc)
    except etcd.EtcdKeyNotFound as e:
        log.debug(e)
        # auth against config file.
        s_pass = bcrypt.hashpw(data['pass'].encode(), 
                               ADMIN_SALT.encode()).decode()
        log.debug(data['name'] + ':' + s_pass)
        if data['name'] == ADMIN_ID and s_pass == ADMIN_PW:
            # Add admin entry in etcd and return True.
            d = dict()
            d['name'] = ADMIN_ID
            d['pass'] = data['pass']
            d['cn'] = 'Admin'
            d['role'] = 'admin'
            d['state'] = 'Enabled'
            s_expire = (datetime.now() + timedelta(days=90)).isoformat() + 'Z'
            d['expireAt'] = s_expire
            (b_ret, s_msg) = create_account(d)
            return b_ret
        else:
            return False
    else:
        d = ast.literal_eval(r.value)
        s_pass = bcrypt.hashpw(data['pass'].encode(), 
                               d['salt'].encode()).decode()
        return data['name'] == ADMIN_ID and s_pass == d['pass']
示例#3
0
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
示例#4
0
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
示例#5
0
def get_tenant(edge_name=None, name=None):
    """Get tenant list.
    """
    l_tenant = list()
    if name is None:
        s_rsc = '{}/tenant'.format(etcdc.prefix)
    else:
        s_rsc = '{}/tenant/{}'.format(etcdc.prefix, name)

    try:
        r = etcdc.read(s_rsc, recursive=True, sorted=True)
    except etcd.EtcdKeyNotFound as e:
        log.error(e)
    else:
        for child in r.children:
            if child.value is not None:
                d = ast.literal_eval(child.value)
                if edge_name is None:
                    l_tenant.append(d)
                else:
                    if d['edge'] == edge_name:
                        # Get app list for the tenant
                        app_rsc = '{}/app'.format(etcdc.prefix)
                        try:
                            app_r = etcdc.read(app_rsc, recursive=True)
                        except etcd.EtcdKeyNotFound as e:
                            log.error(e)
                        else:
                            d['app'] = list()
                            for child in app_r.children:
                                if child.value is not None:
                                    app = ast.literal_eval(child.value)
                                    if d['name'] == app['tenant']:
                                        d_tmp = {
                                            'name': app['name'],
                                            'logo': app['cat_logo'],
                                            'type': app['cat_type'],
                                            'user': app['user'],
                                            'status': app['status'],
                                            'desc': app['desc']
                                        }
                                        d['app'].append(d_tmp)
                            d['app'] = sorted(d['app'],
                                              key=lambda k: k['name'])
                            l_tenant.append(d)
    finally:
        return l_tenant
示例#6
0
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
示例#7
0
def operate_app(name, action):
    """Run app."""
    if not (name and action):
        return (False, 'App name and action should be specified.')

    t_ret = (False, '')

    # Get edge from app
    s_rsc = '{}/app/{}'.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
    else:
        d = ast.literal_eval(r.value)
    s_edge = d['edge']

    # Get endpoint from s_edge.
    s_rsc = '{}/edge/{}'.format(etcdc.prefix, s_edge)
    try:
        r = etcdc.read(s_rsc)
    except etcd.EtcdKeyNotFound as e:
        log.error(e)
        t_ret = (False, e)
        return t_ret
    else:
        d = ast.literal_eval(r.value)
    s_endpoint = d['endpoint']

    # Run an app.
    CMD = "/usr/local/bin/kubectl-virt --kubeconfig " + PROJECT_ROOT + '/' + d['endpoint'] \
            + ' {} '.format(action) + name
    t_ret = cmd(CMD, 5, False)
    log.debug(t_ret)

    return t_ret
示例#8
0
def get_tenant_info(name):
    """Get tenant info
    """
    d_tenant = dict()
    if name is None:
        return (False, 'tenant name should be specified.')

    s_rsc = '{}/tenant/{}'.format(etcdc.prefix, name)

    try:
        r = etcdc.read(s_rsc)
    except etcd.EtcdKeyNotFound as e:
        log.error(e)
    else:
        d_tenant = ast.literal_eval(r.value)
    finally:
        return (True, d_tenant)
示例#9
0
def get_dashboard(name=None):
    """Get dashboard information
    """
    l_edge = list()
    if name is None:
        s_rsc = '{}/edge'.format(etcdc.prefix)
    else:
        s_rsc = '{}/edge/{}'.format(etcdc.prefix, name)

    try:
        r = etcdc.read(s_rsc, recursive=True, sorted=True)
    except etcd.EtcdKeyNotFound as e:
        log.error(e)
    else:
        for child in r.children:
            d = ast.literal_eval(child.value)
            l_edge.append(d)
    finally:
        return l_edge
示例#10
0
def get_catalog(name=None):
    """Get catalog list.
    """
    l_catalog = list()
    if name is None:
        s_rsc = '{}/catalog'.format(etcdc.prefix)
    else:
        s_rsc = '{}/catalog/{}'.format(etcdc.prefix, name)

    try:
        r = etcdc.read(s_rsc, recursive=True, sorted=True)
    except etcd.EtcdKeyNotFound as e:
        log.error(e)
    else:
        for child in r.children:
            if child.value is not None:
                d = ast.literal_eval(child.value)
                l_catalog.append(d)
    finally:
        return l_catalog
示例#11
0
def get_account(name=None):
    """Get account list.
    """
    l_account = list()
    if name is None:  # get all account.
        s_rsc = '{}/account'.format(etcdc.prefix)
    else:
        s_rsc = '{}/account/{}'.format(etcdc.prefix, name)

    try: 
        r = etcdc.read(s_rsc, recursive=True, sorted=True)
    except etcd.EtcdKeyNotFound as e:
        log.error(e)
    else:
        for child in r.children:
            if child.value is not None:
                # need to use ast to convert str to dict.
                d = ast.literal_eval(child.value)
                l_account.append(d)
    finally:
        return l_account
示例#12
0
def _pass_validate(data):
    """password validation
    * check if pass is not in old pass entry.
    """
    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)

    s_pass = bcrypt.hashpw(data['pass'].encode(), 
                           d['salt'].encode()).decode()
    if s_pass == d['pass']:
        return (False, 'NewPasswordSameAsCurrentPassword')

    if 'oldpass' in d:
        for s_oldpass in d['oldpass']:
            if s_oldpass == s_pass:
                return (False, 'PasswordPreviouslyUsed')

    return (True, 'PasswordMatched')
示例#13
0
def get_app(name=None, user=None):
    """Get app list.
    """
    l_app = list()
    if name is None:
        s_rsc = '{}/app'.format(etcdc.prefix)
    else:
        s_rsc = '{}/app/{}'.format(etcdc.prefix, name)

    try:
        r = etcdc.read(s_rsc, recursive=True, sorted=True)
    except etcd.EtcdKeyNotFound as e:
        log.error(e)
    else:
        for child in r.children:
            if child.value is not None:
                d = ast.literal_eval(child.value)
                if user is None:
                    l_app.append(d)
                else:
                    if user == d['user']:
                        l_app.append(d)
    finally:
        return l_app
示例#14
0
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
示例#15
0
def connect_app(name):
    """Return app connection URL."""
    if not name:
        return (False, 'App name should be specified.')

    t_ret = (False, '')

    # Get user from app
    s_rsc = '{}/app/{}'.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
    else:
        d = ast.literal_eval(r.value)
    s_user = d['user']

    if d['cat_type'] == 'vm':
        # Get tenant from user
        s_rsc = '{}/account/{}'.format(etcdc.prefix, s_user)
        try:
            r = etcdc.read(s_rsc)
        except etcd.EtcdKeyNotFound as e:
            log.error(e)
            t_ret = (False, e)
            return t_ret
        else:
            d = ast.literal_eval(r.value)
        s_tenant = d['tenant']

        # Get edge from tenant
        s_rsc = '{}/tenant/{}'.format(etcdc.prefix, s_tenant)
        try:
            r = etcdc.read(s_rsc)
        except etcd.EtcdKeyNotFound as e:
            log.error(e)
            t_ret = (False, e)
            return t_ret
        else:
            d = ast.literal_eval(r.value)
        s_edge = d['edge']

        # Get broker from edge
        s_rsc = '{}/edge/{}'.format(etcdc.prefix, s_edge)
        try:
            r = etcdc.read(s_rsc)
        except etcd.EtcdKeyNotFound as e:
            log.error(e)
            t_ret = (False, e)
            return t_ret
        else:
            d = ast.literal_eval(r.value)
        #s_broker = d['broker'] + '/guacamole/#/client/' + name
        s_broker = d['broker'] + '/ktedge/#/client/' + name
    elif d['cat_type'] == 'container':
        # Get .status.loadBalancer.ingress[0].ip
        # for now just return harden.iorchard.co.kr:40080
        s_broker = 'harden.iorchard.co.kr:40080'

    t_ret = (True, s_broker)
    return t_ret
示例#16
0
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')