Merge branch 'master' of github.com:Mirantis/product
This commit is contained in:
commit
2e9f9e0e10
2
cooks
2
cooks
@ -1 +1 @@
|
||||
Subproject commit 10d11738e69c31bd31c75b689275570bd2824b7f
|
||||
Subproject commit 6e5cea9f5525b3a08591071472a709f0f069ab49
|
@ -241,6 +241,10 @@ behavior: url(/static/css/pie.htc);
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.cluster-control .btn {
|
||||
margin-left: 15px;
|
||||
}
|
||||
|
||||
.dialog-node {
|
||||
cursor: pointer !important;
|
||||
}
|
||||
|
@ -10,18 +10,6 @@
|
||||
<link href="/static/css/overlap.css" rel="stylesheet">
|
||||
<link href="/static/css/buttons.css" rel="stylesheet">
|
||||
<link href="/static/css/font-awesome.css" rel="stylesheet">
|
||||
<style>
|
||||
@font-face {
|
||||
font-family: 'FontAwesome';
|
||||
src: url('/static/font/fontawesome-webfont.eot');
|
||||
src: url('/static/font/fontawesome-webfont.eot?#iefix') format('embedded-opentype'),
|
||||
url('/static/font/fontawesome-webfont.woff') format('woff'),
|
||||
url('/static/font/fontawesome-webfont.ttf') format('truetype'),
|
||||
url('/static/font/fontawesome-webfont.svg#FontAwesome') format('svg');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
</style>
|
||||
<!-- Le HTML5 shim, for IE6-8 support of HTML5 elements -->
|
||||
<!--[if lt IE 9]>
|
||||
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
|
||||
|
@ -16,11 +16,15 @@ function(models, dialogViews, taskViews, clusterPageTemplate, clusterNodeTemplat
|
||||
updateInterval: 5000,
|
||||
template: _.template(clusterPageTemplate),
|
||||
events: {
|
||||
'click .js-add-nodes': 'addRemoveNodes'
|
||||
'click .add-nodes-btn': 'addRemoveNodes',
|
||||
'click .assign-roles-btn': 'assignRoles'
|
||||
},
|
||||
addRemoveNodes: function(e) {
|
||||
(new dialogViews.addRemoveNodesDialog({model: this.model})).render();
|
||||
},
|
||||
assignRoles: function(e) {
|
||||
(new dialogViews.assignRolesDialog({model: this.model})).render();
|
||||
},
|
||||
initialize: function() {
|
||||
this.model.bind('change', this.render, this);
|
||||
this.scheduleUpdate();
|
||||
|
@ -3,20 +3,20 @@ define(
|
||||
'models',
|
||||
'text!templates/dialogs/add_remove_nodes.html',
|
||||
'text!templates/dialogs/create_cluster.html',
|
||||
'text!templates/dialogs/node_list.html'
|
||||
'text!templates/dialogs/node_list.html',
|
||||
'text!templates/dialogs/assign_roles.html'
|
||||
],
|
||||
function(models, addRemoveNodesDialogTemplate, createClusterDialogTemplate, nodeDialogNodeListTemplate) {
|
||||
function(models, addRemoveNodesDialogTemplate, createClusterDialogTemplate, nodeDialogNodeListTemplate, assignRolesDialogTemplate) {
|
||||
var views = {}
|
||||
|
||||
views.addRemoveNodesDialog = Backbone.View.extend({
|
||||
className: 'modal fade',
|
||||
template: _.template(addRemoveNodesDialogTemplate),
|
||||
events: {
|
||||
'click .js-save-changes': 'saveChanges',
|
||||
'click .save-changes-btn': 'saveChanges',
|
||||
'click .dialog-node': 'toggleNode'
|
||||
},
|
||||
saveChanges: function(e) {
|
||||
e.preventDefault();
|
||||
var nodes = this.$('.node-checked').map(function(){return $(this).attr('data-node-id')}).get();
|
||||
this.model.update({nodes: nodes});
|
||||
this.$el.modal('hide');
|
||||
@ -45,11 +45,10 @@ function(models, addRemoveNodesDialogTemplate, createClusterDialogTemplate, node
|
||||
className: 'modal fade',
|
||||
template: _.template(createClusterDialogTemplate),
|
||||
events: {
|
||||
'click .js-create-cluster': 'createCluster',
|
||||
'click .create-cluster-btn': 'createCluster',
|
||||
'click .dialog-node': 'toggleNode'
|
||||
},
|
||||
createCluster: function(e) {
|
||||
e.preventDefault();
|
||||
this.$('.help-inline').text('');
|
||||
this.$('.control-group').removeClass('error');
|
||||
var nodes = this.$('.node-checked').map(function(){return $(this).attr('data-node-id')}).get();
|
||||
@ -111,5 +110,23 @@ function(models, addRemoveNodesDialogTemplate, createClusterDialogTemplate, node
|
||||
}
|
||||
});
|
||||
|
||||
views.assignRolesDialog = Backbone.View.extend({
|
||||
className: 'modal fade',
|
||||
template: _.template(assignRolesDialogTemplate),
|
||||
events: {
|
||||
'click .assign-roles-btn': 'assignRoles'
|
||||
},
|
||||
assignRoles: function() {
|
||||
// TODO
|
||||
this.$el.modal('hide');
|
||||
},
|
||||
render: function() {
|
||||
this.$el.html(this.template());
|
||||
this.$el.on('hidden', function() {$(this).remove()});
|
||||
this.$el.modal();
|
||||
return this;
|
||||
}
|
||||
});
|
||||
|
||||
return views;
|
||||
});
|
||||
|
@ -46,7 +46,7 @@
|
||||
</div>
|
||||
<% } else if (node.get('status') == 'error') { %>
|
||||
<div class="statusbar-text msg-error">
|
||||
<i class="icon-warning-sign"></i><strong>Error</strong>
|
||||
<i class="icon-exclamation-sign"></i><strong>Error</strong>
|
||||
</div>
|
||||
<% } else if (node.get('status') == 'deploying') { %>
|
||||
<div class="statusbar-text msg-warning">
|
||||
|
@ -1,7 +1,12 @@
|
||||
<div class="row">
|
||||
<div class="span8"><h1><%= cluster.get('name') %></h1></div>
|
||||
<div class="span2"><button class="btn pull-right"><i class="icon-wrench icon-white"></i>Settings</button></div>
|
||||
<div class="span2"><button class="btn btn-success pull-right js-add-nodes"><i class="icon-plus-sign icon-white"></i>Add Nodes</button></div>
|
||||
<div class="span6">
|
||||
<h1><%= cluster.get('name') %></h1>
|
||||
</div>
|
||||
<div class="span6 cluster-control">
|
||||
<button class="btn btn-success pull-right add-nodes-btn"><i class="icon-plus-sign icon-white"></i>Add Nodes</button>
|
||||
<button class="btn pull-right assign-roles-btn"><i class="icon-tags icon-white"></i>Assign Roles</button>
|
||||
<button class="btn pull-right"><i class="icon-wrench icon-white"></i>Settings</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="deployment-control"></div>
|
||||
<div class="task-status"></div>
|
||||
|
@ -19,6 +19,6 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<a href="#" class="btn" data-dismiss="modal">Close</a>
|
||||
<a href="#" class="btn btn-success js-save-changes">Save changes</a>
|
||||
<button class="btn" data-dismiss="modal">Close</button>
|
||||
<button class="btn btn-success save-changes-btn">Save changes</button>
|
||||
</div>
|
||||
|
39
nailgun/nailgun/static/templates/dialogs/assign_roles.html
Normal file
39
nailgun/nailgun/static/templates/dialogs/assign_roles.html
Normal file
@ -0,0 +1,39 @@
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal">×</button>
|
||||
<h2>Assign Roles</h2>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<h3>Please choose deployment type</h3>
|
||||
<form>
|
||||
<table class="table">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="width: 16px;">
|
||||
<label class="radio">
|
||||
<input type="radio" name="type">
|
||||
</label>
|
||||
</td>
|
||||
<td>
|
||||
<p>Simple Deployment</p>
|
||||
<p><small>Simple OpenStack deployment</small></p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="width: 16px;">
|
||||
<label class="radio">
|
||||
<input type="radio" name="type">
|
||||
</label>
|
||||
</td>
|
||||
<td>
|
||||
<p>HA Deployment</p>
|
||||
<p><small>Highly-available OpenStack deployment</small></p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn" data-dismiss="modal">Cancel</button>
|
||||
<button class="btn btn-success assign-roles-btn">Assign Roles</button>
|
||||
</div>
|
@ -35,6 +35,6 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<a href="#" class="btn" data-dismiss="modal">Cancel</a>
|
||||
<a href="#" class="btn btn-success js-create-cluster">Create Cluster</a>
|
||||
<button class="btn" data-dismiss="modal">Cancel</button>
|
||||
<button class="btn btn-success create-cluster-btn">Create Cluster</button>
|
||||
</div>
|
||||
|
@ -1,5 +1,6 @@
|
||||
import time, os
|
||||
import devops
|
||||
import unittest
|
||||
from devops.model import Environment, Network, Node, Disk, Cdrom, Interface
|
||||
from devops.controller import Controller
|
||||
from devops.driver.libvirt import Libvirt
|
||||
@ -130,3 +131,40 @@ def tearDown():
|
||||
if not ci.environment_cache_file:
|
||||
ci.destroy_environment()
|
||||
|
||||
class CookbokTestCase(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.ip = ci.environment.node['cookbooks'].ip_address
|
||||
self.cookbooks_dir = os.path.abspath(
|
||||
os.path.join(
|
||||
os.path.dirname(__file__),
|
||||
"..", "..", "cooks", "cookbooks"
|
||||
)
|
||||
)
|
||||
|
||||
self.remote = SSHClient()
|
||||
self.remote.connect_ssh(str(self.ip), "root", "r00tme")
|
||||
self.remote.mkdir("/opt/os-cookbooks/")
|
||||
|
||||
with self.remote.open('/tmp/solo.rb', 'w') as solo_rb:
|
||||
solo_rb.write("""
|
||||
file_cache_path "/tmp/chef"
|
||||
cookbook_path "/opt/os-cookbooks"
|
||||
""")
|
||||
|
||||
def upload_cookbooks(self, cookbooks):
|
||||
if not isinstance(cookbooks, list):
|
||||
cookbooks = [cookbooks]
|
||||
|
||||
for cookbook in cookbooks:
|
||||
self.remote.scp_d(os.path.join(self.cookbooks_dir, cookbook), "/opt/os-cookbooks/")
|
||||
|
||||
def chef_solo(self, attributes={}):
|
||||
with self.remote.open('/tmp/solo.json', 'w') as f:
|
||||
f.write(json.dumps(attributes))
|
||||
|
||||
result = self.remote.exec_cmd("chef-solo -l debug -c /tmp/solo.rb -j /tmp/solo.json")
|
||||
if result['exit_status'] != 0:
|
||||
raise ChefRunError(result['exit_status'], result['stdout'], result['stderr'])
|
||||
|
||||
return result
|
||||
|
||||
|
@ -99,6 +99,9 @@ class SSHClient(object):
|
||||
logging.info("Removing directory: %s" % path)
|
||||
return self.exec_cmd("rm -rf %s" % path)
|
||||
|
||||
def open(self, path, mode='r'):
|
||||
return self.sftp_client.open(path, mode)
|
||||
|
||||
def scp(self, frm, to):
|
||||
logging.info("Copying file: %s -> %s" % (frm, to))
|
||||
self.sftp_client.put(frm, to)
|
||||
|
Loading…
Reference in New Issue
Block a user