nl_tokens: Called with this bound to the caller
pl_tokens: function joinCluster ( provider , bigIp , masterIid , options ) { const TEMP_USER_NAME_LENGHTH = 10 ; // these are hex bytes - user name will be 20 chars const TEMP_USER_PASSWORD_LENGTH = 24 ; // use a multiple of 6 to prevent '=' at the end const now = new Date ( ) ; let managementIp ; let tempPassword ; let tempUser ; if ( ! masterIid ) { return q . reject ( new Error ( 'Must have a master ID to join' ) ) ; } // don't send request too often - master might be in process of syncing this . instance . lastJoinRequest = this . instance . lastJoinRequest || new Date ( 1970 , 0 ) ; const elapsedMsFromLastJoin = now - new Date ( this . instance . lastJoinRequest ) ; if ( elapsedMsFromLastJoin < MIN_MS_BETWEEN_JOIN_REQUESTS ) { logger . silly ( 'Join request is too soon after last join request.' , elapsedMsFromLastJoin , 'ms' ) ; return q ( ) ; } logger . <mask> ( 'Joining cluster.' ) ; if ( provider . hasFeature ( CloudProvider . FEATURE_MESSAGING ) ) { this . instance . lastJoinRequest = now ; return provider . putInstance ( this . instanceId , this . instance ) . then ( ( response ) => { logger . debug ( response ) ; logger . debug ( 'Resetting current device trust' ) ; return bigIp . cluster . resetTrust ( ) ; } ) . then ( ( response ) => { logger . debug ( response ) ; // Make sure we don't have a current copy of the device group return bigIp . cluster . deleteDeviceGroup ( options . deviceGroup ) ; } ) . then ( ( response ) => { logger . debug ( response ) ; return bigIp . deviceInfo ( ) ; } ) . then ( ( response ) => { managementIp = response . managementAddress ; // Get a random user name to use return cryptoUtil . generateRandomBytes ( TEMP_USER_NAME_LENGHTH , 'hex' ) ; } ) . then ( ( respomse ) => { tempUser = respomse ; // Get a random password for the user return cryptoUtil . generateRandomBytes ( TEMP_USER_PASSWORD_LENGTH , 'base64' ) ; } ) . then ( ( response ) => { tempPassword = response ; // Create the temp user account return bigIp . onboard . updateUser ( tempUser , tempPassword , 'admin' ) ; } ) . then ( ( ) => { logger . debug ( 'Sending message to join cluster.' ) ; const messageData = { host : managementIp , port : bigIp . port , username : tempUser , password : tempPassword , hostname : this . instance . hostname , deviceGroup : options . deviceGroup } ; return prepareMessageData . call ( this , provider , masterIid , JSON . stringify ( messageData ) ) ; } ) . then ( ( preppedData ) => { if ( preppedData ) { return provider . sendMessage ( CloudProvider . MESSAGE_ADD_TO_CLUSTER , { toInstanceId : masterIid , fromInstanceId : this . instanceId , data : preppedData } ) ; } logger . debug ( 'No encrypted data received' ) ; return q ( ) ; } ) . catch ( ( err ) => { // need to bubble up nested errors return q . reject ( err ) ; } ) ; } // not using messaging, just send the request via iControl REST const masterInstance = this . instances [ masterIid ] ; this . instance . lastJoinRequest = now ; return provider . putInstance ( this . instanceId , this . instance ) . then ( ( response ) => { logger . debug ( response ) ; logger . debug ( 'Resetting current device trust' ) ; return bigIp . cluster . resetTrust ( ) ; } ) . then ( ( response ) => { logger . debug ( response ) ; // Make sure we don't have a current copy of the device group return bigIp . cluster . deleteDeviceGroup ( options . deviceGroup ) ; } ) . then ( ( response ) => { logger . debug ( response ) ; return provider . getMasterCredentials ( masterInstance . mgmtIp , options . port ) ; } ) . then ( ( credentials ) => { logger . debug ( 'Sending request to join cluster.' ) ; return bigIp . cluster . joinCluster ( options . deviceGroup , masterInstance . mgmtIp , credentials . username , credentials . password , false , { remotePort : options . port } ) ; } ) ; }