weizhouapache commented on a change in pull request #4890:
URL: https://github.com/apache/cloudstack/pull/4890#discussion_r712431532



##########
File path: setup/bindir/cloud-set-guest-sshkey-password-userdata-configdrive.in
##########
@@ -0,0 +1,507 @@
+#!/usr/bin/env bash
+
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.
+
+username=root
+userDataServerPort=8080
+configDriveLabel=config-2
+
+function findPrimaryNetwork(){
+    outputLog "Detecting primary network"
+    if command -v ip &> /dev/null
+    then
+        primaryNet=$(ip -o -4 route show to default | awk '{print $5}')
+    elif command -v netstat &> /dev/null
+    then
+        primaryNet=$(netstat -r4 | grep default | awk '{print $(NF)}')
+    elif command -v route &> /dev/null
+    then
+        primaryNet=$(route -4 2> /dev/null | grep default | awk '{print 
$(NF)}')
+        if [ -z "$primaryNet" ]
+        then
+            primaryNet=$(route get default 2> /dev/null | grep interface | tr 
-d ' ' | awk '{split($0,a,":"); print a[2]}')
+        fi
+    fi
+    if [ -z "$primaryNet" ]
+    then
+        outputLog "Could not find primary network"
+        return 1
+    fi
+    echo "$primaryNet"
+    return 0
+}
+
+function findUserDataServer(){
+    primaryNet=$1
+    outputLog "Trying to find userdata server"
+    if [ -z "$primaryNet" ]
+    then
+        outputLog "Unable to determine the userdata server, falling back to 
data-server"
+        echo "data-server"
+        return 0
+    fi
+
+    if command -v netplan &> /dev/null
+    then
+        outputLog "Operating System is using netplan"
+
+        userDataServer=$(netplan ip leases "$primaryNet" | grep SERVER_ADDRESS 
| awk '{split($0,a,"="); print a[2]}')
+
+        if [ -n "$userDataServer" ]
+        then
+            outputLog "Found userdata server IP $userDataServer in netplan 
config"
+            echo "$userDataServer"
+            return 0
+        fi
+    fi
+
+    if command -v nmcli &> /dev/null
+    then
+        outputLog "Operating System is using NetworkManager"
+
+        userDataServer=$(nmcli -t connection show "$(nmcli -t -f UUID,DEVICE 
connection | grep "$primaryNet" | awk '{split($0,a,":"); print a[1]}')" | grep 
next_server | tr -d ' ' |awk '{split($0,a,"="); print a[2]}')
+
+        if [ -n "$userDataServer" ]
+        then
+            outputLog "Found userdata server IP $userDataServer in 
NetworkManager config"
+            echo "$userDataServer"
+            return 0
+        fi
+    fi
+
+    if command -v wicked &> /dev/null
+    then
+        outputLog "Operating System is using wicked"
+
+        userDataServer=$(grep SERVERID /run/wicked/leaseinfo."$primaryNet"* | 
tr -d "'" | awk '{split($0,a,"="); print a[2]}')
+
+        if [ -n "$userDataServer" ]
+        then
+            outputLog "Found userdata server IP $userDataServer in wicked 
config"
+            echo "$userDataServer"
+            return 0
+        fi
+    fi
+
+    if command -v udhcpc &> /dev/null
+    then
+        outputLog "Operating System is using udhcpc"
+
+        userDataServer=$(< /run/dhcp-server-ip."$primaryNet")
+
+        if [ -n "$userDataServer" ]
+        then
+            outputLog "Found userdata server IP $userDataServer in udhcpc"
+            echo "$userDataServer"
+            return 0
+        fi
+    fi
+
+    outputLog "Searching for DHCP server in lease files"
+
+    primaryLease=$(
+        dhcpFolders="/var/lib/dhclient/* /var/lib/dhcp3/* /var/lib/dhcp/* 
/var/lib/NetworkManager/* /var/db/dhclient*"
+        for files in $dhcpFolders
+        do
+            if [ -e "$files" ]
+            then
+                < "$files" tr -d '\n' | sed 's/  //g ; s/lease {//g ; 
s/}/\n/g' | grep 'option routers'
+            fi
+        done
+    )
+
+    serverList=$(
+        IFS=$'\n'
+        for line in $(echo -e "$primaryLease")
+        do
+            splitLine=$(echo "$line" | sed -e 's/;/\n/g')
+            if date -j &> /dev/null
+            then
+                timestamp=$(date -j -f "%Y/%m/%d %H:%M:%S" "$(echo 
"$splitLine" | grep 'expire' | sed -r 's/.*expire [0-9]+ (.*)/\1/')" +"%s")
+            else
+                timestamp=$(date -d "$(echo "$splitLine" | grep 'expire' | sed 
-e 's/.*expire [0-9]\+ \(.*\)/\1/')" +"%s")
+            fi
+            interface=$(echo "$splitLine" | grep 'interface' | sed -e 
's/.*interface "\(.*\)"/\1/')
+            server=$(echo "$splitLine" | grep 'dhcp-server-identifier' | sed 
-e 's/.*dhcp-server-identifier \(.*\)/\1/')
+            echo "$timestamp","$interface","$server"
+        done
+    )
+
+    userDataServer=$(echo "$serverList" | grep "$primaryNet" | sort -n | tail 
-1 | awk '{split($0,a,","); print a[3]}')
+
+    if [ -n "$userDataServer" ]
+    then
+        outputLog "Userdata server found: $userDataServer"
+        echo "$userDataServer"
+        return 0
+    fi
+
+    outputLog "Unable to determine the userdata server, falling back to 
data-server"
+    echo "data-server"
+    return 0
+}
+
+function getPasswordFromUserDataServer(){
+    userDataServer=$1
+    userDataServerPort=$2
+    outputLog "Sending request to userdata server at $userDataServer to get 
the password"
+    if ! response=$(curl --silent --connect-timeout 20 --retry 3 --header 
"DomU_Request: send_my_password" http://"$userDataServer":"$userDataServerPort";)
+    then
+        outputLog "Failed to send request to userdata server at 
$userDataServer"
+        return 4
+    fi
+    outputLog "Got response from userdata server at $userDataServer"
+    response=$(echo "$response" | tr -d '\r')
+    case $response in
+        "")
+            outputLog "Userdata server at $userDataServer did not have any 
password for the VM"
+            return 2
+        ;;
+        "bad_request")
+            outputLog "VM sent an invalid request to userdata server at 
$userDataServer"
+            return 3
+        ;;
+        "saved_password")
+            outputLog "VM has already saved a password from the userdata 
server at $userDataServer"
+            return 1
+        ;;
+        *)
+            outputLog "VM got a valid password from server at $userDataServer"
+            echo "$response"
+            return 0
+    esac
+}
+
+function findHomeDirectory(){
+    username=$1
+    getent passwd "$username"|awk -F ":" '{print $6}'
+}
+
+function setPassword(){
+    username=$1
+    homeDir=$2
+    password=$3
+    if command -v md5sum &> /dev/null
+    then
+        newMd5=$(echo "$password" | md5sum | awk '{print $1}')
+    elif command -v md5 &> /dev/null
+    then
+        newMd5=$(echo "$password" | md5)
+    else
+        newMd5='N/A'
+    fi
+    if [ $newMd5 != 'N/A' ]
+    then
+        if [ -f "$homeDir"/.password.md5 ]
+        then
+            oldMd5=$(cat "$homeDir"/.password.md5)
+        fi
+        if [ "$newMd5" ==  "$oldMd5" ]
+        then
+            outputLog  "There is no update of VM password"
+            return 0
+        fi
+    else
+        outputLog "Cannot determine change of password"
+    fi
+    outputLog "Changing password for user $username"
+    if command -v chpasswd &> /dev/null
+    then
+        echo "$username":"$password" | chpasswd
+    elif command -v usermod &> /dev/null && command -v mkpasswd &> /dev/null
+    then
+        usermod -p "$(mkpasswd -m SHA-512 "$password")" "$username"
+    elif command -v pw &> /dev/null
+    then
+        echo "$password" | pw mod user "$username" -h 0
+    else
+        outputLog "Failed to change password for user $username"
+        return 1
+    fi
+    outputLog "Successfully changed password for user $username"
+    if [ $newMd5 != 'N/A' ]
+    then
+        echo "$newMd5" > "$homeDir"/.password.md5
+        chmod 600 "$homeDir"/.password.md5
+        chown "$username": "$homeDir"/.password.md5
+    fi
+    return 0
+}
+
+function sendAckToUserDataServer(){
+    userDataServer=$1
+    userDataServerPort=$2
+    outputLog "Sending acknowledgment to userdata server at $userDataServer"
+    if ! curl --silent --connect-timeout 20 --retry 3 --header "DomU_Request: 
saved_password" "$userDataServer":"$userDataServerPort" &> /dev/null
+    then
+        outputLog "Failed to sent acknowledgment to userdata server at 
$userDataServer"
+        return 1
+    fi
+    outputLog "Successfully sent acknowledgment to userdata server at 
$userDataServer"
+    return 0
+}
+
+function getPublicKeyFromUserDataServer(){
+    userDataServer=$1
+    outputLog "Sending request to userdata server at $userDataServer to get 
public key"
+    if ! reponse=$(curl --silent --connect-timeout 20 --retry 3 
http://"$userDataServer"/latest/public-keys)
+    then
+        outputLog "Failed to get public key from userdata server"
+        return 2
+    fi
+    outputLog "Got response from userdata server at $userDataServer"
+    if [ -z "$reponse" ]
+    then
+        outputLog "Did not receive any public keys from userdata server"
+        return 1
+    fi
+    outputLog "Successfully get public key from userdata server"
+    echo "$reponse"
+    return 0
+}
+
+function setPublicKey(){
+    username=$1
+    homeDir=$2
+    publicKey=$3
+    outputLog "Applying public key for $username"
+    sshDir=$homeDir/.ssh
+    authorizedKeysFile=$sshDir/authorized_keys
+
+    if [ ! -d "$sshDir" ]
+    then
+        outputLog ".ssh directory for $username not found, creating .ssh 
directory"
+        mkdir "$sshDir"
+    fi
+
+    if [ ! -f "$authorizedKeysFile" ]
+    then
+        outputLog "authorized_keys file for $username not found, creating 
authorized_keys file"
+        touch "$authorizedKeysFile"
+    fi
+    if grep "$(echo "$publicKey" | awk '{print $2}')" "$authorizedKeysFile" > 
/dev/null
+    then
+        outputLog "No need to update authorized_keys file"
+        return 0
+    fi
+    outputLog "Writing public key in authorized_keys file"
+    echo "$publicKey" >> "$authorizedKeysFile"

Review comment:
       @aleskxyz 
   can you use the same code ?
   ```
   sed -i "/ [email protected]$/d" $authorized
   echo "$publickey [email protected]" >> $authorized
   ```




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


Reply via email to