How to remove disk from VM in Cloudforms, using custom Button? - ruby

Currently, I'm Setting up a custom button in Cloudforms to allow for the removal of a drive from a Virtual Machine that has been provisioned using Cloudforms(hooked into ansible)
I've been looking at this a little while and after some digging discovered the following https://github.com/ManageIQ/manageiq-automation_engine/blob/master/lib/miq_automation_engine/service_models/miq_ae_service_manageiq-providers-vmware-infra_manager-vm.rb
More specifically:
def remove_disk(disk_name, options = {})
sync_or_async_ems_operation(options[:sync], "remove_disk", [disk_name, options])
end
I've assumed two things, that this would probably take the vmdk name and would work the same as "add_disk" (vm.add_disk("[#{vm.storage_name}]", size * 1024, :sync => true)).
I AM AWARE that you can edit disks using the built-in functionality of CLoudforms via the provided configuration button, however, due to customer requirements we needed to edit the HAML files to remove some functionality. Redoing the HAML on every update of CloudForms is rather counterproductive. Creating our own custom dialogs provides us with the customization we needed.
# Get vm object
vm = $evm.root['vm']
raise "Missing $evm.root['vm'] object" unless vm
def log(level, message)
#method = 'Remove_Disk'
$evm.log(level, "#{#method} - #{message}")
end
$evm.create_notification(:audience => 'user', :level => :success, :message => "Lifecycle action 'Remove Disk' Initiated")
log(:info, "Started LCA to remove disk on vm: <#{vm}>")
# Remove disk from the VM
disk_choice = $evm.root['dialog_availabledisks'].to_i
if disk_choice.zero?
disk_name = "#{vm}"
$evm.create_notification(:audience => 'user', :level => :failure, :message => "Lifecycle action 'Remove Disk' Failed, OS Drive cannot be removed.")
log(:error, "C: Drive cannot be deleted")
exit MIQ_ABORT
else
disk_name = "#{vm}_#{disk_choice}"
end
log(:info, "Removing disk:<#{disk_name}> from #{vm}")
begin
vm.remove_disk(disk_name, :sync => true)
rescue => e
log(:error, "e: #{e}")
log(:error, "e.inspect: #{e.inspect}")
log(:error,"[#{e}]\n#{e.backtrace.join("\n")}")
log(:error, "e.message: #{e.message}")
end
exit MIQ_OK
My code runs through without any errors, however, does not actually do anything, the disk selected is not removed from the VM. Fairly sure I am just missing something obvious(Or my assumptions are incorrect), any ideas?

Hello I Have Successfully Remove Disk from VM in Cloudforms with Your Code
But There is one minor thing I have changed
you are using disk_name = "#{vm}_#{disk_choice}" as a disk name in order to delete Disk. But This is not like that.
You have to mention Datastore for that disk in disk_name then it will be work fine
you can try with following code
disk_name = "[your_datastore_name] #{vm}/#{vm}_#{disk_choice}.vmdk"
This works fine with me..!!
One more thing you can consider i.e Delete Backing
Delete Backing => OFF [Default] It will Just Detach your Disk from VM but not completely removed
so you have to turn on your Delete Backing so that it can completely remove disk from storage Domain as well
Delete Backing => ON
you can explore here
Thank you..!!

Related

How to mock a 3rd-party library [duplicate]

an important part of my project is to log in into remote server with ssh and do something with files on it:
Net::SSH.start(#host, #username, :password => #password) do |ssh|
ssh.exec!(rename_files_on_remote_server)
end
How to test it?
I think I can have local ssh server on and check file names on it (maybe it could be in my test/spec directory).
Or maybe someone could point me better solution?
I think it's enough to test that you're sending the correct commands to the ssh server. You're application presumably doesn't implement the server - so you have to trust that the server is correctly working and tested.
If you do implement the server then you'd need to test that, but as far as the SSH stuff goes, i'd do some mocking like this (RSpec 2 syntax):
describe "SSH Access" do
let (:ssh_connection) { mock("SSH Connection") }
before (:each) do
Net::SSH.stub(:start) { ssh_connection }
end
it "should send rename commands to the connection" do
ssh_connection.should_receive(:exec!).ordered.with("expected command")
ssh_connection.should_receive(:exec!).ordered.with("next expected command")
SSHAccessClass.rename_files!
end
end
Your suggested solution is similar to how I've done it before:
Log into the local machine. For convenience you could use 'localhost' or '127.0.0.1', but for a better simulation of network activity you might want to use the full hostname. On Mac OS and Linux you can grab the host easily by using:
`hostname`
or
require 'socket'
hostname = Socket.gethostname
which should be universal.
From there create or touch a file on the local machine after logging in, so you can test for the change with your test code.

Cannot get binaryfile using Ruby from one FTP server under Amazon EC2 instance

I have part of the code which is to get the binary file stream from one FTP server.
It works on my Ubuntu but the code cannot get the binary file from the FTP server when I tried it on the Amazon EC2 instance.
I tried to switch to another gem called open-uri. It can get the binary file stream on both my local PC and remote EC2 instance.
I use the default VPC of EC2 instance.
I already opened port 20 and 21 on EC2. I used dig ftp.cga.ct.gov and there is a answer on EC2.
If there is some point which is not clear for your guys, please point it out
Here is my code in the initialize method of one Ruby class:
def initialize(session_id)
#session_id = session_id
#count = 1
tries = 10
begin
ftp = Net::FTP.new("ftp.cga.ct.gov")
ftp.read_timeout = 500
ftp.login
ftp.chdir('/pub/data/')
bill_str= ftp.getbinaryfile("bill_info.csv", nil)
#bill_array = bill_str.delete("\"").split("\r\n")[1..-1]
rescue Exception => e
if (tries -= 1) > 0
sleep 10
print "re-connect"
retry
else
print "Cannot open FTP\nThe error message is #{e}\n#{e.backtrace.join("\n")}"
end
else
return true
end
super
end
I think it is totally because of Amazon internal subnet bugs. Check my other question and the answer from myself.

How can I tell if my machine is an EC2 instance or not?

I need a Ruby function that will tell me whether or not this machine is an EC2 instance, 100% of the time, even when DNS is broken on our EC2 instances.
The function that we were using was:
def is_ec2?
require 'socket'
Socket::gethostbyname('instance-data.ec2.internal.')
true
rescue
false
end
Except that when the DNS broke, every EC2 machine thought that it WASN'T an EC2 machine, and bad things happened, like the production machine deleting its own SSL certs and replacing them with the local develepment box's certs..
In Python, we're using:
#memoized
def is_ec2():
# This is a 99% check to avoid the need to wait for the timeout.
# Our VM's have this file. Our dev VM's don't.
if not os.path.isfile('/sys/hypervisor/uuid'):
return False
try:
result = boto.utils.get_instance_metadata()
if result == {}:
return False
return True
except Exception:
return False
Except for using wget -q -O - http://169.254.169.254/latest/meta-data instead of boto.utils.get_instance_metadata(), would that work?
Just put that in your hosts file and you won't have to worry about DNS.
But really, doesn't it make more sense to use an ENV var?

Programmatically get access_token from OAuth - Using JIRA-Ruby gem

I'm trying to write a JIRA-ruby script (only be used from command-line) to mark some JIRA issue closed automatically.
I borrow an example from here because I'm using 'jira-ruby' gem.
This works however it will pop-up a browser asking you to click "Allow" to get the access_token. I would like to do this programmatically, but I don't think the API was built for this purpose. As access_token changes every time, and this script will run periodically in a cronjob, so we need to have a way to do this. Any idea what other ways we can do this?
require 'jira'
#jira = JIRA::Client.new({:site => 'http://localhost:2990', :context_path => '/jira', :consumer_key => 'test-jira', :private_key_file => "rsakey.pem"})
if ARGV.length == 0
# If not passed any command line arguments, open a browser and prompt the
# user for the OAuth verifier.
request_token = #jira.request_token
puts "Opening #{request_token.authorize_url}"
system "open #{request_token.authorize_url}"
puts "Enter the oauth_verifier: "
oauth_verifier = gets.strip
access_token = #jira.init_access_token(:oauth_verifier => oauth_verifier)
puts "Access token: #{access_token.token} secret: #{access_token.secret}"
elsif ARGV.length == 2
# Otherwise assume the arguments are a previous access token and secret.
access_token = #jira.set_access_token(ARGV[0], ARGV[1])
else
# Script must be passed 0 or 2 arguments
raise "Usage: #{$0} [ token secret ]"
end
# Show all projects
projects = #jira.Project.all
projects.each do |project|
puts "Project -> key: #{project.key}, name: #{project.name}"
end
issue = #jira.Issue.find('DEMO-1')
puts issue
I know there's a way to use long-life access tokens, but not really use if Jira supports it.
I was using the jira-ruby gem at first but I found the performance terrible. I ended up just going with curl instead as I only needed to require the JSON gem which is less bloated. Have your Jira administrators create a user that will never have the password change with admin access and then do the following to find "DEMO-1"
require 'json'
username = "admin"
password = "abc123"
issue = JSON.parse(%x[curl -u #{username}:#{password} \"http://jira/rest/api/latest/issue/DEMO-1\"])
Here is a link to the Jira REST API documentation, just choose the same version of Jira you are using. This will bypass any issues with oauth and the pop-up.

firefox not opening - cron, ruby, firewatir

I have written a ruby script which opens up dlink admin page in firefox and does a ADSL connection or disconnection.
I could run this script in the terminal without any problem. But if I put it as cron job, it doesn't fire up firefox.
This is the entry I have in crontab
# connect to dataone
55 17 * * * ruby /home/raguanu/Dropbox/nettie.rb >> /tmp/cron_test
I see the following entries in /tmp/cron_test. So it looks like the script indeed ran.
PROFILE:
i486-linux
/usr/bin/firefox -jssh
But I couldn't figure out why I didn't see firefox opening up, for this automation to work. Here is /home/raguanu/Dropbox/nettie.rb
#!/usr/bin/ruby -w
require 'rubygems'
require 'firewatir'
require 'optiflag'
module Options extend OptiFlagSet
character_flag :d do
long_form 'disconnect'
description 'Mention this flag if you want to disconnect dataone'
end
flag :l do
optional
long_form 'admin_link'
default 'http://192.168.1.1'
description 'Dlink web administration link. Defaults to http://192.168.1.1'
end
flag :u do
optional
long_form 'user'
default 'admin'
description 'Dlink administrator user name. Defaults to "admin"'
end
flag :p do
optional
long_form 'password'
default 'admin'
description 'Dlink administrator password. Defaults to "admin"'
end
flag :c do
optional
long_form 'connection_name'
default 'bsnl'
description 'Dataone connection name. Defaults to "bsnl"'
end
extended_help_flag :h do
long_form 'help'
end
and_process!
end
class DlinkAdmin
include FireWatir
def initialize(admin_link = "http://192.168.1.1", user = 'admin', pwd = 'admin')
#admin_link, #user, #pwd = admin_link, user, pwd
end
def connect( connection_name = 'bsnl' )
goto_connection_page connection_name
# disconnect prior to connection
#browser.button(:value, 'Disconnect').click
# connect
#browser.button(:value, 'Connect').click
# done!
#browser.close
end
def disconnect( connection_name = 'bsnl' )
goto_connection_page connection_name
# disconnect
#browser.button(:value, 'Disconnect').click
# done!
#browser.close
end
private
def goto_connection_page( connection_name = 'bsnl')
#browser ||= Firefox.new
#browser.goto(#admin_link)
# login
#browser.text_field(:name, 'uiViewUserName').set(#user)
#browser.text_field(:name, 'uiViewPassword').set(#pwd)
#browser.button(:value,'Log In').click
# setup > dataone
#browser.image(:alt, 'Setup').click
#browser.link(:text, connection_name).click
end
end
admin = DlinkAdmin.new(Options.flags.l, Options.flags.u, Options.flags.p)
unless Options.flags.d?
admin.connect( Options.flags.c )
else
admin.disconnect( Options.flags.c )
end
Any help is appreciated.
You need to have a DISPLAY environment pointing at a valid X-server. This could either involve setting it to the value ":0.0" (without quotes), such that it refers to your local standard DISPLAY.
There's a few things to keep in mind though:
You could run an X virtual frame buffer (xvfb), so that Firefox simply uses that as it's display. This would mean that Firefox would be able to do all its graphical operations, but that it would be independent of your standard graphical environment. You'll have to set the DISPLAY variable appropriately so that it points to the xvfb instance. For instance, if you invoke xvfb as follows:
Xvfb :1 -screen 0 1600x1200x32
Then you'll be able to use this by setting the DISPLAY variable to :1
You're starting a full-blown firefox instance to simply connect or disconnect your modem. You would most likely be able to use "curl" to send the appropriate HTTP requests to the server, such that it performs a connect or disconnect for you. One way to trivially see what you should recreate would be to install a Firefox plugin such as LiveHTTPHeaders and note down the most important HTTP requests as you perform the actions manually.
There's even a ruby binding for curl:
libcurl for Ruby. The resulting script should be much smaller than your current script.
Programs run from cron don't have your interactive environment. Therefore they don't have and DISPLAY variable, and so you can't run any X (graphical) programs, e.g. Firefox.
I would suggest doing the HTTP connections yourself, in ruby, rather than trying to automate Firefox.
the crontab entry is wrong
it is like
#min hour day month dow user command
55 17 * * * ur_user_is_missing ruby /home/raguanu/Dropbox/nettie.rb >> /tmp/cron_test

Resources