Ejemplo n.º 1
0
def handle(name, cloud_config, cloud, log, args):
    """Cloud-init processing function"""
    onboard_status = SUCCESS
    try:
        if not wait_for_do_to_complete():
            LOG.error('f5-declarative-onboarding has failed')
            onboard_status = ERROR
    except Exception as err:
        LOG.error(
            'onboard exception prior to f5-declarative-onboard declaration - %s',
            err)
        onboard_status = ERROR

    if os.path.exists(CLOUD_CONFIG_FILE):
        # read config
        phone_home_url = None
        if 'phone_home_url' in cloud_config[name]:
            LOG.info('phone_home_url from module %s found', name)
            phone_home_url = cloud_config[name]['phone_home_url']

        phone_home_url_verify_tls = True
        if 'phone_home_url_verify_tls' in cloud_config[name]:
            phone_home_url_verify_tls = cloud_config[name][
                'phone_home_url_verify_tls']

        phone_home_url_metadata = {}
        if 'phone_home_url_metadata' in cloud_config[name]:
            phone_home_url_metadata = cloud_config[name][
                'phone_home_url_metadata']

        phone_home_cli = None
        if 'phone_home_cli' in cloud_config[name]:
            phone_home_cli = cloud_config[name]['phone_home_cli']

        post_onboard_enabled = False
        if 'post_onboard_enabled' in cloud_config[name]:
            post_onboard_enabled = bool(
                cloud_config[name]['post_onboard_enabled'])

        if post_onboard_enabled and onboard_status == SUCCESS:
            if not runs_post_onboard_commands(name):
                onboard_status = ERROR

        # call phone_home
        if phone_home_url:
            tmos_onboard_utils.phone_home(phone_home_url, True, False, False,
                                          onboard_status,
                                          phone_home_url_verify_tls,
                                          phone_home_url_metadata)

        if phone_home_cli and onboard_status == SUCCESS:
            tmos_onboard_utils.run_cmd(phone_home_cli)

    clean()

    LOG.info('onboarding ended with status: %s', onboard_status)
Ejemplo n.º 2
0
def handle(name, cloud_config, cloud, log, args):
    """Cloud-init processing function"""
    tag = MODULE_NAME
    # force /PLATFORM to KVM generic
    with open('/PLATFORM', 'w') as platform:
        platform.write(
            "platform=Z100\nfamily=0xC0000000\nhost=Z100\nsystype=0x71\n")
    # find SSH key in vendor_data file
    if os.path.exists(VENDOR_DATA_RAW_FILE):
        LOG.debug('attempting to extract SSH key from vendor_data')
        public_keys = []
        with open(VENDOR_DATA_RAW_FILE, 'r') as vdf:
            for line in vdf:
                if 'ssh-rsa' in line:
                    public_keys.append(line[line.index('ssh-rsa'):])
        if public_keys:
            LOG.debug('injecting %d SSH authorized keys for root' %
                      len(public_keys))
            tmos_onboard_utils.inject_public_ssh_keys(public_keys)
            # randomize root and admin accounts
            LOG.debug('randomizing default account passwords')
            root_password = '******' + ''.join([
                random.choice(string.ascii_letters + string.digits)
                for n in range(32)
            ]) + '\n'
            try:
                util.subp(['chpasswd'], root_password)
            except Exception as e:
                LOG.error('failed to randomize password for root user: %s', e)
            admin_password = '******' + ''.join([
                random.choice(string.ascii_letters + string.digits)
                for n in range(32)
            ]) + '\n'
            try:
                util.subp(['chpasswd'], admin_password)
            except Exception as e:
                LOG.error('failed to randomize password for admin user: %s', e)
    try:
        # forcing hostname from metadata file
        if "local-hostname" in cloud.datasource.metadata:
            LOG.debug('forcing localhost name to %s' %
                      cloud.datasource.metadata['local-hostname'])
            tmos_onboard_utils.wait_for_mcpd()
            tmos_onboard_utils.run_cmd(
                "tmsh modify sys global-settings hostname %s.local" %
                cloud.datasource.metadata['local-hostname'])
    except Exception as ex:
        LOG.debug('exception setting hostname from metadata: %s', ex)
Ejemplo n.º 3
0
def handle(name, cloud_config, cloud, log, args):
    """Cloud-init processing function"""
    onboard_status = SUCCESS
    try:
        if wait_for_do_to_complete():
            # reset restnoded to over come AS3 issue
            # https://github.com/F5Networks/f5-appsvcs-extension/issues/108
            tmos_onboard_utils.bigstart_restart('restnoded')
            tmos_onboard_utils.wait_for_icontrollx()

            if tmos_onboard_utils.ts_declaration_persisted() and (
                    not onboard_status == ERROR):
                ts_available = False
                for _ in range(5):
                    if tmos_onboard_utils.wait_for_rest_worker(
                            '/mgmt/shared/telemetry/declare', timeout=30):
                        ts_available = True
                        break
                    time.sleep(1)
                if ts_available:
                    # check if there was a previous declaration.. if so don't issue
                    response = tmos_onboard_utils.get_ts_declaration()
                    # we have to check the format of the reponse because AS3
                    # does not assure the response is valid JSON
                    if hasattr(response, 'status_code'):
                        if response.status_code == 204 or response.status_code == 200:
                            LOG.info(
                                'making initial f5-telemetry-streaming declaration'
                            )
                            ts_declared = tmos_onboard_utils.ts_declare()
                            if not ts_declared:
                                LOG.error(
                                    'f5-telemetry-streaming inital declaration failed'
                                )
                                onboard_status = ERROR
                            else:
                                LOG.info(
                                    'f5-telemetry-streaming initial declaration submitted successfully'
                                )
                        else:
                            LOG.warn(
                                'f5-telemetry-streaming has a previously errored declaration, not deploying'
                            )
                            onboard_status = ERROR
                    else:
                        LOG.error(
                            'f5-telemetry-streaming has failed, not deploying initial declaration declaration %s - %s',
                            response.status_code, response.text)
                        onboard_status = ERROR
                else:
                    LOG.error(
                        'f5-telemetry-streaming never became available.. timeout...'
                    )
                    LOG.error(
                        'check /var/log/restnoded/restnoded.log for errors')
                    onboard_status = ERROR

            if tmos_onboard_utils.as3_declaration_persisted() and (
                    not onboard_status == ERROR):
                as3_available = False
                for _ in range(5):
                    if tmos_onboard_utils.wait_for_rest_worker(
                            '/mgmt/shared/appsvcs/declare', timeout=30):
                        as3_available = True
                        break
                    time.sleep(1)

                if as3_available:
                    # check if there was a previous declaration.. if so don't issue
                    response = tmos_onboard_utils.get_as3_declaration()
                    if hasattr(response, 'status_code'):
                        # we have to check the format of the reponse because AS3
                        # does not assure the response is valid JSON
                        if response.status_code == 204 or response.status_code == 200:
                            LOG.info(
                                'making initial f5-appsvcs-extension declaration'
                            )
                            as3_declared = tmos_onboard_utils.as3_declare()
                            if not as3_declared:
                                LOG.error(
                                    'f5-appsvcs-extension inital declaration failed'
                                )
                                onboard_status = ERROR
                            else:
                                LOG.info(
                                    'f5-appsvcs-extension initial declaration submitted successfully'
                                )
                        else:
                            LOG.warn(
                                'f5-appsvcs-extension has a previously errored declaration, not deploying'
                            )
                            onboard_status = ERROR
                    else:
                        LOG.error(
                            'f5-appsvcs-extension has failed, not deploying initial declaration declaration %s - %s',
                            response.status_code, response.text)
                        onboard_status = ERROR
                else:
                    LOG.error(
                        'f5-appsvcs-extension never became available.. timeout...'
                    )
                    LOG.error(
                        'check /var/log/restnoded/restnoded.log for errors')
                    onboard_status = ERROR
        else:
            LOG.error(
                'f5-declarative-onboarding has failed, not deploying f5-appsvcs-extension initial declaration'
            )
            onboard_status = ERROR
    except Exception as err:
        LOG.error(
            'onboard exception prior to f5-appsvcs-extension declaration - %s',
            err)

    if os.path.exists(CLOUD_CONFIG_FILE):
        # read config
        phone_home_url = None
        if 'phone_home_url' in cloud_config[name]:
            LOG.info('phone_home_url from module %s found', name)
            phone_home_url = cloud_config[name]['phone_home_url']

        phone_home_url_verify_tls = True
        if 'phone_home_url_verify_tls' in cloud_config[name]:
            phone_home_url_verify_tls = cloud_config[name][
                'phone_home_url_verify_tls']

        phone_home_url_metadata = {}
        if 'phone_home_url_metadata' in cloud_config[name]:
            phone_home_url_metadata = cloud_config[name][
                'phone_home_url_metadata']

        phone_home_cli = None
        if 'phone_home_cli' in cloud_config[name]:
            phone_home_cli = cloud_config[name]['phone_home_cli']

        post_onboard_enabled = False
        if 'post_onboard_enabled' in cloud_config[name]:
            post_onboard_enabled = bool(
                cloud_config[name]['post_onboard_enabled'])

        if post_onboard_enabled and onboard_status == SUCCESS:
            if not runs_post_onboard_commands(name):
                onboard_status = ERROR

        # call phone_home
        if phone_home_url:
            tmos_onboard_utils.phone_home(
                phone_home_url, True,
                tmos_onboard_utils.ts_declaration_persisted(),
                tmos_onboard_utils.as3_declaration_persisted(), onboard_status,
                phone_home_url_verify_tls, phone_home_url_metadata)
        if phone_home_cli and onboard_status == SUCCESS:
            tmos_onboard_utils.run_cmd(phone_home_cli)

    clean()

    LOG.info('onboarding ended with status: %s', onboard_status)
def onboard(trusted_sources, icontrollx_package_urls, phone_home_url,
            phone_home_url_verify_tls, phone_home_cli):
    """Implements the onboarding business logic"""
    onboard_script = TMSH_CMD_FILE_DIR + '/onboard.sh'
    if os.path.isfile(onboard_script):
        util.del_file(onboard_script)
    script_files = os.listdir(TMSH_CMD_FILE_DIR)
    script_files.sort()
    with open(onboard_script, 'w') as obs:
        obs.write("#!/bin/bash\n\n")
        obs.write("function check_mcpd_up() {\n")
        obs.write("    checks=0\n")
        obs.write("    while [ $checks -lt 120 ]; do\n")
        obs.write(
            "        if tmsh -a show sys mcp-state field-fmt 2> /dev/null | grep -q running; then\n"
        )
        obs.write("            break\n")
        obs.write("        fi\n")
        obs.write("        echo 'waiting for mcpd to reach running state'\n")
        obs.write("        let checks=checks+1\n")
        obs.write("        sleep 10\n")
        obs.write("    done\n")
        obs.write("}\n\n")
        obs.write("function exec_phases() {\n")
        for script_file in script_files:
            obs.write("    /bin/bash %s/%s\n" %
                      (TMSH_CMD_FILE_DIR, script_file))
        obs.write("}\n\n")
        obs.write("check_mcpd_up\n")
        obs.write("exec_phases\n")
        obs.write("echo 1 > " + ONBOARD_COMPLETE_FLAG_FILE + '\n')
    os.chmod(onboard_script, 0775)
    with open(LOG_FILE, 'a+') as onboardlog:
        subprocess.call(['nohup', 'sh', '-c', onboard_script, '&'],
                        stdout=onboardlog,
                        stderr=onboardlog)
    end_time = time.time() + ONBOARD_TIMEOUT
    while (end_time - time.time()) > 0:
        if not os.path.exists(ONBOARD_COMPLETE_FLAG_FILE):
            time.sleep(1)
        else:
            for ext_url in icontrollx_package_urls:
                LOG.info('downloading: %s', ext_url)
                if tmos_onboard_utils.download_extension(ext_url):
                    LOG.info(
                        'extension %s downloaded in discovered iControl extensions',
                        ext_url)
                else:
                    LOG.error('exenstion %s could not be donwloaded', ext_url)
            end_time = 0
            tmos_onboard_utils.install_extensions(trusted_sources)
    onboard_status = 'SUCCESS'

    if not os.path.exists(ONBOARD_COMPLETE_FLAG_FILE):
        LOG.error('Onboarding scripts failed to complete...exiting')
        onboard_status = ERROR

    if phone_home_url:
        tmos_onboard_utils.phone_home(phone_home_url, False, False,
                                      onboard_status,
                                      phone_home_url_verify_tls)

    if phone_home_cli and onboard_status == SUCCESS:
        tmos_onboard_utils.run_cmd(phone_home_cli)

    LOG.info('onboarding ended with status: %s', onboard_status)
Ejemplo n.º 5
0
def onboard(do_declaration, as3_declaration, ts_declaration, trusted_sources,
            post_onboard_enabled, post_onboard_commands, phone_home_url,
            phone_home_url_verify_tls, phone_home_url_metadata,
            phone_home_cli):
    """Implements the onboarding business logic"""

    do_enabled = True
    if do_declaration:
        try:
            tmos_onboard_utils.persist_do_declaration(do_declaration, None)
        except Exception as err:
            LOG.error(
                'could not persist f5-declarative-onboarding declaration: %s',
                err)
            do_enabled = False
    else:
        do_enabled = False

    ts_enabled = True
    if ts_declaration:
        try:
            tmos_onboard_utils.persist_ts_declaration(ts_declaration)
        except Exception as err:
            LOG.error(
                'could not persist f5-telemetry-streaming declaration %s', err)
            ts_enabled = False
    else:
        as3_enabled = False

    as3_enabled = True
    if as3_declaration:
        try:
            tmos_onboard_utils.persist_as3_declaration(as3_declaration)
        except Exception as err:
            LOG.error('could not persist f5-appsvcs-extension declaration %s',
                      err)
            as3_enabled = False
    else:
        as3_enabled = False

    if post_onboard_enabled:
        tmsh_cmd_dir_exists()
        create_post_onboard_script(post_onboard_commands)
        create_post_onboard()

    if not tmos_onboard_utils.is_mgmt_ip:
        LOG.debug('waiting on mgmt interface provisioning to complete')
        tmos_onboard_utils.wait_for_mgmt_dhcp(timeout=600)

    LOG.debug('waiting for mcpd to become available')
    tmos_onboard_utils.wait_for_mcpd()

    LOG.debug('waiting for iControl to become available')
    tmos_onboard_utils.wait_for_icontrol()

    LOG.info('installing discovered iControl LX extensions')
    tmos_onboard_utils.install_extensions(trusted_sources)

    if do_enabled or ts_enabled or as3_enabled:
        icontrol_available = False
        for _ in range(5):
            if tmos_onboard_utils.wait_for_icontrollx(timeout=30):
                icontrol_available = True
                break
            time.sleep(1)
        if not icontrol_available:
            LOG.error('iControl LX never became available.. timeout...')
            LOG.error('check /var/log/restnoded/restnoded.log for errors')
            LOG.error('disabling iControl LX declarations..')
            do_enabled = False
            as3_enabled = False

        LOG.debug('waiting for iControl LX interfaces to be available')
        tmos_onboard_utils.wait_for_icontrollx()

    do_posted = False
    if do_enabled:
        do_available = False
        for _ in range(5):
            if tmos_onboard_utils.wait_for_rest_worker(
                    '/mgmt/shared/declarative-onboarding', timeout=30):
                do_available = True
                break
            time.sleep(1)
        if do_available:
            if tmos_onboard_utils.do_declare():
                do_posted = True
        else:
            LOG.error(
                'f5-declarative-onboarding never became available.. timeout...'
            )
            LOG.error('check /var/log/restnoded/restnoded.log for errors')

    onboard_status = SUCCESS
    if do_enabled and not do_posted:
        # DO enabled, initial post failed (bad declaration syntax)
        # fail the phone_home_url
        onboard_status = ERROR
    elif do_posted and (ts_enabled or as3_enabled):
        # DO enabled, posted async, need to background AS3 - phone home deferred to background AS3 process
        run_declarations_deffered()
        return
    elif do_posted and not (ts_enabled or as3_enabled):
        run_do_wait()
        return
    elif ts_enabled or as3_enabled:
        # DO not enabled, run AS3 declaration now
        # reset restnoded to over come AS3 issue
        # https://github.com/F5Networks/f5-appsvcs-extension/issues/108
        tmos_onboard_utils.bigstart_restart('restnoded')
        tmos_onboard_utils.wait_for_icontrollx()

        if ts_enabled and (not onboard_status == ERROR):
            ts_available = False
            for _ in range(5):
                if tmos_onboard_utils.wait_for_rest_worker(
                        '/mgmt/shared/telemetry/declare', timeout=30):
                    ts_available = True
                    break
                time.sleep(1)
            if ts_available:
                # check if there was a previous declaration.. if so don't issue
                response = tmos_onboard_utils.get_ts_declaration()
                # we have to check the format of the reponse because AS3
                # does not assure the response is valid JSON
                if hasattr(response, 'status_code'):
                    if response.status_code == 204 or response.status_code == 200:
                        LOG.info(
                            'making initial f5-telemetry-streaming declaration'
                        )
                        ts_declared = tmos_onboard_utils.ts_declare()
                        if not ts_declared:
                            LOG.error(
                                'f5-telemetry-streaming inital declaration failed'
                            )
                            onboard_status = ERROR
                        else:
                            LOG.info(
                                'f5-telemetry-streaming initial declaration submitted successfully'
                            )
                            if post_onboard_enabled:
                                if not run_post_onboard_commands:
                                    onboard_status = ERROR
                    else:
                        LOG.warn(
                            'f5-telemetry-streaming has a previously errored declaration, not deploying'
                        )
                        onboard_status = ERROR
                else:
                    LOG.error(
                        'f5-telemetry-streaming has failed, not deploying initial declaration declaration %s - %s',
                        response.status_code, response.text)
                    onboard_status = ERROR
            else:
                LOG.error(
                    'f5-telemetry-streaming never became available.. timeout...'
                )
                LOG.error('check /var/log/restnoded/restnoded.log for errors')
                onboard_status = ERROR

        if as3_enabled and (not onboard_status == ERROR):
            # this logic was added because AS3 performs hidden tasks
            # after it is started that can only be assured when
            # AS3 endpoint returns a response
            as3_available = False
            for _ in range(5):
                if tmos_onboard_utils.wait_for_rest_worker(
                        '/mgmt/shared/appsvcs/declare', timeout=30):
                    as3_available = True
                    break
                time.sleep(1)

            if as3_available:
                # check if there was a previous declaration.. if so don't issue
                response = tmos_onboard_utils.get_as3_declaration()
                # we have to check the format of the reponse because AS3
                # does not assure the response is valid JSON
                if hasattr(response, 'status_code'):
                    if response.status_code == 204 or response.status_code == 200:
                        LOG.info(
                            'making initial f5-appsvcs-extension declaration')
                        as3_declared = tmos_onboard_utils.as3_declare()
                        if not as3_declared:
                            LOG.error(
                                'f5-appsvcs-extension inital declaration failed'
                            )
                            onboard_status = ERROR
                        else:
                            LOG.info(
                                'f5-appsvcs-extension initial declaration submitted successfully'
                            )
                            if post_onboard_enabled:
                                if not run_post_onboard_commands:
                                    onboard_status = ERROR
                    else:
                        LOG.warn(
                            'f5-appsvcs-extension has a previously errored declaration, not deploying'
                        )
                        onboard_status = ERROR
                else:
                    LOG.error(
                        'f5-appsvcs-extension has failed, not deploying initial declaration declaration %s - %s',
                        response.status_code, response.text)
                    onboard_status = ERROR
            else:
                LOG.error(
                    'f5-appsvcs-extension never became available.. timeout...')
                LOG.error('check /var/log/restnoded/restnoded.log for errors')
                onboard_status = ERROR
    else:
        # neither DO or AS3 enabled
        if post_onboard_enabled:
            if not run_post_onboard_commands():
                onboard_status = ERROR

    if phone_home_url:
        tmos_onboard_utils.phone_home(phone_home_url, do_enabled, ts_enabled,
                                      as3_enabled, onboard_status,
                                      phone_home_url_verify_tls,
                                      phone_home_url_metadata)
    if phone_home_cli and onboard_status == SUCCESS:
        tmos_onboard_utils.run_cmd(phone_home_cli)

    LOG.info('onboarding ended with status: %s', onboard_status)