mirror of
https://github.com/vmware/vsphere-automation-sdk-python.git
synced 2024-11-22 09:39:58 -05:00
Initial version of vm-request-o-matic
This is a simple sample application that includes a web form that creates a VM in a VMware Cloud on AWS SDDC.
This commit is contained in:
parent
8febd6904f
commit
157b3897f1
BIN
samples/vmc/vm-request-o-matic/demo.mp4
Normal file
BIN
samples/vmc/vm-request-o-matic/demo.mp4
Normal file
Binary file not shown.
110
samples/vmc/vm-request-o-matic/index.html
Normal file
110
samples/vmc/vm-request-o-matic/index.html
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>VMware Cloud on AWS VM Request-O-Matic</title><!-- Get a pretty style sheet -->
|
||||||
|
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div align="center"><img src="vmc-sticker.png" width="200"></div>
|
||||||
|
<h2 align="center">VM Request-O-Matic</h2>
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-xs-12 col-sm-6 col-sm-push-3">
|
||||||
|
<p>Use this form to create a new VM on VMware Cloud on AWS</p>
|
||||||
|
<form id="vmForm" name="vmForm">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="username">Your Name</label> <input class="form-control" id="username" name="username" placeholder="Bob Bobber" required="" type="tel">
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="emailaddress">Email Address</label> <input class="form-control" id="emailaddress" name="emailaddress" placeholder="Bob@bobber.com" required="" type="tel">
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="vmtype">VM Type</label> <select class="form-control" id="vmtype" name="vmtype" required="">
|
||||||
|
<option selected value="40ff3b8c-f6c7-4aa3-8db8-bb631e16ffae">
|
||||||
|
Windows 10 Desktop (4 CPU, 4GB RAM, 25GB HDD)
|
||||||
|
</option>
|
||||||
|
<option value="37561477-a8c2-4aed-9fce-1bb38557c2b0">
|
||||||
|
Windows Server 2016 (8 CPU, 12GB RAM, 100GB HDD)
|
||||||
|
</option>
|
||||||
|
<option value="40ff3b8c-f6c7-4aa3-8db8-bb631e16ffae">
|
||||||
|
Ubuntu Desktop (4 CPU, 4GB RAM, 25GB HDD)
|
||||||
|
</option>
|
||||||
|
<option value="575fbc82-fb0f-4c1f-95c3-3b0fb0613b82">
|
||||||
|
Ubuntu Server (8 CPU, 12GB RAM, 100GB HDD)
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
</div><button class="btn btn-default" type="submit">Create a VM!</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div class="hidden alert alert-success" id="success" role="alert">
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
Success! Your VM was created successfully, check your email for login instructions.
|
||||||
|
</div>
|
||||||
|
<div class="hidden alert alert-danger" id="error" role="alert">
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
Dang. Something went wrong, check your email for next steps.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div><!-- get the AWS Javascript library -->
|
||||||
|
<script src="https://sdk.amazonaws.com/js/aws-sdk-2.98.0.min.js">
|
||||||
|
</script>
|
||||||
|
<script>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// set up Amazon Cognito (create a federated identity pool)
|
||||||
|
// https://us-west-2.console.aws.amazon.com/cognito/create
|
||||||
|
// Initialize the Amazon Cognito credentials provider
|
||||||
|
AWS.config.region = 'us-west-2'; // Region
|
||||||
|
AWS.config.credentials = new AWS.CognitoIdentityCredentials({
|
||||||
|
IdentityPoolId: 'us-west-2:e93c4c86-240d-4966-86ef-e56cf60ba468',
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
function invokeLambda( e ){
|
||||||
|
|
||||||
|
<!-- pull the variables out of the form -->
|
||||||
|
var username = document.getElementById('username'),
|
||||||
|
emailaddress = document.getElementById('emailaddress');
|
||||||
|
|
||||||
|
|
||||||
|
var selectid = document.getElementById("vmtype");
|
||||||
|
var selectedvm = selectid.options[selectid.selectedIndex].value;
|
||||||
|
|
||||||
|
|
||||||
|
// create JSON object for parameters for invoking Lambda function
|
||||||
|
var lambdaParams = {
|
||||||
|
FunctionName : 'vm-request-o-matic',
|
||||||
|
InvocationType : 'RequestResponse',
|
||||||
|
LogType : 'None',
|
||||||
|
Payload: JSON.stringify({
|
||||||
|
username: username.value,
|
||||||
|
emailaddress: emailaddress.value,
|
||||||
|
vmtype: selectedvm})
|
||||||
|
};
|
||||||
|
|
||||||
|
// create variable to hold data returned by the Lambda function
|
||||||
|
var lambdaResults;
|
||||||
|
|
||||||
|
|
||||||
|
var lambda = new AWS.Lambda({region: 'us-west-2', apiVersion: '2015-03-31'});
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
lambda.invoke(lambdaParams, function(error, data) {
|
||||||
|
if (error) {
|
||||||
|
prompt(error);
|
||||||
|
} else {
|
||||||
|
lambdaResults = JSON.parse(data.Payload);
|
||||||
|
prompt(lambdaResults);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
document.getElementById('vmForm').addEventListener('submit', invokeLambda);
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
22
samples/vmc/vm-request-o-matic/readme.md
Normal file
22
samples/vmc/vm-request-o-matic/readme.md
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
This is a simple 'serverless application' that allows you to create a VM in
|
||||||
|
an SDDC on VMware Cloud on AWS using a few cool tools including: Lambda,
|
||||||
|
Cognito, S3, and VMware Cloud on AWS.
|
||||||
|
|
||||||
|
Matt Dreyer
|
||||||
|
August 16, 2017
|
||||||
|
|
||||||
|
|
||||||
|
To make this work you need to do the following:
|
||||||
|
|
||||||
|
1. Make sure that the vCenter in your SDDC is open to the world, or painfully configure Lambda
|
||||||
|
to run in an VPC and NAT to a specific IP address (which requires even more IAM roles for VPC access).
|
||||||
|
2. Create a working VM, and then Clone it to an OVF template in Content Library
|
||||||
|
3. Use the vCenter API browser to discover the UUID of the your OVF template
|
||||||
|
4. Update the HTML in index.html to match the UUID(s) of the VMs you wish to deploy
|
||||||
|
5. Create a new Lambda function and upload vm-request-form.zip as your code
|
||||||
|
6. Create a new Cognito "Federated Identity" for "anonymous access"
|
||||||
|
7. Update the javascript in index.html to match your new Cognito role
|
||||||
|
8. Create an S3 bucket and configure it for Webhosting
|
||||||
|
9. Upload index.html and vmc-sticker.png into your bucket
|
||||||
|
10. Muck with IAM until Lambda and Cognito get along together
|
||||||
|
(required Cognito role permissions are AWSLambdaExecute and AWSLambdaRole)
|
183
samples/vmc/vm-request-o-matic/vm-request-o-matic - Clean.py
Normal file
183
samples/vmc/vm-request-o-matic/vm-request-o-matic - Clean.py
Normal file
@ -0,0 +1,183 @@
|
|||||||
|
"""
|
||||||
|
|
||||||
|
Simple web form that creates VMs in a VMware Cloud on AWS SDDC
|
||||||
|
|
||||||
|
vCenter API documentation is available at https://code.vmware.com/apis/191/vsphere-automation
|
||||||
|
|
||||||
|
Matt Dreyer
|
||||||
|
August 15, 2017
|
||||||
|
|
||||||
|
You can install python 3.6 from https://www.python.org/downloads/windows/
|
||||||
|
|
||||||
|
You can install the dependent python packages locally (handy for Lambda) with:
|
||||||
|
pip install requests -t . --upgrade
|
||||||
|
pip install simplejson -t . --upgrade
|
||||||
|
pip install certifi -t . --upgrade
|
||||||
|
pip install pyvim -t . --upgrade
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
import requests #need this for Get/Post/Delete
|
||||||
|
import certifi #need this for HTTPS
|
||||||
|
import simplejson as json #need this for JSON
|
||||||
|
import uuid #need this to automatically name newly created VMs
|
||||||
|
|
||||||
|
|
||||||
|
# To use this script you need to create an OAuth Refresh token for your Org
|
||||||
|
# You can generate an OAuth Refresh Token using the tool at vmc.vmware.com
|
||||||
|
# https://console.cloud.vmware.com/csp/gateway/portal/#/user/tokens
|
||||||
|
strAccessKey = "your key goes here"
|
||||||
|
|
||||||
|
|
||||||
|
#where are our service end points
|
||||||
|
strProdURL = "https://vmc.vmware.com"
|
||||||
|
strCSPProdURL = "https://console.cloud.vmware.com"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def getAccessToken(myKey):
|
||||||
|
params = {'refresh_token': myKey}
|
||||||
|
headers = {'Content-Type': 'application/json'}
|
||||||
|
response = requests.post('https://console.cloud.vmware.com/csp/gateway/am/api/auth/api-tokens/authorize', params=params, headers=headers)
|
||||||
|
json_response = response.json()
|
||||||
|
access_token = json_response['access_token']
|
||||||
|
|
||||||
|
# debug only
|
||||||
|
# print(response.status_code)
|
||||||
|
# print(response.json())
|
||||||
|
|
||||||
|
return access_token
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#-------------------- Figure out which Org we are in
|
||||||
|
def getTenantID(sessiontoken):
|
||||||
|
|
||||||
|
myHeader = {'csp-auth-token' : sessiontoken}
|
||||||
|
|
||||||
|
response = requests.get( strProdURL + '/vmc/api/orgs', headers=myHeader)
|
||||||
|
|
||||||
|
# debug only
|
||||||
|
# print(response.status_code)
|
||||||
|
# print(response.json())
|
||||||
|
|
||||||
|
# parse the response to grab our tenant id
|
||||||
|
jsonResponse = response.json()
|
||||||
|
strTenant = str(jsonResponse[0]['id'])
|
||||||
|
|
||||||
|
return(strTenant)
|
||||||
|
|
||||||
|
|
||||||
|
#---------------Login to vCenter and get an API token
|
||||||
|
# this will only work if the MGW firewall rules are configured appropriately
|
||||||
|
def vCenterLogin(sddcID, tenantid, sessiontoken):
|
||||||
|
|
||||||
|
#Get the vCenter details from VMC
|
||||||
|
myHeader = {'csp-auth-token' : sessiontoken}
|
||||||
|
myURL = strProdURL + "/vmc/api/orgs/" + tenantid + "/sddcs/" + sddcID
|
||||||
|
response = requests.get(myURL, headers=myHeader)
|
||||||
|
jsonResponse = response.json()
|
||||||
|
|
||||||
|
vCenterURL = jsonResponse['resource_config']['vc_ip']
|
||||||
|
vCenterUsername = jsonResponse['resource_config']['cloud_username']
|
||||||
|
vCenterPassword = jsonResponse['resource_config']['cloud_password']
|
||||||
|
|
||||||
|
|
||||||
|
#Now get an API token from vcenter
|
||||||
|
myURL = vCenterURL + "rest/com/vmware/cis/session"
|
||||||
|
response = requests.post(myURL, auth=(vCenterUsername,vCenterPassword))
|
||||||
|
token = response.json()['value']
|
||||||
|
vCenterAuthHeader = {'vmware-api-session-id':token}
|
||||||
|
|
||||||
|
return(vCenterURL, vCenterAuthHeader)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#------------ Create a VM from an OVF stored in Content Library
|
||||||
|
|
||||||
|
def createVM(sddcID, tenantid, sessiontoken, vmID, vmName):
|
||||||
|
|
||||||
|
#first we need to get an authentaction token from vCenter
|
||||||
|
vCenterURL, vCenterAuthHeader = vCenterLogin(sddcID, tenantid, sessiontoken)
|
||||||
|
|
||||||
|
#Lets give our cow a name
|
||||||
|
vmname = vmName + "-" + str(uuid.uuid4())
|
||||||
|
|
||||||
|
#now lets create a VM from an OVF template stored in the Content Library
|
||||||
|
#first we need to create a deployment spec
|
||||||
|
deploymentspec = { \
|
||||||
|
"target": { \
|
||||||
|
"resource_pool_id": "resgroup-55", \
|
||||||
|
"host_id": "host-31", \
|
||||||
|
"folder_id": "group-v52" \
|
||||||
|
}, \
|
||||||
|
"deployment_spec": { \
|
||||||
|
"name": vmname, \
|
||||||
|
"accept_all_EULA": "true", \
|
||||||
|
"storage_mappings": [ \
|
||||||
|
{ \
|
||||||
|
"key": "dont-delete-this-key", \
|
||||||
|
"value": { \
|
||||||
|
"type": "DATASTORE", \
|
||||||
|
"datastore_id": "datastore-61", \
|
||||||
|
"provisioning": "thin" \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
], \
|
||||||
|
"storage_provisioning": "thin", \
|
||||||
|
"storage_profile_id": "aa6d5a82-1c88-45da-85d3-3d74b91a5bad", \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
print("\nPlease wait, VM deployment is in process....")
|
||||||
|
|
||||||
|
myURL = vCenterURL + "rest/com/vmware/vcenter/ovf/library-item/id:" + vmID + "?~action=deploy"
|
||||||
|
response = requests.post(myURL, headers=vCenterAuthHeader, json=deploymentspec, timeout=None)
|
||||||
|
#print(response.status_code)
|
||||||
|
#print(response.text)
|
||||||
|
|
||||||
|
if response.status_code == 200:
|
||||||
|
print("Succesfully created a VM named: " + vmname )
|
||||||
|
else:
|
||||||
|
print("Failed to create a VM \n" + response.text)
|
||||||
|
return(vmname)
|
||||||
|
|
||||||
|
|
||||||
|
#--------------------------------------------
|
||||||
|
#---------------- Main ----------------------
|
||||||
|
#--------------------------------------------
|
||||||
|
def lambda_handler(event, context):
|
||||||
|
|
||||||
|
|
||||||
|
sddcID = "your sddc id goes here"
|
||||||
|
tenantID = "your tenant id goes here"
|
||||||
|
|
||||||
|
#Get our access token
|
||||||
|
sessiontoken = getAccessToken(strAccessKey)
|
||||||
|
|
||||||
|
|
||||||
|
#get our tenant ID if it wasn't hard coded at the top of the file
|
||||||
|
if tenantID == "":
|
||||||
|
tenantID = getTenantID(sessiontoken)
|
||||||
|
|
||||||
|
#grab the form input
|
||||||
|
vmType = event['vmtype']
|
||||||
|
emailAddress = event['emailaddress']
|
||||||
|
username = event['username']
|
||||||
|
vmName = emailAddress
|
||||||
|
|
||||||
|
#create a vm based on web form input
|
||||||
|
print("starting vm creation process for " + vmName)
|
||||||
|
|
||||||
|
vmName = createVM(sddcID, tenantID, sessiontoken, vmType, vmName)
|
||||||
|
|
||||||
|
print("created vm named: " + vmName)
|
||||||
|
|
||||||
|
feedback = "Congratulations, your VM named (" + vmName + ") is ready!"
|
||||||
|
|
||||||
|
return(feedback)
|
||||||
|
|
||||||
|
#testing only
|
||||||
|
#lambda_handler({'username': 'Matt Dreyer', 'emailaddress': 'matt.dreyer@gmail.com', 'vmtype': '40ff3b8c-f6c7-4aa3-8db8-bb631e16ffae'}, 0)
|
BIN
samples/vmc/vm-request-o-matic/vmc-sticker.png
Normal file
BIN
samples/vmc/vm-request-o-matic/vmc-sticker.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 159 KiB |
Loading…
Reference in New Issue
Block a user