vishesh92 commented on code in PR #11654:
URL: https://github.com/apache/cloudstack/pull/11654#discussion_r2371711043


##########
engine/userdata/src/main/java/org/apache/cloudstack/userdata/UserDataManagerImpl.java:
##########
@@ -137,7 +139,11 @@ public String validateAndGetUserDataForSystemVM(String 
userDataUuid) {
             return null;
         }
         if (userDataVo.getDomainId() == Domain.ROOT_DOMAIN && 
userDataVo.getAccountId() == User.UID_ADMIN) {
-            return userDataVo.getUserData();
+            // Decode base64 user data, compress it, then re-encode to reduce 
command line length

Review Comment:
   I used an AI tool to generate some sample user data and check.
   
   <details><summary>sample user data</summary>
   <p>
   
   // Test Case 1: Basic cloud-config with package installation
               String basicCloudConfig = "#cloud-config\n" +
                   "packages:\n" +
                   "  - nginx\n" +
                   "  - docker.io\n" +
                   "  - git\n" +
                   "  - curl\n" +
                   "  - vim\n" +
                   "  - htop\n" +
                   "write_files:\n" +
                   "  - content: |\n" +
                   "      Hello World!\n" +
                   "      This is a test file.\n" +
                   "    path: /home/ubuntu/hello.txt\n" +
                   "    permissions: '0644'\n" +
                   "runcmd:\n" +
                   "  - systemctl enable nginx\n" +
                   "  - systemctl start nginx\n" +
                   "  - echo 'Setup complete' > /var/log/setup.log\n";
               results.add(new TestResult("Basic cloud-config", 
basicCloudConfig));
               
               // Test Case 2: Complex cloud-config with users, SSH keys, and 
services
               String complexCloudConfig = "#cloud-config\n" +
                   "users:\n" +
                   "  - name: devuser\n" +
                   "    groups: sudo,docker\n" +
                   "    shell: /bin/bash\n" +
                   "    sudo: ['ALL=(ALL) NOPASSWD:ALL']\n" +
                   "    ssh_authorized_keys:\n" +
                   "      - ssh-rsa 
AAAAB3NzaC1yc2EAAAADAQABAAABgQC7vbqajDhubzjWkNo6HLx4ySHp8IfEtJSVo7tP9q2RhYKzL8AzL1v7M2dKwGHGJ8EwPdMzBgU5tS+v8pEo+1nV5+VWOq0W4MtL
 [email protected]\n" +
                   "      - ssh-rsa 
AAAAB3NzaC1yc2EAAAADAQABAAABgQDEfGHIjKlMnOpQrStUvWxYz+TcX9mZYHdRqO8VwGtQ2r4E6z4E+1mWq8vEP2qR4zZwGhYd8fGhIjKlMnOpQrStUvWxYz
 [email protected]\n" +
                   "packages:\n" +
                   "  - nginx\n" +
                   "  - docker.io\n" +
                   "  - docker-compose\n" +
                   "  - git\n" +
                   "  - curl\n" +
                   "  - wget\n" +
                   "  - vim\n" +
                   "  - nano\n" +
                   "  - htop\n" +
                   "  - tree\n" +
                   "  - jq\n" +
                   "  - unzip\n" +
                   "  - python3-pip\n" +
                   "  - nodejs\n" +
                   "  - npm\n" +
                   "write_files:\n" +
                   "  - content: |\n" +
                   "      upstream backend {\n" +
                   "          server 127.0.0.1:3000;\n" +
                   "          server 127.0.0.1:3001;\n" +
                   "      }\n" +
                   "      server {\n" +
                   "          listen 80;\n" +
                   "          location / {\n" +
                   "              proxy_pass http://backend;\n"; +
                   "              proxy_set_header Host $host;\n" +
                   "              proxy_set_header X-Real-IP $remote_addr;\n" +
                   "              proxy_set_header X-Forwarded-For 
$proxy_add_x_forwarded_for;\n" +
                   "              proxy_set_header X-Forwarded-Proto 
$scheme;\n" +
                   "          }\n" +
                   "      }\n" +
                   "    path: /etc/nginx/sites-available/default\n" +
                   "    permissions: '0644'\n" +
                   "  - content: |\n" +
                   "      #!/bin/bash\n" +
                   "      # Application deployment script\n" +
                   "      set -e\n" +
                   "      cd /opt/app\n" +
                   "      git clone https://github.com/company/webapp.git .\n" +
                   "      npm install\n" +
                   "      npm run build\n" +
                   "      pm2 start ecosystem.config.js\n" +
                   "    path: /usr/local/bin/deploy-app.sh\n" +
                   "    permissions: '0755'\n" +
                   "  - content: |\n" +
                   "      version: '3.8'\n" +
                   "      services:\n" +
                   "        redis:\n" +
                   "          image: redis:alpine\n" +
                   "          ports:\n" +
                   "            - \"6379:6379\"\n" +
                   "          volumes:\n" +
                   "            - redis_data:/data\n" +
                   "        postgres:\n" +
                   "          image: postgres:13\n" +
                   "          environment:\n" +
                   "            POSTGRES_DB: myapp\n" +
                   "            POSTGRES_USER: myuser\n" +
                   "            POSTGRES_PASSWORD: mypassword\n" +
                   "          volumes:\n" +
                   "            - postgres_data:/var/lib/postgresql/data\n" +
                   "          ports:\n" +
                   "            - \"5432:5432\"\n" +
                   "      volumes:\n" +
                   "        redis_data:\n" +
                   "        postgres_data:\n" +
                   "    path: /opt/docker-compose.yml\n" +
                   "    permissions: '0644'\n" +
                   "runcmd:\n" +
                   "  - mkdir -p /opt/app\n" +
                   "  - chown devuser:devuser /opt/app\n" +
                   "  - systemctl enable nginx\n" +
                   "  - systemctl start nginx\n" +
                   "  - systemctl enable docker\n" +
                   "  - systemctl start docker\n" +
                   "  - usermod -aG docker devuser\n" +
                   "  - npm install -g pm2\n" +
                   "  - cd /opt && docker-compose up -d\n" +
                   "  - /usr/local/bin/deploy-app.sh\n" +
                   "  - echo 'Complex setup complete' > /var/log/setup.log\n" +
                   "bootcmd:\n" +
                   "  - echo 'Starting cloud-init setup' > 
/var/log/bootcmd.log\n" +
                   "final_message: |\n" +
                   "  Cloud-init setup completed successfully!\n" +
                   "  Services started:\n" +
                   "  - nginx\n" +
                   "  - docker\n" +
                   "  - postgresql\n" +
                   "  - redis\n" +
                   "  - webapp\n";
               results.add(new TestResult("Complex cloud-config", 
complexCloudConfig));
               
               // Test Case 3: Shell script userdata
               String shellScript = "#!/bin/bash\n" +
                   "# Comprehensive server setup script\n" +
                   "set -e\n" +
                   "\n" +
                   "# Update system\n" +
                   "apt-get update\n" +
                   "apt-get upgrade -y\n" +
                   "\n" +
                   "# Install essential packages\n" +
                   "apt-get install -y \\\n" +
                   "    nginx \\\n" +
                   "    docker.io \\\n" +
                   "    docker-compose \\\n" +
                   "    git \\\n" +
                   "    curl \\\n" +
                   "    wget \\\n" +
                   "    vim \\\n" +
                   "    htop \\\n" +
                   "    tree \\\n" +
                   "    jq \\\n" +
                   "    unzip \\\n" +
                   "    python3-pip \\\n" +
                   "    nodejs \\\n" +
                   "    npm \\\n" +
                   "    certbot \\\n" +
                   "    python3-certbot-nginx\n" +
                   "\n" +
                   "# Configure firewall\n" +
                   "ufw allow OpenSSH\n" +
                   "ufw allow 'Nginx Full'\n" +
                   "ufw --force enable\n" +
                   "\n" +
                   "# Create application user\n" +
                   "useradd -m -s /bin/bash appuser\n" +
                   "usermod -aG sudo,docker appuser\n" +
                   "\n" +
                   "# Setup application directory\n" +
                   "mkdir -p /opt/webapp\n" +
                   "chown appuser:appuser /opt/webapp\n" +
                   "\n" +
                   "# Configure nginx\n" +
                   "cat > /etc/nginx/sites-available/default <<'EOF'\n" +
                   "server {\n" +
                   "    listen 80;\n" +
                   "    server_name _;\n" +
                   "    \n" +
                   "    location / {\n" +
                   "        proxy_pass http://127.0.0.1:3000;\n"; +
                   "        proxy_http_version 1.1;\n" +
                   "        proxy_set_header Upgrade $http_upgrade;\n" +
                   "        proxy_set_header Connection 'upgrade';\n" +
                   "        proxy_set_header Host $host;\n" +
                   "        proxy_set_header X-Real-IP $remote_addr;\n" +
                   "        proxy_set_header X-Forwarded-For 
$proxy_add_x_forwarded_for;\n" +
                   "        proxy_set_header X-Forwarded-Proto $scheme;\n" +
                   "        proxy_cache_bypass $http_upgrade;\n" +
                   "    }\n" +
                   "    \n" +
                   "    location /health {\n" +
                   "        access_log off;\n" +
                   "        return 200 \"healthy\\n\";\n" +
                   "        add_header Content-Type text/plain;\n" +
                   "    }\n" +
                   "}\n" +
                   "EOF\n" +
                   "\n" +
                   "# Create monitoring script\n" +
                   "cat > /usr/local/bin/monitor.sh <<'EOF'\n" +
                   "#!/bin/bash\n" +
                   "# Simple monitoring script\n" +
                   "while true; do\n" +
                   "    echo \"$(date): System status check\"\n" +
                   "    echo \"CPU: $(cat /proc/loadavg)\"\n" +
                   "    echo \"Memory: $(free -h | grep '^Mem')\"\n" +
                   "    echo \"Disk: $(df -h / | tail -n1)\"\n" +
                   "    echo \"---\"\n" +
                   "    sleep 300\n" +
                   "done\n" +
                   "EOF\n" +
                   "chmod +x /usr/local/bin/monitor.sh\n" +
                   "\n" +
                   "# Install Node.js LTS\n" +
                   "curl -fsSL https://deb.nodesource.com/setup_lts.x | sudo -E 
bash -\n" +
                   "apt-get install -y nodejs\n" +
                   "\n" +
                   "# Install PM2 for process management\n" +
                   "npm install -g pm2\n" +
                   "\n" +
                   "# Setup systemd service for monitoring\n" +
                   "cat > /etc/systemd/system/monitor.service <<'EOF'\n" +
                   "[Unit]\n" +
                   "Description=System Monitor\n" +
                   "After=network.target\n" +
                   "\n" +
                   "[Service]\n" +
                   "Type=simple\n" +
                   "User=root\n" +
                   "ExecStart=/usr/local/bin/monitor.sh\n" +
                   "Restart=always\n" +
                   "RestartSec=10\n" +
                   "\n" +
                   "[Install]\n" +
                   "WantedBy=multi-user.target\n" +
                   "EOF\n" +
                   "\n" +
                   "# Enable services\n" +
                   "systemctl daemon-reload\n" +
                   "systemctl enable nginx\n" +
                   "systemctl enable docker\n" +
                   "systemctl enable monitor\n" +
                   "\n" +
                   "# Start services\n" +
                   "systemctl start nginx\n" +
                   "systemctl start docker\n" +
                   "systemctl start monitor\n" +
                   "\n" +
                   "# Log completion\n" +
                   "echo \"$(date): Server setup completed successfully\" > 
/var/log/setup-complete.log\n" +
                   "echo \"Setup completed at $(date)\" | wall\n";
               results.add(new TestResult("Shell script userdata", 
shellScript));
               
               // Test Case 4: Cloud-boothook
               String cloudBoothook = "#cloud-boothook\n" +
                   "#!/bin/bash\n" +
                   "# This runs very early in the boot process\n" +
                   "echo 'Cloud-boothook executed at' $(date) >> 
/var/log/cloud-boothook.log\n" +
                   "\n" +
                   "# Set hostname\n" +
                   "hostnamectl set-hostname webapp-server\n" +
                   "\n" +
                   "# Configure timezone\n" +
                   "timedatectl set-timezone UTC\n" +
                   "\n" +
                   "# Disable swap\n" +
                   "swapoff -a\n" +
                   "sed -i '/ swap / s/^/#/' /etc/fstab\n" +
                   "\n" +
                   "# Kernel parameter tuning\n" +
                   "echo 'net.ipv4.ip_forward=1' >> /etc/sysctl.conf\n" +
                   "echo 'net.bridge.bridge-nf-call-iptables=1' >> 
/etc/sysctl.conf\n" +
                   "echo 'net.bridge.bridge-nf-call-ip6tables=1' >> 
/etc/sysctl.conf\n" +
                   "echo 'vm.max_map_count=262144' >> /etc/sysctl.conf\n" +
                   "sysctl -p\n" +
                   "\n" +
                   "# Create directories\n" +
                   "mkdir -p /opt/app/{config,logs,data}\n" +
                   "mkdir -p /var/cache/app\n" +
                   "\n" +
                   "echo 'Cloud-boothook setup completed' >> 
/var/log/cloud-boothook.log\n";
               results.add(new TestResult("Cloud-boothook", cloudBoothook));
               
               // Test Case 5: MIME multipart with mixed content types
               String mimeMultipart = "Content-Type: multipart/mixed; 
boundary=\"===============1234567890==\"\n" +
                   "MIME-Version: 1.0\n" +
                   "\n" +
                   "--===============1234567890==\n" +
                   "Content-Type: text/cloud-config; charset=\"us-ascii\"\n" +
                   "MIME-Version: 1.0\n" +
                   "Content-Transfer-Encoding: 7bit\n" +
                   "Content-Disposition: attachment; 
filename=\"cloud-config\"\n" +
                   "\n" +
                   "#cloud-config\n" +
                   "packages:\n" +
                   "  - docker.io\n" +
                   "  - docker-compose\n" +
                   "write_files:\n" +
                   "  - content: |\n" +
                   "      [Unit]\n" +
                   "      Description=My Application\n" +
                   "      After=docker.service\n" +
                   "      Requires=docker.service\n" +
                   "      \n" +
                   "      [Service]\n" +
                   "      Type=oneshot\n" +
                   "      RemainAfterExit=yes\n" +
                   "      WorkingDirectory=/opt/app\n" +
                   "      ExecStart=/usr/local/bin/docker-compose up -d\n" +
                   "      ExecStop=/usr/local/bin/docker-compose down\n" +
                   "      \n" +
                   "      [Install]\n" +
                   "      WantedBy=multi-user.target\n" +
                   "    path: /etc/systemd/system/myapp.service\n" +
                   "    permissions: '0644'\n" +
                   "\n" +
                   "--===============1234567890==\n" +
                   "Content-Type: text/x-shellscript; charset=\"us-ascii\"\n" +
                   "MIME-Version: 1.0\n" +
                   "Content-Transfer-Encoding: 7bit\n" +
                   "Content-Disposition: attachment; filename=\"setup.sh\"\n" +
                   "\n" +
                   "#!/bin/bash\n" +
                   "set -e\n" +
                   "\n" +
                   "# Create application structure\n" +
                   "mkdir -p /opt/app\n" +
                   "cd /opt/app\n" +
                   "\n" +
                   "# Create docker-compose.yml\n" +
                   "cat > docker-compose.yml <<EOF\n" +
                   "version: '3.8'\n" +
                   "services:\n" +
                   "  web:\n" +
                   "    image: nginx:alpine\n" +
                   "    ports:\n" +
                   "      - \"80:80\"\n" +
                   "    volumes:\n" +
                   "      - ./html:/usr/share/nginx/html:ro\n" +
                   "  app:\n" +
                   "    image: node:16-alpine\n" +
                   "    working_dir: /app\n" +
                   "    volumes:\n" +
                   "      - ./app:/app\n" +
                   "    command: npm start\n" +
                   "    environment:\n" +
                   "      - NODE_ENV=production\n" +
                   "EOF\n" +
                   "\n" +
                   "# Create basic HTML\n" +
                   "mkdir -p html\n" +
                   "echo '<h1>Welcome to My Application</h1>' > 
html/index.html\n" +
                   "\n" +
                   "# Set permissions\n" +
                   "chown -R 1000:1000 /opt/app\n" +
                   "\n" +
                   "# Enable and start service\n" +
                   "systemctl daemon-reload\n" +
                   "systemctl enable myapp.service\n" +
                   "systemctl start myapp.service\n" +
                   "\n" +
                   "echo 'Application setup completed'\n" +
                   "\n" +
                   "--===============1234567890==--\n";
               results.add(new TestResult("MIME multipart", mimeMultipart));
               
               // Test Case 6: Very repetitive configuration (should compress 
well)
               StringBuilder repetitiveConfig = new 
StringBuilder("#cloud-config\n");
               repetitiveConfig.append("write_files:\n");
               for (int i = 1; i <= 50; i++) {
                   repetitiveConfig.append("  - content: |\n");
                   repetitiveConfig.append("      #!/bin/bash\n");
                   repetitiveConfig.append("      # Configuration script " + i 
+ "\n");
                   repetitiveConfig.append("      echo 'Processing 
configuration " + i + "'\n");
                   repetitiveConfig.append("      mkdir -p /opt/config" + i + 
"\n");
                   repetitiveConfig.append("      echo 'Configuration " + i + " 
completed' > /opt/config" + i + "/status.txt\n");
                   repetitiveConfig.append("      chmod 755 /opt/config" + i + 
"\n");
                   repetitiveConfig.append("    path: /usr/local/bin/config" + 
i + ".sh\n");
                   repetitiveConfig.append("    permissions: '0755'\n");
               }
               repetitiveConfig.append("runcmd:\n");
               for (int i = 1; i <= 50; i++) {
                   repetitiveConfig.append("  - /usr/local/bin/config" + i + 
".sh\n");
               }
   
   </p>
   </details> 
   
   Based on the compression test results, here's the detailed size comparison 
table:
   
   1. **Original size**: Raw userdata string length
   2. **Base64 size**: Original string → Base64 encoded 
   3. **Compressed+Base64 size**: Original string → Gzip compressed → Base64 
encoded
   
   ## Userdata Compression Analysis Results
   
   | **Userdata Type** | **Original Size** | **Base64 Only** | **Gzip+Base64** 
| **Compression Ratio** | **Savings** |
   
|-------------------|-------------------|------------------|------------------|----------------------|-------------|
   | Basic cloud-config | 321 chars | 428 chars | 304 chars | 71.03% | 
**29.0%** |
   | Complex cloud-config | 2,628 chars | 3,504 chars | 1,572 chars | 44.86% | 
**55.1%** |
   | Shell script userdata | 2,484 chars | 3,312 chars | 1,492 chars | 45.05% | 
**55.0%** |
   | Cloud-boothook | 732 chars | 976 chars | 520 chars | 53.28% | **46.7%** |
   | MIME multipart | 1,741 chars | 2,324 chars | 1,036 chars | 44.58% | 
**55.4%** |
   | Repetitive config (50 scripts) | 16,163 chars | 21,552 chars | 1,728 chars 
| 8.02% | **92.0%** |
   



-- 
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