Skip to content

Commit

Permalink
[CE-142][CE-111] UI for add vSphere host
Browse files Browse the repository at this point in the history
1> Add Basic theme UI for vSphere type host
2> Add User guide for create vSpehre type host

Change-Id: I177bb67d5d7ba425a075b9a1d026b9bae1787a70
Signed-off-by: hainingzhang <[email protected]>
  • Loading branch information
hainingzhang committed Oct 31, 2017
1 parent bc5e4b5 commit 5ae0ec3
Show file tree
Hide file tree
Showing 12 changed files with 505 additions and 28 deletions.
Binary file added docs/imgs/vsphere-active.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/imgs/vsphere-basicSetting.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/imgs/vsphere-pending.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/imgs/vsphere-select.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/imgs/vsphere-vcSetting.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/imgs/vsphere-vmSetting.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
108 changes: 108 additions & 0 deletions docs/vsphere.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
# vSphere type host creation guide

## Prerequisites

- Make sure time is in sync on all esxi hosts in the cluster will be used by Cello otherwise deployment may fail due to certificate expiry check.
- Cello vSphere agent is tested on vSphere deployments with vCenter, single node vSphere without vCenter is not supported.
- Deployment requires DHCP server in the VM network.(If you create VM that use VM network and it can get IP automatically which mean it has a DHCP server)
- vCenter user with following minimal set of privileges is required.
- Datastore &gt; Allocate space
- Datastore &gt; Low level file Operations
- Folder &gt; Create Folder
- Folder &gt; Delete Folder
- Network &gt; Assign network
- Resource &gt; Assign virtual machine to resource pool
- Virtual machine &gt; Configuration &gt; Add new disk
- Virtual Machine &gt; Configuration &gt; Add existing disk
- Virtual Machine &gt; Configuration &gt; Add or remove device
- Virtual Machine &gt; Configuration &gt; Change CPU count
- Virtual Machine &gt; Configuration &gt; Change resource
- Virtual Machine &gt; Configuration &gt; Memory
- Virtual Machine &gt; Configuration &gt; Modify device settings
- Virtual Machine &gt; Configuration &gt; Remove disk
- Virtual Machine &gt; Configuration &gt; Rename
- Virtual Machine &gt; Configuration &gt; Settings
- Virtual machine &gt; Configuration &gt; Advanced
- Virtual Machine &gt; Interaction &gt; Power off
- Virtual Machine &gt; Interaction &gt; Power on
- Virtual Machine &gt; Inventory &gt; Create from existing
- Virtual Machine &gt; Inventory &gt; Create new
- Virtual Machine &gt; Inventory &gt; Remove
- Virtual Machine &gt; Provisioning &gt; Clone virtual machine
- Virtual Machine &gt; Provisioning &gt; Customize
- Virtual Machine &gt; Provisioning &gt; Read customization specifications
- vApp &gt; ImportProfile-driven
- storage -&gt; Profile-driven storage view

## Deployment

**Note** :

The vSphere agent is tested on vCenter 6.0 and vCenter 6.5

### Upload VM image to be used to vSphere:

Upload the template OS OVA to vCenter before create vSphere type host in Cello. The work nodes that run the fabric workloads will be cloned from this VM template.

#### Upload using vSphere Client.

1. Login to vSphere Client.
2. Right-Click on ESX host on which you want to deploy template.
3. Select Deploy OVF template.
4. Copy and paste URL for [OVA for Cello](https://drive.google.com/file/d/0B4Ioua6jjCH9b0ROOE14SUlqUk0/view?usp=sharing)
5. Please deploy the ova on the same cluster which will be planned to be used by cello later
6. **Check the name of the VM created** , this will be used to create vSphere type host in Cello later. (Should default to PhotonOSTemplate.ova)

This OVA is based on Photon OS(v2.0)

**NOTE: DO NOT POWER ON THE IMPORTED VM.**

If you do power it on, future clones of this VM will end up [getting the same IP as the imported VM](https://github.com/vmware/photon/wiki/Frequently-Asked-Questions#q-why-do-all-of-my-cloned-photon-os-instances-have-the-same-ip-address-when-using-dhcp). To work around this run the following command before powering the VM off.

echo -n &gt; /etc/machine-id

## Add vSphere type host

Login to Cello and navigate to the Hosts-&gt;Add Host

In the &quot;Add a host&quot; page select &quot;Host Type&quot; as VSPHERE

![select vsphere](imgs/vsphere-select.png)

Give a name of the vSphere host like &quot;cello-vsphere&quot;, you can specify a capacity number, this number can be configured later. Click &quot;Next&quot;

![basic setting](imgs/vsphere-basicSetting.png)

In the VC address field input your VC IP address, if your VC use some port other than 443, you should add the port eg. 10.112.125.53:8443

In the VC user field input a username with the privileges as described in Prerequisites.

In the VC network field enter the network name.

In the Datacenter field enter the datacenter name.

In the Cluster field enter the cluster name that will be used for Cello, this cluster need to belong to the datacenter entered in the Datacenter field.

In the datastore field, enter a datastore that all the esxi hosts in the cluster can be reachable.

![vc setting](imgs/vsphere-vcSetting.png)

In the VM IP field enter a static IP address that belong to the VM network.

In the VM Gateway filed enter the VM network gateway.

In the VM Netmask field enter the network mask for the VM network.

In the VM DNS filed enter the DNS for the VM network.

In the VM template field enter the template name (If you don&#39;t change the name it will be PhotonOSTemplate.ova by default)

![vm setting](imgs/vsphere-vmSetting.png)

Click Create. You will see the follow page.

. ![vc pending](imgs/vsphere-pending.png)

This means that the vSphere agent is trying to create a new work node. This will take several minutes which is depend on your esxi host&#39;s resource and network speed. After the node created it will automatically download the farbic 1.0 images to the work node. When everything is ready the new host will be in active state.

![vc active](imgs/vsphere-active.png)
107 changes: 90 additions & 17 deletions src/resources/host_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import logging
import os
import sys
import uuid

from flask import jsonify, Blueprint, render_template
from flask import request as r
Expand Down Expand Up @@ -70,31 +71,103 @@ def host_create():
else:
schedulable = "false"

logger.debug("name={}, worker_api={}, capacity={}"
"fillup={}, schedulable={}, log={}/{}".
format(name, worker_api, capacity, autofill, schedulable,
log_type, log_server))
if not name or not worker_api or not capacity or not log_type:
error_msg = "host POST without enough data"
logger.warning(error_msg)
return make_fail_resp(error=error_msg, data=r.form)
else:
host_type = host_type if host_type else detect_daemon_type(worker_api)
if host_type == "vsphere":
vcaddress = r.form['vc_address']
if vcaddress.find(":") == -1:
address = vcaddress
port = "443"
else:
address = vcaddress.split(':')[0]
port = vcaddress.split(':')[1]
logger.debug("address={}, port={}".format(address, port))

vmname = "cello-vsphere-" + str(uuid.uuid1())
vsphere_param = {
'vc': {
'address': address,
'port': port,
'username': r.form['vc_user'],
'password': r.form['vc_password'],
'network': r.form['vc_network'],
'vc_datastore': r.form['datastore'],
'vc_datacenter': r.form['datacenter'],
'vc_cluster': r.form['cluster'],
'template': r.form['vm_template']},
'vm': {
'vmname': vmname,
'ip': r.form['vm_ip'],
'gateway': r.form['vm_gateway'],
'netmask': r.form['vm_netmask'],
'dns': r.form['vm_dns'],
'vcpus': int(r.form['vm_cpus']),
'memory': int(r.form['vm_memory'])}}

logger.debug("name={}, capacity={}"
"fillup={}, schedulable={}, log={}/{}, vsphere_param={}".
format(name, capacity, autofill, schedulable,
log_type, log_server, vsphere_param))

vsphere_must_have_params = {
'Name': name,
'Capacity': capacity,
'LoggingType': log_type,
'VCAddress': address,
'VCUser': r.form['vc_user'],
'VCPassword': r.form['vc_password'],
'VCNetwork': r.form['vc_network'],
'Datastore': r.form['datastore'],
'Datacenter': r.form['datacenter'],
'Cluster': r.form['cluster'],
'VMIp': r.form['vm_ip'],
'VMGateway': r.form['vm_gateway'],
'VMNetmask': r.form['vm_netmask']}
for key in vsphere_must_have_params:
if vsphere_must_have_params[key] == '':
error_msg = "host POST without {} data".format(key)
logger.warning(error_msg)
return make_fail_resp(error=error_msg, data=r.form)
result = host_handler.create(name=name, worker_api=worker_api,
capacity=int(capacity),
autofill=autofill,
schedulable=schedulable,
log_level=log_level,
log_type=log_type,
log_server=log_server,
host_type=host_type)
if result:
logger.debug("host creation successfully")
return make_ok_resp(code=CODE_CREATED)
else:
error_msg = "Failed to create host {}".format(r.form["name"])
host_type=host_type,
params=vsphere_param)
else:
logger.debug("name={}, worker_api={}, capacity={}"
"fillup={}, schedulable={}, log={}/{}".
format(name, worker_api, capacity, autofill, schedulable,
log_type, log_server))
if not name or not worker_api or not capacity or not log_type:
error_msg = "host POST without enough data"
logger.warning(error_msg)
return make_fail_resp(error=error_msg)
return make_fail_resp(error=error_msg, data=r.form)
else:
host_type = host_type if host_type \
else detect_daemon_type(worker_api)
result = host_handler.create(name=name, worker_api=worker_api,
capacity=int(capacity),
autofill=autofill,
schedulable=schedulable,
log_level=log_level,
log_type=log_type,
log_server=log_server,
host_type=host_type)
logger.debug("result.msg={}".format(result.get('msg')))
if (host_type == "vsphere") and ('msg' in result):
vsphere_errmsg = result.get('msg')
error_msg = "Failed to create vsphere host {}".format(vsphere_errmsg)
logger.warning(error_msg)
return make_fail_resp(error=error_msg)
elif result:
logger.debug("host creation successfully")
return make_ok_resp(code=CODE_CREATED)
else:
error_msg = "Failed to create host {}".format(r.form["name"])
logger.warning(error_msg)
return make_fail_resp(error=error_msg)


@bp_host_api.route('/host', methods=['PUT'])
Expand Down
59 changes: 59 additions & 0 deletions src/themes/basic/static/css/vsphere.step.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
.steps {
list-style: none;
display: table;
width: 100%;
padding: 0;
margin: 0;
position: relative;
}
.steps li {
display: table-cell;
text-align: center;
width: 1%;
}
.steps li .step {
border: 2px solid #ced1d6;
font-size: 15px;
border-radius: 100%;
background-color: #FFF;
position: relative;
z-index: 2;
display: inline-block;
width: 30px;
height: 30px;
line-height: 25px;
}
.steps li:before {
display: block;
content: "";
width: 100%;
height: 7px;
font-size: 0;
overflow: hidden;
border-top: 2px solid #CED1D6;
position: relative;
top: 21px;
z-index: 1;
}
.steps li.last-child:before {
max-width: 50%;
width: 50%;
}
.steps li:last-child:before {
max-width: 50%;
width: 50%;
}
.steps li:first-child:before {
max-width: 51%;
left: 50%;
}
.steps li.active:before,
.steps li.active .step{
border-color: #428bca;
}
.steps li .title {
display: block;
margin-top: 2px;
max-width: 100%;
font-size: 12px;
}
3 changes: 3 additions & 0 deletions src/themes/basic/static/js/script.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ $(document).ready(function () {
//var name = $(this).parents('form:first').find('[name="name"]').val();
//var worker_api = $(this).parents('form:first').find('[name="worker_api"]').val();
var form_data = $('#add_new_host_form').serialize();
$("#host_create_button").attr('disabled',true);

$.ajax({
url: "/api/host",
Expand All @@ -70,12 +71,14 @@ $(document).ready(function () {
console.log(response);
$('#newHostModal').hide();
alertMsg('Success!', 'New host is created.', 'success');
$("#host_create_button").attr('disabled',false);
setTimeout("location.reload(true);", 2000);
},
error: function (error) {
console.log(error);
$('#newHostModal').hide();
alertMsg('Failed!', error.responseJSON.error, 'danger');
$("#host_create_button").attr('disabled',false);
setTimeout("location.reload(true);", 2000);
}
});
Expand Down
Loading

0 comments on commit 5ae0ec3

Please sign in to comment.