Class: EY::CloudServer::MysqlStart

Inherits:
Object
  • Object
show all
Defined in:
lib/ey_cloud_server/mysql_start.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ MysqlStart

Returns a new instance of MysqlStart.



11
12
13
14
15
16
17
18
# File 'lib/ey_cloud_server/mysql_start.rb', line 11

def initialize(options = {})
  @password      = options[:password]      || abort("ERROR: You must provide a password.")
  @check         = options[:check]         || abort("ERROR: You must a check interval.")
  @start_timeout = options[:start_timeout] || abort("ERROR: You must provide a start timeout.")
  @stop_timeout  = options[:stop_timeout]  || 1200

  abort("ERROR: You must be root.") unless Process.euid == 0
end

Instance Attribute Details

#checkObject

Returns the value of attribute check.



9
10
11
# File 'lib/ey_cloud_server/mysql_start.rb', line 9

def check
  @check
end

#passwordObject

Returns the value of attribute password.



9
10
11
# File 'lib/ey_cloud_server/mysql_start.rb', line 9

def password
  @password
end

#start_timeoutObject

Returns the value of attribute start_timeout.



9
10
11
# File 'lib/ey_cloud_server/mysql_start.rb', line 9

def start_timeout
  @start_timeout
end

#stop_timeoutObject

Returns the value of attribute stop_timeout.



9
10
11
# File 'lib/ey_cloud_server/mysql_start.rb', line 9

def stop_timeout
  @stop_timeout
end

Class Method Details

.parse(argv, options = {}) ⇒ Object



120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
# File 'lib/ey_cloud_server/mysql_start.rb', line 120

def self.parse(argv, options = {})
  opts = OptionParser.new do |opts|
    opts.version = VERSION

    opts.banner = "Usage: mysql_start [-flag]"
    opts.define_head "mysql_start: start, recover, zap, or otherwise pound mysql into submission."
    opts.separator '*'*80

    opts.on("-p", "--password PASSWORD", "Root password for mysqladmin.") do |password|
      options[:password] = password
    end

    opts.on("-c", "--check NUMBER", "Check mysql interval in seconds.") do |check|
      options[:check] = check.to_i
    end

    opts.on("-t", "--timeout NUMBER", "Maximum wait time in seconds. (DEPRECATED)") do |start_timeout|
      options[:start_timeout] = start_timeout.to_i
    end

    opts.on("-a", "--start NUMBER", "Startup timeout in seconds.") do |start_timeout|
      options[:start_timeout] = start_timeout.to_i
    end

    opts.on("-o", "--stop NUMBER", "Graceful termination timeout in seconds.") do |stop_timeout|
      options[:stop_timeout] = stop_timeout.to_i
    end
  end

  opts.parse!(argv)

  options
end

.run(argv = ARGV, options = {}) ⇒ Object



4
5
6
7
# File 'lib/ey_cloud_server/mysql_start.rb', line 4

def self.run(argv = ARGV, options = {})
  options = parse(argv, options)
  new(options).run
end

Instance Method Details

#log_mysql_event(message) ⇒ Object



107
108
109
# File 'lib/ey_cloud_server/mysql_start.rb', line 107

def log_mysql_event(message)
`echo #{message} >> /root/chef-mysql.log`
end

#mysql_runningObject



116
117
118
# File 'lib/ey_cloud_server/mysql_start.rb', line 116

def mysql_running()
  system("ps -u mysql | grep '[m]ysqld'")
end

#mysql_startedObject



111
112
113
114
# File 'lib/ey_cloud_server/mysql_start.rb', line 111

def mysql_started()
  log_mysql_event("MySQL restarted successfully")
  exit 0
end

#runObject



20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/ey_cloud_server/mysql_start.rb', line 20

def run
  count = 0
  if system('/etc/init.d/mysql restart')
    mysql_started()
  else
    log_mysql_event("MySQL did not start within the startup timeout")
    loop {
      # test to make sure mysql is running
      if mysql_running()
        log_mysql_event("MySQL did start and is working through crash recovery")
        slept = 0
        loop {
          if system("mysqladmin -p#{password} status") # mysql is accessible
            log_mysql_event("MySQL completed crash recovery, performing clean restart")
            system('killall -TERM mysqld')          # safe shutdown of mysql
            termslept = 0
            termlimit = stop_timeout
            loop {
              break if not mysql_running()
              sleep(check)
              termslept = termslept + check
              if termslept > termlimit
                log_mysql_event("MySQL did not shut down cleanly within the time limit, killing")
                system('killall -9 mysqld')
              end
            }
            system('/etc/init.d/mysql zap')         # clear files
            if system('/etc/init.d/mysql restart')  # clean start
              mysql_started()
            end
          else
            log_mysql_event("MySQL has been starting for #{slept/60} minutes and is still attempting to start") if slept % 120 == 0
            sleep(check)
          end
        break if not mysql_running()
        slept = slept + check
        if slept > start_timeout
          log_mysql_event("MySQL was not able to start after #{slept/60} minutes and was forcibly killed")
          system("killall -9 mysqld")
        end
        }
      else
        log_mysql_event("MySQL did not start, zapping")
        begin
          pidfile = '/var/run/mysqld/mysqld.pid'
          if File.exists?(pidfile)
            File.open('/var/run/mysqld/mysqld.pid', 'r') do |f|
              pid = f.read.to_i
              Process.kill("TERM", pid)

              mysqld_is_dead = false
              started_at = Time.now
              # /etc/init.d/mysql has 120 as STOPTIMEOUT, so we should
              # wait at least that long
              until mysqld_is_dead || ((Time.now - started_at) > 120)
                begin
                  Process.kill(0, pid)
                  sleep 1
                rescue Errno::ESRCH      # no such process
                  mysqld_is_dead = true
                end
              end
            end
          end
        rescue Exception => e
          File.open('/root/chef-mysql.log', 'a') do |f|
            f.write("Blew up: \n")
            f.write(e.message)
            f.write("\n")
            f.write(e.backtrace.join("\t\n"))
          end
        end
        system('/etc/init.d/mysql zap')
        if system('/etc/init.d/mysql restart')
          mysql_started()
        end
      end
    count += 1
    if count > 10
      log_mysql_event("Failed to start mysql after 10 attempts, raising error.")
      exit(1)
    end
    sleep 1
    }
  end
end