720 lines
26 KiB
TypeScript
720 lines
26 KiB
TypeScript
'use client'
|
|
|
|
import { useState } from 'react'
|
|
import { useRouter } from 'next/navigation'
|
|
import { Header } from '@/components/header'
|
|
import { Footer } from '@/components/footer'
|
|
import { Button } from '@/components/ui/button'
|
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
|
|
import { Input } from '@/components/ui/input'
|
|
import { Label } from '@/components/ui/label'
|
|
import {
|
|
Select,
|
|
SelectContent,
|
|
SelectItem,
|
|
SelectTrigger,
|
|
SelectValue,
|
|
} from '@/components/ui/select'
|
|
import { Checkbox } from '@/components/ui/checkbox'
|
|
import { Alert, AlertDescription } from '@/components/ui/alert'
|
|
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'
|
|
import {
|
|
Cloud,
|
|
Server,
|
|
HardDrive,
|
|
Shield,
|
|
AlertCircle,
|
|
Check,
|
|
Cpu,
|
|
MapPin,
|
|
ExternalLink,
|
|
Terminal,
|
|
} from 'lucide-react'
|
|
|
|
import { useAuth } from '@/contexts/AuthContext'
|
|
import { checkSufficientBalance, formatCurrency } from '@/lib/balance-service'
|
|
|
|
interface Plan {
|
|
id: string
|
|
name: string
|
|
price: {
|
|
daily: number
|
|
monthly: number
|
|
}
|
|
}
|
|
|
|
interface OSImage {
|
|
id: string
|
|
name: string
|
|
price?: {
|
|
daily: number
|
|
monthly: number
|
|
}
|
|
}
|
|
|
|
interface DataCenter {
|
|
id: string
|
|
name: string
|
|
}
|
|
|
|
interface DeploymentResult {
|
|
status: string
|
|
cloudid?: string
|
|
message?: string
|
|
password?: string
|
|
ipv4?: string
|
|
server_id?: string
|
|
error?: string
|
|
[key: string]: any
|
|
}
|
|
|
|
export default function CloudInstancePage() {
|
|
const router = useRouter()
|
|
const { user } = useAuth()
|
|
const [loading, setLoading] = useState(false)
|
|
const [error, setError] = useState('')
|
|
const [success, setSuccess] = useState('')
|
|
const [deploymentResult, setDeploymentResult] = useState<DeploymentResult | null>(null)
|
|
const [billingCycle, setBillingCycle] = useState<'daily' | 'monthly'>('monthly')
|
|
|
|
// Form state
|
|
const [formData, setFormData] = useState({
|
|
hostname: '',
|
|
planId: '',
|
|
image: '',
|
|
password: '',
|
|
dcslug: '',
|
|
enableBackup: false,
|
|
enablePublicIp: true,
|
|
})
|
|
|
|
// Available plans
|
|
const plans: Plan[] = [
|
|
{ id: '10027', name: '2 vCPU, 4GB RAM, 80GB SSD', price: { daily: 60, monthly: 1600 } },
|
|
{ id: '10028', name: '4 vCPU, 8GB RAM, 160GB SSD', price: { daily: 80, monthly: 2200 } },
|
|
{ id: '10029', name: '8 vCPU, 32GB RAM, 480GB SSD', price: { daily: 100, monthly: 2800 } },
|
|
{ id: '10030', name: '16 vCPU, 64GB RAM, 960GB SSD', price: { daily: 120, monthly: 3200 } },
|
|
]
|
|
|
|
// Available OS images
|
|
const images: OSImage[] = [
|
|
{ id: 'almalinux-9.2-x86_64', name: 'Alma Linux 9.2' },
|
|
{ id: 'centos-7.9-x86_64', name: 'CentOS 7.9' },
|
|
{ id: 'debian-12-x86_64', name: 'Debian 12' },
|
|
{ id: 'ubuntu-22.04-x86_64', name: 'Ubuntu 22.04 LTS' },
|
|
{ id: 'windows-2022', name: 'Windows Server 2022', price: { daily: 200, monthly: 5000 } },
|
|
]
|
|
|
|
// Data centers
|
|
const dataCenters: DataCenter[] = [
|
|
{ id: 'inmumbaizone2', name: 'Mumbai, India' },
|
|
{ id: 'inbangalore', name: 'Bangalore, India' },
|
|
]
|
|
|
|
// Get user balance from auth context
|
|
const userBalance = user?.balance || 0
|
|
|
|
// Calculate total price
|
|
const calculatePrice = () => {
|
|
const selectedPlan = plans.find((p) => p.id === formData.planId)
|
|
const selectedImage = images.find((i) => i.id === formData.image)
|
|
|
|
if (!selectedPlan) return 0
|
|
|
|
let total = selectedPlan.price[billingCycle]
|
|
|
|
// Add Windows license cost if applicable
|
|
if (selectedImage?.price) {
|
|
total += selectedImage.price[billingCycle]
|
|
}
|
|
|
|
// Add backup cost (20% of plan price)
|
|
if (formData.enableBackup) {
|
|
total += selectedPlan.price[billingCycle] * 0.2
|
|
}
|
|
|
|
return total
|
|
}
|
|
|
|
const handleDeploy = async (e: React.FormEvent) => {
|
|
e.preventDefault()
|
|
setError('')
|
|
setSuccess('')
|
|
setDeploymentResult(null)
|
|
|
|
if (!user) {
|
|
router.push('/auth?redirect=/services/cloud-instance')
|
|
return
|
|
}
|
|
|
|
// Validate form
|
|
if (
|
|
!formData.hostname ||
|
|
!formData.planId ||
|
|
!formData.image ||
|
|
!formData.password ||
|
|
!formData.dcslug
|
|
) {
|
|
setError('All fields are required')
|
|
return
|
|
}
|
|
|
|
// Check password strength
|
|
if (formData.password.length < 8) {
|
|
setError('Password must be at least 8 characters long')
|
|
return
|
|
}
|
|
|
|
// Check balance
|
|
const totalPrice = calculatePrice()
|
|
const balanceCheck = await checkSufficientBalance(totalPrice)
|
|
|
|
if (!balanceCheck.sufficient) {
|
|
setError(
|
|
balanceCheck.error ||
|
|
`Insufficient balance. You need ${formatCurrency(totalPrice)} but only have ${formatCurrency(balanceCheck.currentBalance || 0)}`
|
|
)
|
|
return
|
|
}
|
|
|
|
setLoading(true)
|
|
|
|
try {
|
|
const response = await fetch('/api/services/deploy-cloude', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
},
|
|
body: JSON.stringify({
|
|
hostname: formData.hostname,
|
|
planid: formData.planId,
|
|
image: formData.image,
|
|
dclocation: formData.dcslug,
|
|
password: formData.password,
|
|
cycle: billingCycle,
|
|
amount: totalPrice,
|
|
backup: formData.enableBackup,
|
|
publicip: formData.enablePublicIp,
|
|
}),
|
|
})
|
|
|
|
const result: DeploymentResult = await response.json()
|
|
|
|
if (!response.ok) {
|
|
throw new Error(result.message || `Deployment failed with status ${response.status}`)
|
|
}
|
|
|
|
if (result.status === 'success') {
|
|
setDeploymentResult(result)
|
|
|
|
// Create success message with server details
|
|
let successMessage = 'Cloud instance deployed successfully!'
|
|
if (result.cloudid) {
|
|
successMessage += ` Server ID: ${result.cloudid}`
|
|
}
|
|
if (result.ipv4) {
|
|
successMessage += ` | IP: ${result.ipv4}`
|
|
}
|
|
|
|
setSuccess(successMessage)
|
|
|
|
// Reset form after successful deployment
|
|
setFormData({
|
|
hostname: '',
|
|
planId: '',
|
|
image: '',
|
|
password: '',
|
|
dcslug: '',
|
|
enableBackup: false,
|
|
enablePublicIp: true,
|
|
})
|
|
} else {
|
|
throw new Error(result.message || 'Deployment failed')
|
|
}
|
|
} catch (err) {
|
|
console.error('Deployment error:', err)
|
|
setError(err instanceof Error ? err.message : 'Failed to deploy cloud instance')
|
|
} finally {
|
|
setLoading(false)
|
|
}
|
|
}
|
|
|
|
const resetForm = () => {
|
|
setDeploymentResult(null)
|
|
setSuccess('')
|
|
setError('')
|
|
}
|
|
|
|
return (
|
|
<div className="min-h-screen bg-background">
|
|
<Header />
|
|
|
|
<div className="container mx-auto px-4 pt-24 pb-16">
|
|
<div className="max-w-4xl mx-auto">
|
|
{/* Page Header */}
|
|
<div className="text-center mb-12">
|
|
<div className="inline-flex items-center justify-center w-16 h-16 bg-gradient-to-br from-blue-500 to-purple-600 rounded-full mb-4">
|
|
<Cloud className="w-8 h-8 text-white" />
|
|
</div>
|
|
<h1 className="text-4xl font-bold mb-4">Deploy Cloud Instance</h1>
|
|
<p className="text-xl text-muted-foreground">
|
|
High-performance cloud servers with instant deployment
|
|
</p>
|
|
</div>
|
|
|
|
{!user && (
|
|
<Alert className="mb-8">
|
|
<AlertCircle className="h-4 w-4" />
|
|
<AlertDescription>
|
|
You need to be logged in to deploy a cloud instance.{' '}
|
|
<a
|
|
href="/auth?redirect=/services/cloud-instance"
|
|
className="text-primary underline"
|
|
>
|
|
Click here to login
|
|
</a>
|
|
</AlertDescription>
|
|
</Alert>
|
|
)}
|
|
|
|
{success && (
|
|
<Alert className="mb-8 bg-green-50 border-green-200">
|
|
<Check className="h-4 w-4 text-green-600" />
|
|
<AlertDescription className="text-green-800">
|
|
<div className="space-y-3">
|
|
<div className="font-semibold">{success}</div>
|
|
|
|
{deploymentResult?.ipv4 && (
|
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 mt-3">
|
|
<div>
|
|
<Label className="text-sm font-medium text-green-700">
|
|
Server IP Address
|
|
</Label>
|
|
<div className="flex items-center mt-1">
|
|
<Input
|
|
className="font-mono text-sm bg-green-100 border-green-300"
|
|
value={deploymentResult.ipv4}
|
|
readOnly
|
|
/>
|
|
<Button
|
|
variant="outline"
|
|
size="sm"
|
|
className="ml-2"
|
|
onClick={() => {
|
|
navigator.clipboard.writeText(deploymentResult.ipv4!)
|
|
// You can add a toast notification here
|
|
}}
|
|
>
|
|
<ExternalLink className="h-4 w-4" />
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
|
|
<div>
|
|
<Label className="text-sm font-medium text-green-700">Server ID</Label>
|
|
<p className="text-sm font-mono bg-green-100 p-2 rounded border border-green-300 mt-1">
|
|
{deploymentResult.cloudid || deploymentResult.server_id}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
{deploymentResult?.password && (
|
|
<div className="mt-3">
|
|
<Label className="text-sm font-medium text-green-700">Root Password</Label>
|
|
<div className="flex items-center mt-1">
|
|
<Input
|
|
type="password"
|
|
className="font-mono text-sm bg-green-100 border-green-300"
|
|
value={deploymentResult.password}
|
|
readOnly
|
|
/>
|
|
<Button
|
|
variant="outline"
|
|
size="sm"
|
|
className="ml-2"
|
|
onClick={() => {
|
|
navigator.clipboard.writeText(deploymentResult.password!)
|
|
// You can add a toast notification here
|
|
}}
|
|
>
|
|
Copy
|
|
</Button>
|
|
</div>
|
|
<p className="text-xs text-green-600 mt-1">
|
|
Please change this password after first login
|
|
</p>
|
|
</div>
|
|
)}
|
|
|
|
{deploymentResult?.message && (
|
|
<div className="mt-3 p-3 bg-green-100 rounded-md">
|
|
<p className="text-sm text-green-700">{deploymentResult.message}</p>
|
|
</div>
|
|
)}
|
|
|
|
<div className="flex gap-3 mt-4 pt-3 border-t border-green-200">
|
|
<Button
|
|
onClick={() => router.push('/dashboard/instances')}
|
|
className="bg-green-600 hover:bg-green-700"
|
|
>
|
|
<Server className="w-4 h-4 mr-2" />
|
|
View All Instances
|
|
</Button>
|
|
|
|
<Button
|
|
variant="outline"
|
|
onClick={() => {
|
|
// SSH connection button - you can implement this
|
|
if (deploymentResult?.ipv4) {
|
|
const sshCommand = `ssh root@${deploymentResult.ipv4}`
|
|
navigator.clipboard.writeText(sshCommand)
|
|
// Show toast notification
|
|
}
|
|
}}
|
|
>
|
|
<Terminal className="w-4 h-4 mr-2" />
|
|
Copy SSH Command
|
|
</Button>
|
|
|
|
<Button variant="outline" onClick={resetForm}>
|
|
Deploy Another
|
|
</Button>
|
|
</div>
|
|
|
|
<div className="mt-4 text-xs text-green-600">
|
|
<p>✅ Deployment successful! Your server is being provisioned.</p>
|
|
{/* <p>📧 Login details will be sent to your email once ready.</p> */}
|
|
</div>
|
|
</div>
|
|
</AlertDescription>
|
|
</Alert>
|
|
)}
|
|
|
|
{deploymentResult ? (
|
|
<Card>
|
|
<CardHeader>
|
|
<CardTitle>Deployment Successful!</CardTitle>
|
|
<CardDescription>
|
|
Your cloud instance has been deployed successfully.
|
|
</CardDescription>
|
|
</CardHeader>
|
|
<CardContent className="space-y-4">
|
|
<div className="grid grid-cols-2 gap-4">
|
|
<div>
|
|
<Label>Server ID</Label>
|
|
<p className="text-sm font-mono bg-muted p-2 rounded">
|
|
{deploymentResult.server_id}
|
|
</p>
|
|
</div>
|
|
<div>
|
|
<Label>Status</Label>
|
|
<p className="text-sm capitalize">{deploymentResult.status}</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="flex gap-4">
|
|
<Button onClick={() => router.push('/dashboard/instances')}>
|
|
View Instances
|
|
</Button>
|
|
<Button variant="outline" onClick={resetForm}>
|
|
Deploy Another
|
|
</Button>
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
) : (
|
|
<form onSubmit={handleDeploy}>
|
|
<div className="space-y-8">
|
|
{/* Billing Cycle Selection */}
|
|
<Card>
|
|
<CardHeader>
|
|
<CardTitle>Billing Cycle</CardTitle>
|
|
<CardDescription>Choose your preferred billing period</CardDescription>
|
|
</CardHeader>
|
|
<CardContent>
|
|
<Tabs
|
|
value={billingCycle}
|
|
onValueChange={(v) => setBillingCycle(v as 'daily' | 'monthly')}
|
|
>
|
|
<TabsList className="grid w-full grid-cols-2">
|
|
<TabsTrigger value="daily">Daily</TabsTrigger>
|
|
<TabsTrigger value="monthly">Monthly (Save 20%)</TabsTrigger>
|
|
</TabsList>
|
|
</Tabs>
|
|
</CardContent>
|
|
</Card>
|
|
|
|
{/* Server Configuration */}
|
|
<Card>
|
|
<CardHeader>
|
|
<CardTitle>Server Configuration</CardTitle>
|
|
<CardDescription>Configure your cloud instance specifications</CardDescription>
|
|
</CardHeader>
|
|
<CardContent className="space-y-4">
|
|
<div>
|
|
<Label htmlFor="hostname">Hostname</Label>
|
|
<Input
|
|
id="hostname"
|
|
placeholder="my-server.example.com"
|
|
value={formData.hostname}
|
|
onChange={(e) => setFormData({ ...formData, hostname: e.target.value })}
|
|
required
|
|
/>
|
|
</div>
|
|
|
|
<div>
|
|
<Label htmlFor="plan">Server Plan</Label>
|
|
<Select
|
|
value={formData.planId}
|
|
onValueChange={(value) => setFormData({ ...formData, planId: value })}
|
|
>
|
|
<SelectTrigger>
|
|
<SelectValue placeholder="Select a plan" />
|
|
</SelectTrigger>
|
|
<SelectContent>
|
|
{plans.map((plan) => (
|
|
<SelectItem key={plan.id} value={plan.id}>
|
|
<div className="flex items-center justify-between w-full">
|
|
<span>{plan.name}</span>
|
|
<span className="ml-4 text-primary">
|
|
₹{plan.price[billingCycle]}/
|
|
{billingCycle === 'daily' ? 'day' : 'month'}
|
|
</span>
|
|
</div>
|
|
</SelectItem>
|
|
))}
|
|
</SelectContent>
|
|
</Select>
|
|
</div>
|
|
|
|
<div>
|
|
<Label htmlFor="image">Operating System</Label>
|
|
<Select
|
|
value={formData.image}
|
|
onValueChange={(value) => setFormData({ ...formData, image: value })}
|
|
>
|
|
<SelectTrigger>
|
|
<SelectValue placeholder="Select an OS" />
|
|
</SelectTrigger>
|
|
<SelectContent>
|
|
{images.map((image) => (
|
|
<SelectItem key={image.id} value={image.id}>
|
|
<div className="flex items-center justify-between w-full">
|
|
<span>{image.name}</span>
|
|
{image.price && (
|
|
<span className="ml-4 text-primary">
|
|
+₹{image.price[billingCycle]}/
|
|
{billingCycle === 'daily' ? 'day' : 'month'}
|
|
</span>
|
|
)}
|
|
</div>
|
|
</SelectItem>
|
|
))}
|
|
</SelectContent>
|
|
</Select>
|
|
</div>
|
|
|
|
<div>
|
|
<Label htmlFor="datacenter">Data Center</Label>
|
|
<Select
|
|
value={formData.dcslug}
|
|
onValueChange={(value) => setFormData({ ...formData, dcslug: value })}
|
|
>
|
|
<SelectTrigger>
|
|
<SelectValue placeholder="Select location" />
|
|
</SelectTrigger>
|
|
<SelectContent>
|
|
{dataCenters.map((dc) => (
|
|
<SelectItem key={dc.id} value={dc.id}>
|
|
<div className="flex items-center gap-2">
|
|
<MapPin className="w-4 h-4" />
|
|
{dc.name}
|
|
</div>
|
|
</SelectItem>
|
|
))}
|
|
</SelectContent>
|
|
</Select>
|
|
</div>
|
|
|
|
<div>
|
|
<Label htmlFor="password">Root Password</Label>
|
|
<Input
|
|
id="password"
|
|
type="password"
|
|
placeholder="Strong password (min 8 characters)"
|
|
value={formData.password}
|
|
onChange={(e) => setFormData({ ...formData, password: e.target.value })}
|
|
required
|
|
/>
|
|
<p className="text-xs text-muted-foreground mt-1">
|
|
Minimum 8 characters required
|
|
</p>
|
|
</div>
|
|
|
|
<div className="space-y-3">
|
|
<div className="flex items-center space-x-2">
|
|
<Checkbox
|
|
id="backup"
|
|
checked={formData.enableBackup}
|
|
onCheckedChange={(checked) =>
|
|
setFormData({ ...formData, enableBackup: checked as boolean })
|
|
}
|
|
/>
|
|
<Label htmlFor="backup" className="cursor-pointer">
|
|
Enable automatic backups (+20% of plan cost)
|
|
</Label>
|
|
</div>
|
|
|
|
<div className="flex items-center space-x-2">
|
|
<Checkbox
|
|
id="publicip"
|
|
checked={formData.enablePublicIp}
|
|
onCheckedChange={(checked) =>
|
|
setFormData({ ...formData, enablePublicIp: checked as boolean })
|
|
}
|
|
/>
|
|
<Label htmlFor="publicip" className="cursor-pointer">
|
|
Enable public IP address
|
|
</Label>
|
|
</div>
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
|
|
{/* Pricing Summary */}
|
|
<Card>
|
|
<CardHeader>
|
|
<CardTitle>Order Summary</CardTitle>
|
|
</CardHeader>
|
|
<CardContent>
|
|
<div className="space-y-2">
|
|
<div className="flex justify-between">
|
|
<span className="text-muted-foreground">Base Plan</span>
|
|
<span>
|
|
₹{plans.find((p) => p.id === formData.planId)?.price[billingCycle] || 0}
|
|
</span>
|
|
</div>
|
|
{images.find((i) => i.id === formData.image)?.price && (
|
|
<div className="flex justify-between">
|
|
<span className="text-muted-foreground">Windows License</span>
|
|
<span>
|
|
₹
|
|
{images.find((i) => i.id === formData.image)?.price?.[billingCycle] ||
|
|
0}
|
|
</span>
|
|
</div>
|
|
)}
|
|
{formData.enableBackup && (
|
|
<div className="flex justify-between">
|
|
<span className="text-muted-foreground">Backup Service</span>
|
|
<span>
|
|
₹
|
|
{(plans.find((p) => p.id === formData.planId)?.price[billingCycle] ||
|
|
0) * 0.2}
|
|
</span>
|
|
</div>
|
|
)}
|
|
<div className="border-t pt-2">
|
|
<div className="flex justify-between font-semibold">
|
|
<span>Total</span>
|
|
<span className="text-primary">
|
|
₹{calculatePrice()}/{billingCycle === 'daily' ? 'day' : 'month'}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
<div className="pt-2">
|
|
<div className="flex justify-between text-sm">
|
|
<span className="text-muted-foreground">Your Balance</span>
|
|
<span
|
|
className={
|
|
userBalance >= calculatePrice() ? 'text-green-600' : 'text-red-600'
|
|
}
|
|
>
|
|
₹{userBalance.toFixed(2)}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
|
|
{error && (
|
|
<Alert variant="destructive">
|
|
<AlertCircle className="h-4 w-4" />
|
|
<AlertDescription>{error}</AlertDescription>
|
|
</Alert>
|
|
)}
|
|
|
|
{/* Deploy Button */}
|
|
<Button type="submit" className="w-full" size="lg" disabled={loading || !user}>
|
|
{loading ? (
|
|
<>
|
|
<div className="animate-spin rounded-full h-4 w-4 border-b-2 border-white mr-2"></div>
|
|
Deploying...
|
|
</>
|
|
) : (
|
|
'Deploy Cloud Instance'
|
|
)}
|
|
</Button>
|
|
</div>
|
|
</form>
|
|
)}
|
|
|
|
{/* Features */}
|
|
{!deploymentResult && (
|
|
<div className="mt-16 grid md:grid-cols-3 gap-8">
|
|
<Card>
|
|
<CardHeader>
|
|
<Server className="w-8 h-8 text-primary mb-2" />
|
|
<CardTitle>High Performance</CardTitle>
|
|
</CardHeader>
|
|
<CardContent>
|
|
<p className="text-sm text-muted-foreground">
|
|
Enterprise-grade hardware with NVMe SSD storage
|
|
</p>
|
|
</CardContent>
|
|
</Card>
|
|
|
|
<Card>
|
|
<CardHeader>
|
|
<Shield className="w-8 h-8 text-primary mb-2" />
|
|
<CardTitle>Secure & Reliable</CardTitle>
|
|
</CardHeader>
|
|
<CardContent>
|
|
<p className="text-sm text-muted-foreground">
|
|
DDoS protection and 99.99% uptime SLA
|
|
</p>
|
|
</CardContent>
|
|
</Card>
|
|
|
|
<Card>
|
|
<CardHeader>
|
|
<HardDrive className="w-8 h-8 text-primary mb-2" />
|
|
<CardTitle>Instant Deployment</CardTitle>
|
|
</CardHeader>
|
|
<CardContent>
|
|
<p className="text-sm text-muted-foreground">
|
|
Your server ready in less than 60 seconds
|
|
</p>
|
|
</CardContent>
|
|
</Card>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
|
|
<Footer />
|
|
</div>
|
|
)
|
|
}
|
|
|
|
// jRIfuQspDJlWdgXxLmqVFSUthwBOkezibPCyoTvHYcEANraGKMnZ
|
|
// {
|
|
// "status": "success",
|
|
// "cloudid": "1645972",
|
|
// "message": "Cloud Server deploy in process and as soon it get ready to use system will send you login detail over the email.",
|
|
// "password": "00000000",
|
|
// "ipv4": "103.189.89.32"
|
|
// }
|