Skip to content

Commit

Permalink
Adding support for declaring machines dead in the UI. It works and it…
Browse files Browse the repository at this point in the history
… is lovely (reference #562)
  • Loading branch information
Slava Akhmechet committed Apr 4, 2012
1 parent 0515818 commit 861536d
Show file tree
Hide file tree
Showing 3 changed files with 183 additions and 94 deletions.
171 changes: 123 additions & 48 deletions admin/static/coffee/otherviews.coffee
Expand Up @@ -363,16 +363,26 @@ module 'ResolveIssuesView', ->
# ResolveIssuesView.Container
class @Container extends Backbone.View
className: 'resolve-issues'
template: Handlebars.compile $('#resolve_issues-container-template').html()
template_outer: Handlebars.compile $('#resolve_issues-container-outer-template').html()
template_inner: Handlebars.compile $('#resolve_issues-container-inner-template').html()

initialize: =>
log_initial '(initializing) resolve issues view: container'
issues.on 'all', (model, collection) => @render()
issues.on 'all', (model, collection) => @render_issues()

render: ->
@.$el.html @template
issues_exist: if issues.length > 0 then true else false
@.$el.html @template_outer
@render_issues()

return @

# we're adding an inner render function to avoid rerendering
# everything (for example we need to not render the alert,
# otherwise it disappears)
render_issues: ->
@.$('#resolve_issues-container-inner-placeholder').html @template_inner
issues_exist: if issues.length > 0 then true else false

issue_views = []
issues.each (issue) ->
issue_views.push new ResolveIssuesView.Issue
Expand All @@ -383,6 +393,47 @@ module 'ResolveIssuesView', ->

return @

class @DeclareMachineDeadModal extends ClusterView.AbstractModal
template: Handlebars.compile $('#declare_machine_dead-modal-template').html()
alert_tmpl: Handlebars.compile $('#declared_machine_dead-alert-template').html()

initialize: ->
log_initial '(initializing) modal dialog: declare machine dead'
super @template

render: (machine_to_kill) ->
log_render '(rendering) declare machine dead dialog'
validator_options =
submitHandler: =>
$.ajax
url: "/ajax/machines/#{machine_to_kill.id}"
type: 'DELETE'
contentType: 'application/json'

success: (response) =>
clear_modals()

if (response)
throw "Received a non null response to a delete... this is incorrect"

# Grab the new set of issues (so we don't have to wait)
$.ajax
url: '/ajax/issues'
success: set_issues
async: false

# remove the dead machine from the models
machines.remove(machine_to_kill.id)

# rerender issue view (just the issues, not the whole thing)
window.app.resolve_issues_view.render_issues()

# notify the user that we succeeded
$('#user-alert-space').append @alert_tmpl
machine_name: machine_to_kill.get("name")

super validator_options, { 'machine_name': machine_to_kill.get("name") }

# ResolveIssuesView.Issue
class @Issue extends Backbone.View
className: 'issue-container'
Expand All @@ -397,58 +448,82 @@ module 'ResolveIssuesView', ->
initialize: ->
log_initial '(initializing) resolve issues view: issue'

render_machine_down: (_template) ->
machine = machines.get(@model.get('victim'))

masters = []
replicas = []

# Look at all namespaces in the cluster and determine whether this machine had a master or replicas for them
namespaces.each (namespace) ->
for machine_uuid, role_summary of namespace.get('blueprint').peers_roles
if machine_uuid is machine.get('id')
for shard, role of role_summary
if role is 'role_primary'
masters.push
name: namespace.get('name')
uuid: namespace.get('id')
shard: human_readable_shard shard
if role is 'role_secondary'
console.log shard
replicas.push
name: namespace.get('name')
uuid: namespace.get('id')
shard: human_readable_shard shard

json =
name: machine.get('name')
masters: if _.isEmpty(masters) then null else masters
replicas: if _.isEmpty(replicas) then null else replicas
no_responsibilities: if (_.isEmpty(replicas) and _.isEmpty(masters)) then true else false
datetime: iso_date_from_unix_time @model.get('time')

@.$el.html _template(json)

# Declare machine dead handler
@.$('p a.btn').off "click"
@.$('p a.btn').click =>
declare_dead_modal = new ResolveIssuesView.DeclareMachineDeadModal
declare_dead_modal.render machine

render_name_conflict_issue: (_template) ->
json =
name: @model.get('contested_name')
type: @model.get('contested_type')
num_contestants: @model.get('contestants').length
contestants: _.map(@model.get('contestants'), (uuid) ->
uuid: uuid
)
datetime: iso_date_from_unix_time @model.get('time')

@.$el.html _template(json)

render_persistence_issue: (_template) ->
json = datetime: iso_date_from_unix_time @model.get('time')
@.$el.html _template(json)

render_vlock_conflict: (_template) ->
json = datetime: iso_date_from_unix_time @model.get('time')
@.$el.html _template(json)

render_unknown_issue: (_template) ->
json = issue_type: @model.get('type')
@.$el.html _template(json)

render: ->
_template = @templates[@model.get('type')]
switch @model.get('type')
when 'MACHINE_DOWN'
machine = machines.get(@model.get('victim'))

masters = []
replicas = []

# Look at all namespaces in the cluster and determine whether this machine had a master or replicas for them
namespaces.each (namespace) ->
for machine_uuid, role_summary of namespace.get('blueprint').peers_roles
if machine_uuid is machine.get('id')
for shard, role of role_summary
if role is 'role_primary'
masters.push
name: namespace.get('name')
uuid: namespace.get('id')
shard: shard
if role is 'role_secondary'
replicas.push
name: namespace.get('name')
uuid: namespace.get('id')
shard: shard

json =
name: machine.get('name')
masters: masters
replicas: replicas
datetime: iso_date_from_unix_time @model.get('time')

@render_machine_down _template
when 'NAME_CONFLICT_ISSUE'
json =
name: @model.get('contested_name')
type: @model.get('contested_type')
num_contestants: @model.get('contestants').length
contestants: _.map(@model.get('contestants'), (uuid) ->
uuid: uuid
)
datetime: iso_date_from_unix_time @model.get('time')
@render_name_conflict_issue _template
when 'PERSISTENCE_ISSUE'
json =
datetime: iso_date_from_unix_time @model.get('time')
@render_persistence_issue _template
when 'VCLOCK_CONFLICT'
json =
datetime: iso_date_from_unix_time @model.get('time')
@render_vclock_conflict _template
else
_template = @unknown_issue_template
json =
issue_type: @model.get('type')

@.$el.html _template(json)
@render_unknown_issue @unknown_issue_template

@.$('abbr.timeago').timeago()

return @
Expand Down
8 changes: 4 additions & 4 deletions admin/static/less/cluster.less
Expand Up @@ -190,7 +190,7 @@
font-size: 1.4em;
color: @grayLight
}
.btn { float: right; }
.btn { margin-top: 10px; }
.issue {
margin: 20px 0px;
padding: 15px 25px;
Expand All @@ -202,11 +202,9 @@

.header {
margin-top: 3px;
padding-left: 44px;
min-height: 32px;
h3 {
line-height: 1em;
margin-bottom: 0.5em;
}
}

Expand All @@ -220,7 +218,9 @@
font-size: 0.75em;
color: @gray;
text-transform: uppercase;
line-height: 4em;
padding-top: 3px;
margin-bottom: 0;
padding-bottom: 0;
}

.details {
Expand Down
98 changes: 56 additions & 42 deletions admin/templates/cluster.html
Expand Up @@ -655,11 +655,14 @@ <h5 class="cluster">Cluster status</h5>
</script>

<!-- Resolve issues view -->
<script id="resolve_issues-container-template" type="text/x-handlebars-template">
<script id="resolve_issues-container-outer-template" type="text/x-handlebars-template">
<h1>Resolve issues</h1>
<div id="user-alert-space"></div>
<div id="resolve_issues-container-inner-placeholder"></div>
</script>
<script id="resolve_issues-container-inner-template" type="text/x-handlebars-template">
{{#if issues_exist}}
<div class="issues"></div>
<a class="btn large danger">Resolve these issues</a>
{{else}}
<p class="no-issues">No issues reported in the cluster.</p>
{{/if}}
Expand All @@ -673,15 +676,38 @@ <h3 class="title">Machine {{name}} is unreachable.</h3>
{{/if}}
</div>
<hr />
<h4>This machine is responsible for the following namespaces:</h4>
{{#if no_responsibilities}}
<h4>This machine has no master or replica responsibilities.</h4>

{{else}}

<!-- Masters -->
{{#if masters}}
<h4>This machine is responsible for the following masters:</h4>
<ul>
{{#each masters}}
<li>This machine acts as a master for the namespace <a href="#namespaces/{{uuid}}">{{name}}</a> for the shard {{shard}}.</li>
<li>Namespace <a href="#namespaces/{{uuid}}">{{name}}</a> for the shard {{shard}}.</li>
{{/each}}
</ul>
{{else}}
<h4>This machine has no master responsibilities.</h4>
{{/if}}

<!-- Replicas -->
{{#if replicas}}
<h4>This machine is responsible for the following replicas:</h4>
<ul>
{{#each replicas}}
<li>This machine acts as a replica for the namespace <a href="#namespaces/{{uuid}}">{{name}}</a> for the shard {{shard}}.</li>
<li>Namespace <a href="#namespaces/{{uuid}}">{{name}}</a> for the shard {{shard}}.</li>
{{/each}}
</ul>
{{else}}
<h4>This machine has no replica responsibilities.</h4>
{{/if}}

{{/if}}

<p><a class="btn large danger">Declare Dead</a></p>
</div>
</script>
<script id="resolve_issues-name_conflict-template" type="text/x-handlebars-template">
Expand Down Expand Up @@ -761,6 +787,13 @@ <h1>Events</h1>
</div>
</script>

<script id="declared_machine_dead-alert-template" type="text/x-handlebars-template">
<div class="alert" data-alert="alert">
<a class="close" href="#">&times;</a>
<p>You successfully declared machine <span class="name">{{machine_name}}</span> dead.</p>
</div>
</script>

<script id="added_datacenter-alert-template" type="text/x-handlebars-template">
<div class="alert" data-alert="alert">
<a class="close" href="#">&times;</a>
Expand Down Expand Up @@ -898,6 +931,24 @@ <h3>Remove a namespace</h3>
</div>
</script>

<script id="declare_machine_dead-modal-template" type="text/x-handlebars-template">
<div class="modal declare_machine_dead">
<form class="form">
<div class="modal-header">
<a href="#" class="close">&times;</a>
<h3>Declare machine dead</h3>
</div>
<div class="modal-body">
<p>Are you sure you want to declare <strong>{{machine_name}}</strong> dead?</p>
</div>
<div class="modal-footer">
<button class="btn primary declare_machine_dead" type="submit" name="declare-machine-dead" value="Declare dead">Declare dead</button>
<a href="#" class="btn secondary cancel">Cancel</a>
</div>
</form>
</div>
</script>

<script id="edit_machines-modal-template" type="text/x-handlebars-template">
<div class="modal modify-replicas">
<form class="form">
Expand Down Expand Up @@ -1059,43 +1110,6 @@ <h3>Remove a datacenter</h3>
</div>
</script>

<script id="suspend_machine-modal-template" type="text/x-handlebars-template">
<div class="modal suspend-machine">
<form class="form">
<div class="modal-header">
<a href="#" class="close">&times;</a>
<h3>Suspend a machine</h3>
</div>
<div class="modal-body">
<div class="alert block-message error">
<p>
<strong>Be careful.</strong>
Suspending these machines will cause the following
namespaces to become unavailable:
<ul class="namespace-list">
{{#each machines }}
{{#each namespaces}}
<li><a href="#namespaces/{{id}}" target="_blank">{{name}}</a></li>
{{/each}}
{{/each }}
</ul>
</p>
</div>
<p>Are you sure you want to suspend these machines:</p>
<ul class="machine-list">
{{#each machines}}
<li><a href="#machines/{{id}}" target="_blank">{{name}}</a></li>
{{/each}}
</ul>
</div>
<div class="modal-footer">
<button class="btn primary suspend-machine" type="submit" name="suspend-machine" value="Suspend machine">Suspend machines</button>
<a href="#" class="btn secondary cancel">Cancel</a>
</div>
</form>
</div>
</script>

<script id="set_datacenter-modal-template" type="text/x-handlebars-template">
<div class="modal set-datacenter">
<form class="form">
Expand Down

0 comments on commit 861536d

Please sign in to comment.