The Startup
Published in

The Startup

Monitor Servers and Reboot SolusVM via AWS Lambda Function

Get Lambda to do the dirty work for you.

A lot of server errors can be fixed with a quick reboot. The problem is, you aren’t always right there the second an issue occurs to reboot your server and so your websites go down and looses traffic. Even with monitoring services, your sites stay down because you are sleeping and don’t get the notification until the morning. But there’s good news if your servers have a SolusVM admin backend! We can create a Lambda script in Python to check your websites health and reboot any that are experiencing downtime!

Last year, I wrote a tutorial on how to do this via Cronjob and a Bash Script, but I’ve realized AWS Lambda is really the perfect solution for this (after all, what if the server running the Bash script goes down? Serverless to the rescue!). And because this script runs so infrequently, it won’t cost a dime!

Step One:

Create an AWS account here. I’m not going to walk you through this. If you have trouble, get some help here.

Step Two:

Since we want email notification, we’re going to setup SES.

  1. Click on Services.
  2. Search for “ses”.
  3. And click on “Simple Email Service”.

On the SES dashboard, you’ll want to note which region you are creating in:

Then you’ll want to add a new verified email address:

And then add the email address you want to receive alerts at. Then you’ll get a verification email sent to that email account, and you’ll want to click the link contained in that email to verify the email address is in fact yours.

Once you do this, you’ll see the verification status for your email address turn to green with the “verified” status.

Step Three:

Create a new Lambda Function.

  1. Click on “Services”
  2. Search for “lambda” in the search prompt
  3. Click on “Lambda”

Then you’ll want to click on “Create Function”:

Next we’ll fill in the details about our new function:

  1. Select “Author from scratch”.
  2. Give your function a name (like “UpTime”).
  3. And select “Python 3.7” from the dropdown list as the runtime language.

Then we’ll want to give our Lambda function the permissions it needs in order to run and send us an email when a server is rebooted.

Click on “Choose or create an execution role”

Then ensure that “Create a new role with basic Lambda permissions” is selected.

And click “Create function”.

Great job! You now have an awesome Lambda function waiting for your commands.

Then copy and paste this code into your newly created function:

import urllib3
import boto3
import botocore
# Make sure the SES region matches the region
# you chose for your SES configuration
sesRegion = 'us-west-2'
client = boto3.client('ses', region)
charset = 'UTF-8'
# The email address to send reboot notifications to
# (the one you varified in SES)
sender = 'YOUREMAILADDRESSHERE'
# Location of your host's SolusVM API command.php so you can reboot
# your server via API - you can request this from your host
# APICOMMANDURL= 'https://vpscpsomething.com/api/client/command.php'
# Create dictionary with server info - replace the SERVERNAME
# part with a descriptive name for each server and use the
# same name for the matching KEY and HASH dictionaries.
# If you have more servers just add a new line with that
# server information.
# Also, replace the example url with the url you want to test
# on that server. If you use PHP on your server, select a url
# that will test and make sure PHP is running correctly (and
# if you are using MySQL - a PHP file that will test the
# MySQL connection).
SERVERS = {
'SERVERNAME1': 'https://www.servername1.com/sometesturl/',
'SERVERNAME2': 'https://www.servername2.com/sometesturl/'
}
# Create a dictionary with the API key for each server
KEY = {
'SERVERNAME1': 'SolusVM-API-KEY-SERVER-1',
'SERVERNAME2': 'SolusVM-API-KEY-SERVER-2'
}
# Create a dictionary with the API hash for each server
HASH = {
'SERVERNAME1': 'SolusVM-API-HASH-SERVER-1',
'SERVERNAME2': 'SolusVM-API-HASH-SERVER-2'
}
def lambda_handler(event, context):
# Now we cycle through each server - test if the server
# returns a 200 OK header and if not, reboot the server
# via the SolusVM API and also send a notification email.
for x in SERVERS:
user_agent = {'user-agent': 'Mozilla/5.0 (Windows NT 6.3; rv:36.0) ..'}
try:
http = urllib3.PoolManager(10, headers=user_agent, timeout=4.0, retries=False)
response = http.urlopen('GET', SERVERS[x])
#If the server is up
if response.status == 200:
print(x + " is " + str(response.status))
continue
# If the server returns any response other than 200,
# reboot the server
if response.status != 200:
print(x + " is " + str(response.status))
http = urllib3.PoolManager(10, headers=user_agent)
apiURL = APICOMMANDURL + '?key=' + KEY[x] + '&hash=' + HASH[x] + '&action=reboot'
response = http.urlopen('GET', apiURL)
print('Rebooted ' + x)
subject = 'Rebooted ' + x
content = x + ' was rebooted because it returned a response of ' + str(response.status) + '.'
sendMailToUser(content, subject)
# If the server is down and does not respond,
# then reboot the server
except urllib3.exceptions.ReadTimeoutError:
print(x + ' has an issue')
http = urllib3.PoolManager(10, headers=user_agent)
apiURL = APICOMMANDURL + '?key=' + KEY[x] + '&hash=' + HASH[x] + '&action=reboot'
response = http.urlopen('GET', apiURL)
print('Rebooted ' + x)
subject = 'Rebooted ' + x
content = x + ' was rebooted because of a read timeout error.'
sendMailToUser(content, subject)
return
def sendMailToUser(content, subject):
# Send Email using SES
return client.send_email(
Source=sender,
ReplyToAddresses=[ sender ],
Destination={
'ToAddresses': [
sender,
],
},
Message={
'Subject': {
'Charset': charset,
'Data': subject
},
'Body': {
'Html': {
'Charset': charset,
'Data': content
},
'Text': {
'Charset': charset,
'Data': content
}
}
}
)

Then click “Save”.

Now you’ll need to go through the code and read the comments and customize it accordingly so that the code has the specifics to monitor your servers and reboot them when there is a problem. Make sure and save the function once you are done entering your details.

Once you are done entering your information, scroll down end edit the timeout properties for the function:

Around 15 seconds should be plenty.

4. Modify the Functions IAM Role

Since we want our function to be able to send us an email, we need to modify its IAM role.

  1. Click on “Services”
  2. Search for “IAM”

….you get the picture

Then you’ll need to click on “Roles” and click on the role name that has your function name as its prefix.

Then click on “Add inline policy”

Then in the “Service” section, you’ll need to search for “SES”. In the “Actions” section click on “All SES actions”. And in the “Resources” section, choose “All resources”. This permission might be more broad than you desire, so you can feel free to modify it to your security needs.

Then click “Review policy” at the bottom right of the page.

Then you’ll need to give the policy a name and click “Create policy”.

5. Testing

Now we’re ready to test our Lambda function. Go ahead a shut down one of your servers via the SolusVM dashboard.

Then click “Test”.

Here you’ll need to give your test a name and delete the the JSON contents, leaving just the two “{}”. Then click “Create”

Then make sure your test is selected in the dropdown and click “Test”

If all goes well, you should see that your script ran successfully and you can view the log in CloudWatch:

Your CloudWatch log should have something like the following:

And you should have also recieved an email letting you know the server was rebooted. Yay! Success!

6. Scheduling

Now we just want to run this function on a schedule, so we don’t have to do anything manually.

Head back to your Lambda function and click “Add trigger”.

Then select “CloudWatch Events/EventBridge” from the drop-down list.

Then click on the drop-down list and select “Create a new rule”.

Next, add a name and description for your new trigger:

Select “Schedule expression.

Then create a Cron expression at CronMaker and copy all but the left-most character (since CloudWatch Events cannot be triggered on seconds) and place it into the parenthesis of cron() in the “Schedule expression” field. The example 0/15 * 1/1 * ? * will run the function every 15 minutes. Make sure “Enable trigger” is checked.

And finally, click “Add”.

7. Sit back and relax!

That’s it! Now you can sit back and relax, knowing when your servers go down for some unexplainable reason, they’ll be back up in no time!

If you have any comments or something you think will make this even better, let me know in the comments!

P.S.
If you want your Lambda function to run a little faster, comment out all the print statements in the code. If you ever need them to debug something, just uncomment them out again.

--

--

--

Get smarter at building your thing. Follow to join The Startup’s +8 million monthly readers & +756K followers.

Recommended from Medium

Getting Started with React and WebAssembly using Hooks

Serverless Supercharged: One Time Password-based authentication with Firebase cloud backend

Use AWS CDK to deploy a S3 Bucket, static content, and create Route53 entries

“Mo, wtf is COGS?”: Breaking down acronyms and tribal knowledge for engineers

9 Techniques to Build Cloud-Native, Geo-Distributed SQL Apps with Low Latency

Fast and stable MongoDB-based tests in Spring

Publishing Events to Kafka using an Outbox Pattern

Deploy Fastai — Transformers based NLP models using Amazon SageMaker and Creating API using AWS…

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Nathan Wells

Nathan Wells

More from Medium

How Serverless Cloud Works (Part 2)

How to Create Thumbs with AWS Lambda

How to use AWS EventBridge to schedule tasks

How-To: AWS Lambda (Python) API Resolvers for AWS AppSync, Amplify, and Angular