{"id":46368,"date":"2017-02-24T12:09:27","date_gmt":"2017-02-24T06:39:27","guid":{"rendered":"http:\/\/www.tothenew.com\/blog\/?p=46368"},"modified":"2017-02-24T12:09:27","modified_gmt":"2017-02-24T06:39:27","slug":"how-to-run-fabric-using-aws-lambda-and-paramiko","status":"publish","type":"post","link":"https:\/\/www.tothenew.com\/blog\/how-to-run-fabric-using-aws-lambda-and-paramiko\/","title":{"rendered":"How to run Fabric using AWS Lambda and Paramiko?"},"content":{"rendered":"<p>We usually come across few scenarios where we need something to run on the remote servers for the sake of automation. I came across such a use case in <a href=\"http:\/\/www.tothenew.com\/devops-aws\">AWS<\/a> where I need to run fabric on a server to be triggered from <a title=\"Introduction To AWS LAMBDA\" href=\"http:\/\/www.tothenew.com\/blog\/introduction-to-aws-lambda\/\">AWS Lambda<\/a>. This fabric script further does few tasks on other servers.<\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone  wp-image-46369\" src=\"\/blog\/wp-ttn-blog\/uploads\/2017\/02\/fab.png\" alt=\"fab\" width=\"209\" height=\"163\" \/><img decoding=\"async\" loading=\"lazy\" class=\"alignnone  wp-image-46370\" src=\"\/blog\/wp-ttn-blog\/uploads\/2017\/02\/aws-lambda-300x300.png\" alt=\"aws-lambda\" width=\"164\" height=\"164\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2017\/02\/aws-lambda-300x300.png 300w, \/blog\/wp-ttn-blog\/uploads\/2017\/02\/aws-lambda-150x150.png 150w, \/blog\/wp-ttn-blog\/uploads\/2017\/02\/aws-lambda-624x624.png 624w, \/blog\/wp-ttn-blog\/uploads\/2017\/02\/aws-lambda.png 925w\" sizes=\"(max-width: 164px) 100vw, 164px\" \/><\/p>\n<p><b>Background\/Scenario:<\/b> While working on a spot instance, my architecture needs few files to be updated when a spot instance comes up or goes down. AWS Lambda gets triggered by the spot instance according to the events. Since <a title=\"AWS Lambda with new features for Mobile Devs\" href=\"http:\/\/www.tothenew.com\/blog\/aws-lambda-with-new-features-for-mobile-devs\/\">AWS Lambda supports few language\/platforms<\/a> including Python, I thought using Fabric would be a good idea to trigger from Lambda but Fabric needs \u201cfab\u201d binary to get executed and AWS Lambda does allow us to install anything on it. So, incorporated one EC2 instance on which <a title=\"DevOps Tools\" href=\"http:\/\/www.tothenew.com\/devops-chef-puppet-docker\">few DevOps tools<\/a> such as <a title=\"Understanding Chef and Writing Cookbooks\" href=\"http:\/\/www.tothenew.com\/blog\/understanding-chef-and-writing-cookbooks\/\">Chef <\/a>and <a title=\"7 Must-Have Jenkins Plugins\" href=\"http:\/\/www.tothenew.com\/blog\/7-must-have-jenkins-plugins\/\">Jenkins <\/a>were already running and installed Fabric on it.<\/p>\n<p>Now the next task was to execute the fabfile present on the server. Since Python on AWS Lambda does not have Paramiko module, I had build a package which contains the Paramiko module along with my pPthon code and uploaded the same on AWS Lambda. This would trigger Fabric configured on the server.<\/p>\n<p>Here are the steps which can help you to implement the above scenario.<\/p>\n<ol>\n<li>Install Fabric on a server and create a fabfile at any desired location containing your logic (say \/opt\/fabfile.py). This could be done on any existing EC2 instance running any utility service as Fabric would need few resource to run.a. Install a virtualenv on the system:\n<p>[js]sudo pip install virtualenv<br \/>\n#Or<br \/>\nsudo apt-get install python-virtualenv[\/js]<\/p>\n<p>b. Setup\/use virtualenv.<\/p>\n<p>[js]#create a folder for your app<br \/>\nvirtualenv ~\/my_app<br \/>\n#Activate the virtualenv<br \/>\ncd ~\/my_app\/bin<br \/>\nsource activate[\/js]<\/p>\n<p>c. Install the Paramiko module inside the virtual environment:<\/p>\n<p>[js]pip install paramiko[\/js]<\/p>\n<p>d. Add your Python source file:<\/p>\n<p>[js]cd ~\/my_app<br \/>\nvi my_script.py<br \/>\nimport sys<br \/>\nimport time<br \/>\nimport select<br \/>\nimport paramiko<br \/>\ndef functionName(event, context):<br \/>\n        host = &#8216;x.x.x.x&#8217;<br \/>\n        i = 1<br \/>\n        while True:<br \/>\n            try:<br \/>\n                ssh = paramiko.SSHClient()<br \/>\n                ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())<br \/>\n                ssh.connect(host,username=&quot;user&quot;,password=&quot;Pasword&quot;,port=22)<br \/>\n                print &quot;Connected to %s&quot; % host<br \/>\n                Break<br \/>\n            except paramiko.AuthenticationException:<br \/>\n                print &quot;Authentication failed when connecting to %s&quot; % host<br \/>\n                sys.exit(1)<br \/>\n            Except:<br \/>\n                print &quot;Could not SSH to %s, waiting for it to start&quot; % host<br \/>\n                i += 1<br \/>\n                time.sleep(2)<br \/>\n            # If we could not connect within time limit<br \/>\n            if i == 30:<br \/>\n                print &quot;Could not connect to %s. Giving up&quot; % host                sys.exit(1)<br \/>\n        # Send the command (non-blocking)<br \/>\n        stdin, stdout, stderr = ssh.exec_command(&quot;sudo \/usr\/bin\/fab -f \/home\/username\/fabfile.py copy&quot;)<br \/>\n        print &quot;Start Execuitng Fab&quot;<br \/>\n        &quot;&quot;&quot;<br \/>\n        while stdout.readline():<br \/>\n           print stdout.readline()<br \/>\n        ssh.close()<br \/>\n        &quot;&quot;&quot;<br \/>\n        while not stdout.channel.exit_status_ready():<br \/>\n            # Only print data if there is data to read in the channel<br \/>\n            if stdout.channel.recv_ready():<br \/>\n                rl, wl, xl = select.select([stdout.channel], [], [], 0.0)<br \/>\n                if len(rl) &gt; 0:<br \/>\n                    # Print data from stdout<br \/>\n                    print stdout.channel.recv(512),<br \/>\n        #<br \/>\n        # Disconnect from the host<br \/>\n        #<br \/>\n        print &quot;Command done, closing SSH connection&quot;<br \/>\n        ssh.close()<br \/>\nfunctionName(&quot;asdfsafd&quot;,&quot;Asdfasdf&quot;)[\/js]<\/p>\n<p>e. Copy all content from lib\/python2.7\/site-packages and lib64\/python2.7\/site-packages directories into ~\/myapp and compress the whole package into a zip file.<\/li>\n<li>Create a zip package to upload on an AWS Lambda function.<\/li>\n<li><span style=\"font-weight: 400\">Upload the zip on the AWS Lambda function. Against \u201cHandler\u201d field in AWS Lambda function write my_script.functionName. After running it, errors could come which are to the unavailability of few \u201c.so\u201d. Add the required \u201c.so\u201d file under \u201cmy_app\u201d and update the zip.<\/span><\/li>\n<li><span style=\"font-weight: 400\">After all required \u201c.so\u201d file is available, the Lambda function would do the desired task.<\/span><\/li>\n<\/ol>\n<p><strong><span style=\"font-weight: 400\">This use case is typically helpful for the scenario where we want to perform few tasks from a server which we have used as our utility server for which we have few scripts ready and needs to be triggered after an event.<\/span><\/strong><\/p>\n","protected":false},"excerpt":{"rendered":"<p>We usually come across few scenarios where we need something to run on the remote servers for the sake of automation. I came across such a use case in AWS where I need to run fabric on a server to be triggered from AWS Lambda. This fabric script further does few tasks on other servers. [&hellip;]<\/p>\n","protected":false},"author":506,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"iawp_total_views":29},"categories":[1174,2348,1],"tags":[1853,1679,1780,4440,4441,1358,4442],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/46368"}],"collection":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/users\/506"}],"replies":[{"embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/comments?post=46368"}],"version-history":[{"count":0,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/46368\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/media?parent=46368"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/categories?post=46368"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/tags?post=46368"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}