#!/bin/bash # # A tool to wipe the by-products of a cluster bringup from a bootstrap # node but leave the bootstrap node and related roles, nodes, clients # etc undamaged # # Usage cluster_nuke.sh # if [[ -z "$1" ]] { echo "Usage : $0 'environment'" echo "did nothing..." exit } global ENVIRONMENT := $1 if [[ ! -f "cluster.txt" ]] { echo "I am a bear of very little brain so I couldn't find the cluster.txt file. No clusters were harmed in the making of this error message" exit } if [[ ! -f "environments/${ENVIRONMENT}.json" ]] { echo "You are scaring me now, I don't see the environment file you asked for. Not doing nothing" exit } while read HOSTNAME MACADDR IPADDR ILOIPADDR DOMAIN ROLE { if [[ "$ROLE" = "bootstrap" ]] { global BOOTSTRAP_NODE := $HOSTNAME global BCPC_HYPERVISOR_DOMAIN := $DOMAIN echo "Ignoring $HOSTNAME - bootstrap node to be retained" } elif [[ "$ROLE" = "work" || "$ROLE" = "head" ]] { # # Build a list of entries to remove from the databag. # # Extend the above test if there are other roles that cluster # members can have global CLUSTER_MEMBERS := ""$(CLUSTER_MEMBERS) $(HOSTNAME)"" } else { echo "Ignoring $HOSTNAME - unknown role" } } < cluster.txt if [[ -z "$BOOTSTRAP_NODE" ]] { echo "No bootstrap node found, unsafe to continue. Are you nuts?" exit } # cross check that what I think is the bootstrap node for this domain # based on the cluster definition file cluster appears correctly as a # node in the databag global BOOT_FQDN := ""$(BOOTSTRAP_NODE).$(BCPC_HYPERVISOR_DOMAIN)"" echo "BOOT FQDN = $(BOOT_FQDN)" global MATCH := $[knife node list | grep $BOOT_FQDN] if [[ ! -z "$MATCH" ]] { echo "Plausible level of consistency present : it looks to me like I should delete all nodes and clients except $MATCH..." } else { echo "$BOOT_FQDN not found in data bag, unsafe to continue. Can't fool me that way!" exit } echo "Making safety copy of $(ENVIRONMENT) configs..." global DATABAG_BACKUP := ""~/$ENVIRONMENT.databag.$Pid"" knife data bag show configs $(ENVIRONMENT) >> $(DATABAG_BACKUP) echo "Databag configs for $(ENVIRONMENT) dumped to $(DATABAG_BACKUP)" echo "Deleting data bag configs..." knife data bag delete --yes configs echo "Removing clients and nodes..." for CLIENT in [$CLUSTER_MEMBERS] { knife client delete --yes "$(CLIENT).$(BCPC_HYPERVISOR_DOMAIN)" knife node delete --yes "$(CLIENT).$(BCPC_HYPERVISOR_DOMAIN)" } echo "reload knife data..." knife role from file roles/*.json knife cookbook upload -a -o cookbooks knife environment from file "environments/$(ENVIRONMENT).json" echo "Removing cobbler systems..." for CLIENT in [$(CLUSTER_MEMBERS)] { global SOMETHING := $(CLIENT) sudo cobbler system remove --name=$(CLIENT) } if [[ ! -z "$SOMETHING" ]] { echo "Sync cobbler..." sudo cobbler sync } echo "Removing cobbler profile..." sudo cobbler profile remove --name=bcpc_host sudo cobbler sync # Prevent stale kickstart being installed echo "Hiding stale kickstart in case Chef goes all wibbly..." global KICKSTART_FILE := '"/var/lib/cobbler/kickstarts/bcpc_ubuntu_host.preseed'" sudo mv $(KICKSTART_FILE) "$(KICKSTART_FILE).old.$Pid" echo "Rerunning Chef client ..." sudo chef-client sudo chef-client sudo chef-client echo "Checking results ..." global CHECK := $[knife data bag show configs $(ENVIRONMENT) | grep -i cobbler-root] if [[ -z "$CHECK" ]] { echo "Warning, no cobbler-root found. I'm so sorry." exit } else { echo "Cobbler-root found : $(CHECK)" } echo "Verifying kickstarts..." global CHECK := $[sudo cobbler profile dumpvars --name=bcpc_host | grep kickstart | grep bcpc] if [[ -z "$CHECK" ]] { echo "Warning, no BCPC kickstart data found. Duh!" exit } else { echo "Found BCPC kickstart : $(CHECK)" } echo "Succesfully took off and nuked the site from orbit. It's the only way to be sure." (CommandList children: [ (If arms: [ (if_arm cond: [ (Sentence child: (DBracket expr:(BoolUnary op_id:BoolUnary_z child:{(DQ ($ VSub_Number "$1"))})) terminator: ) ] action: [ (C {(echo)} {(DQ ("Usage : ") ($ VSub_Number "$0") (" 'environment'"))}) (C {(echo)} {(DQ ("did nothing..."))}) (C {(exit)}) ] spids: [-1 37] ) ] spids: [-1 58] ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:ENVIRONMENT) op: Equal rhs: {(DQ ($ VSub_Number "$1"))} spids: [60] ) ] spids: [60] ) (If arms: [ (if_arm cond: [ (Sentence child: (DBracket expr: (LogicalNot child:(BoolUnary op_id:BoolUnary_f child:{(DQ (cluster.txt))})) ) terminator: ) ] action: [ (C {(echo)} { (DQ ( "I am a bear of very little brain so I couldn't find the cluster.txt file. No clusters were harmed in the making of this error message" ) ) } ) (C {(exit)}) ] spids: [-1 80] ) ] spids: [-1 92] ) (If arms: [ (if_arm cond: [ (Sentence child: (DBracket expr: (LogicalNot child: (BoolUnary op_id: BoolUnary_f child: {(DQ (environments/) (${ VSub_Name ENVIRONMENT) (.json))} ) ) ) terminator: ) ] action: [ (C {(echo)} { (DQ ( "You are scaring me now, I don't see the environment file you asked for. Not doing nothing" ) ) } ) (C {(exit)}) ] spids: [-1 113] ) ] spids: [-1 125] ) (While cond: [ (Sentence child: (C {(read)} {(HOSTNAME)} {(MACADDR)} {(IPADDR)} {(ILOIPADDR)} {(DOMAIN)} {(ROLE)}) terminator: ) ] body: (DoGroup children: [ (If arms: [ (if_arm cond: [ (Sentence child: (DBracket expr: (BoolBinary op_id: BoolBinary_GlobEqual left: {(DQ ($ VSub_Name "$ROLE"))} right: {(DQ (bootstrap))} ) ) terminator: ) ] action: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:BOOTSTRAP_NODE) op: Equal rhs: {(DQ ($ VSub_Name "$HOSTNAME"))} spids: [167] ) ] spids: [167] ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:BCPC_HYPERVISOR_DOMAIN) op: Equal rhs: {(DQ ($ VSub_Name "$DOMAIN"))} spids: [173] ) ] spids: [173] ) (C {(echo)} { (DQ ("Ignoring ") ($ VSub_Name "$HOSTNAME") (" - bootstrap node to be retained") ) } ) ] spids: [-1 164] ) (if_arm cond: [ (Sentence child: (DBracket expr: (LogicalOr left: (BoolBinary op_id: BoolBinary_GlobEqual left: {(DQ ($ VSub_Name "$ROLE"))} right: {(DQ (work))} ) right: (BoolBinary op_id: BoolBinary_GlobEqual left: {(DQ ($ VSub_Name "$ROLE"))} right: {(DQ (head))} ) ) ) terminator: ) ] action: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:CLUSTER_MEMBERS) op: Equal rhs: {(DQ (${ VSub_Name CLUSTER_MEMBERS) (" ") (${ VSub_Name HOSTNAME))} spids: [240] ) ] spids: [240] ) ] spids: [188 217] ) ] else_action: [ (C {(echo)} {(DQ ("Ignoring ") ($ VSub_Name "$HOSTNAME") (" - unknown role"))}) ] spids: [252 264] ) ] spids: [144 266] ) redirects: [(Redir op_id:Redir_Less fd:-1 arg_word:{(cluster.txt)} spids:[268])] ) (If arms: [ (if_arm cond: [ (Sentence child: (DBracket expr: (BoolUnary op_id:BoolUnary_z child:{(DQ ($ VSub_Name "$BOOTSTRAP_NODE"))}) ) terminator: ) ] action: [ (C {(echo)} {(DQ ("No bootstrap node found, unsafe to continue. Are you nuts?"))}) (C {(exit)}) ] spids: [-1 285] ) ] spids: [-1 297] ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:BOOT_FQDN) op: Equal rhs: {(DQ (${ VSub_Name BOOTSTRAP_NODE) (.) (${ VSub_Name BCPC_HYPERVISOR_DOMAIN))} spids: [309] ) ] spids: [309] ) (C {(echo)} {(DQ ("BOOT FQDN = ") (${ VSub_Name BOOT_FQDN))}) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:MATCH) op: Equal rhs: { (CommandSubPart command_list: (CommandList children: [ (Pipeline children: [ (C {(knife)} {(node)} {(list)}) (C {(grep)} {($ VSub_Name "$BOOT_FQDN")}) ] negated: False ) ] ) left_token: spids: [330 342] ) } spids: [329] ) ] spids: [329] ) (If arms: [ (if_arm cond: [ (Sentence child: (DBracket expr: (LogicalNot child: (BoolUnary op_id:BoolUnary_z child:{(DQ ($ VSub_Name "$MATCH"))}) ) ) terminator: ) ] action: [ (C {(echo)} { (DQ ( "Plausible level of consistency present : it looks to me like I should delete all nodes and clients except " ) ($ VSub_Name "$MATCH") (...) ) } ) ] spids: [-1 359] ) ] else_action: [ (C {(echo)} { (DQ ($ VSub_Name "$BOOT_FQDN") (" not found in data bag, unsafe to continue. Can't fool me that way!") ) } ) (C {(exit)}) ] spids: [370 383] ) (C {(echo)} {(DQ ("Making safety copy of ") (${ VSub_Name ENVIRONMENT) (" configs..."))}) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:DATABAG_BACKUP) op: Equal rhs: {(DQ ("~/") ($ VSub_Name "$ENVIRONMENT") (.databag.) ($ VSub_Dollar "$$"))} spids: [395] ) ] spids: [395] ) (SimpleCommand words: [{(knife)} {(data)} {(bag)} {(show)} {(configs)} {(DQ (${ VSub_Name ENVIRONMENT))}] redirects: [ (Redir op_id: Redir_DGreat fd: -1 arg_word: {(DQ (${ VSub_Name DATABAG_BACKUP))} spids: [419] ) ] ) (C {(echo)} { (DQ ("Databag configs for ") (${ VSub_Name ENVIRONMENT) (" dumped to ") (${ VSub_Name DATABAG_BACKUP) ) } ) (C {(echo)} {(DQ ("Deleting data bag configs..."))}) (C {(knife)} {(data)} {(bag)} {(delete)} {(--yes)} {(configs)}) (C {(echo)} {(DQ ("Removing clients and nodes..."))}) (ForEach iter_name: CLIENT iter_words: [{($ VSub_Name "$CLUSTER_MEMBERS")}] do_arg_iter: False body: (DoGroup children: [ (C {(knife)} {(client)} {(delete)} {(--yes)} {(DQ (${ VSub_Name CLIENT) (.) (${ VSub_Name BCPC_HYPERVISOR_DOMAIN))} ) (C {(knife)} {(node)} {(delete)} {(--yes)} {(DQ (${ VSub_Name CLIENT) (.) (${ VSub_Name BCPC_HYPERVISOR_DOMAIN))} ) ] spids: [475 515] ) spids: [471 473] ) (C {(echo)} {(DQ ("reload knife data..."))}) (C {(knife)} {(role)} {(from)} {(file)} {(roles/) (Lit_Other "*") (.json)}) (C {(knife)} {(cookbook)} {(upload)} {(-a)} {(-o)} {(cookbooks)}) (C {(knife)} {(environment)} {(from)} {(file)} {(DQ (environments/) (${ VSub_Name ENVIRONMENT) (.json))} ) (C {(echo)} {(DQ ("Removing cobbler systems..."))}) (ForEach iter_name: CLIENT iter_words: [{(DQ (${ VSub_Name CLUSTER_MEMBERS))}] do_arg_iter: False body: (DoGroup children: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:SOMETHING) op: Equal rhs: {(DQ (${ VSub_Name CLIENT))} spids: [587] ) ] spids: [587] ) (C {(sudo)} {(cobbler)} {(system)} {(remove)} {(--name) (Lit_Other "=") (${ VSub_Name CLIENT)}) ] spids: [584 609] ) spids: [576 582] ) (If arms: [ (if_arm cond: [ (Sentence child: (DBracket expr: (LogicalNot child: (BoolUnary op_id:BoolUnary_z child:{(DQ ($ VSub_Name "$SOMETHING"))}) ) ) terminator: ) ] action: [(C {(echo)} {(DQ ("Sync cobbler..."))}) (C {(sudo)} {(cobbler)} {(sync)})] spids: [-1 627] ) ] spids: [-1 643] ) (C {(echo)} {(DQ ("Removing cobbler profile..."))}) (C {(sudo)} {(cobbler)} {(profile)} {(remove)} {(--name) (Lit_Other "=") (bcpc_host)}) (C {(sudo)} {(cobbler)} {(sync)}) (C {(echo)} {(DQ ("Hiding stale kickstart in case Chef goes all wibbly..."))}) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:KICKSTART_FILE) op: Equal rhs: {(DQ (/var/lib/cobbler/kickstarts/bcpc_ubuntu_host.preseed))} spids: [680] ) ] spids: [680] ) (C {(sudo)} {(mv)} {(DQ (${ VSub_Name KICKSTART_FILE))} {(DQ (${ VSub_Name KICKSTART_FILE) (.old.) ($ VSub_Dollar "$$"))} ) (C {(echo)} {(DQ ("Rerunning Chef client ..."))}) (C {(sudo)} {(chef-client)}) (C {(sudo)} {(chef-client)}) (C {(sudo)} {(chef-client)}) (C {(echo)} {(DQ ("Checking results ..."))}) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:CHECK) op: Equal rhs: { (CommandSubPart command_list: (CommandList children: [ (Pipeline children: [ (C {(knife)} {(data)} {(bag)} {(show)} {(configs)} {(${ VSub_Name ENVIRONMENT)}) (C {(grep)} {(-i)} {(cobbler-root)}) ] negated: False ) ] ) left_token: spids: [730 752] ) } spids: [729] ) ] spids: [729] ) (If arms: [ (if_arm cond: [ (Sentence child: (DBracket expr:(BoolUnary op_id:BoolUnary_z child:{(DQ ($ VSub_Name "$CHECK"))})) terminator: ) ] action: [(C {(echo)} {(DQ ("Warning, no cobbler-root found. I'm so sorry."))}) (C {(exit)})] spids: [-1 767] ) ] else_action: [(C {(echo)} {(DQ ("Cobbler-root found : ") (${ VSub_Name CHECK))})] spids: [779 791] ) (C {(echo)} {(DQ ("Verifying kickstarts..."))}) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:CHECK) op: Equal rhs: { (CommandSubPart command_list: (CommandList children: [ (Pipeline children: [ (C {(sudo)} {(cobbler)} {(profile)} {(dumpvars)} {(--name) (Lit_Other "=") (bcpc_host)} ) (C {(grep)} {(kickstart)}) (C {(grep)} {(bcpc)}) ] negated: False ) ] ) left_token: spids: [801 825] ) } spids: [800] ) ] spids: [800] ) (If arms: [ (if_arm cond: [ (Sentence child: (DBracket expr:(BoolUnary op_id:BoolUnary_z child:{(DQ ($ VSub_Name "$CHECK"))})) terminator: ) ] action: [(C {(echo)} {(DQ ("Warning, no BCPC kickstart data found. Duh!"))}) (C {(exit)})] spids: [-1 840] ) ] else_action: [(C {(echo)} {(DQ ("Found BCPC kickstart : ") (${ VSub_Name CHECK))})] spids: [852 864] ) (C {(echo)} {(DQ ("Succesfully took off and nuked the site from orbit. It's the only way to be sure."))} ) ] )