From: marios <[email protected]>

---
 server/lib/deltacloud/drivers/ec2/ec2_driver.rb    |   92 ++++++++++++++++-
 .../drivers/terremark/terremark_driver.rb          |  112 ++++++++++++++++++--
 2 files changed, 195 insertions(+), 9 deletions(-)

diff --git a/server/lib/deltacloud/drivers/ec2/ec2_driver.rb 
b/server/lib/deltacloud/drivers/ec2/ec2_driver.rb
index 076bfc4..6ced942 100644
--- a/server/lib/deltacloud/drivers/ec2/ec2_driver.rb
+++ b/server/lib/deltacloud/drivers/ec2/ec2_driver.rb
@@ -36,6 +36,7 @@ class EC2Driver < Deltacloud::BaseDriver
 
   feature :instances, :user_data
   feature :instances, :authentication_key
+  feature :access_rules, :show
 
   define_hardware_profile('m1.small') do
     cpu                1
@@ -230,7 +231,6 @@ class EC2Driver < Deltacloud::BaseDriver
   #
   # Storage Snapshots
   #
-
   def storage_snapshots(credentials, opts=nil)
     ec2 = new_client( credentials )
     snapshots = []
@@ -250,6 +250,70 @@ class EC2Driver < Deltacloud::BaseDriver
     snapshots
   end
 
+#--
+# ACCESS RULES
+#--
+  def access_rules(credentials, opts={})
+    rules = []
+    ec2 = new_client(credentials)
+    ec2.describe_security_groups().securityGroupInfo.item.each do |group| 
+        group_name = group['groupName'] 
+        unless group.ipPermissions.nil?
+          group.ipPermissions.item.each do |rule|
+            if rule['ipRanges'] #i.e. with cidr address - not interested in 
access to groups
+              protocol = rule['ipProtocol']
+              port_start = rule['fromPort']
+              port_end = rule['toPort'] 
+              ports = (protocol.downcase == 'icmp') ? '' : ((port_start == 
port_end) ? port_start : "#{port_start}-#{port_end}")
+              id = "#{group_name}_#{protocol}:#{ports}"
+              rules << AccessRule.new({ :id => id,
+                                        :port => ports,
+                                        :protocol => protocol,
+                                        :instance_group => group_name
+                                      })
+            end #if
+         end #ipPermissions.item.each do
+      end #unless 
+    end #securityGroupInfo.item.each do
+    rules
+  end 
+
+#--
+# CREATE_ACCESS_RULE
+#--
+  def create_access_rule(credentials, opts={})
+    #at minimum can expect: opts['protocol'] and opts['port']
+    ec2 = new_client(credentials)
+    protocol = opts['protocol'].downcase
+    icmp = (protocol.downcase == 'icmp') #if icmp, ports should be -1
+    port = (icmp ? '-1' : opts['port'])
+    instance_group = opts['instance_group']
+    cidr_ip = '0.0.0.0/0' #open to all
+    opts = { :ip_protocol => protocol, :from_port => port,
+             :to_port => port, :cidr_ip => cidr_ip, :group_name => 
instance_group }
+    ec2.authorize_security_group_ingress(opts)
+  end
+
+#--
+# DELETE_ACCESS_RULE
+#--
+  def delete_access_rule(credentials, opts={})
+    ec2 = new_client(credentials)
+    #opts['id'] eg "default_tcp:22"
+    instance_group = opts[:id].to_s.split("_").first
+    protocol = opts[:id].to_s.split("_").last.split(":").first
+    icmp = (protocol.downcase == 'icmp') #if icmp, ports should be -1
+    port = (icmp ? '-1' : opts[:id].to_s.split("_").last.split(":").last)
+    options = {     :group_name => instance_group,
+                    :ip_protocol => protocol,
+                    :from_port => port,
+                    :to_port => port,
+                    :cidr_ip => "0.0.0.0/0",
+              }
+    ec2.revoke_security_group_ingress(options)
+  end
+
+
   private
 
   def new_client(credentials)
@@ -338,3 +402,29 @@ end
     end
   end
 end
+
+
+#(13:15:54) mfojtik_: i'll write a notes about features here, because it will 
look messy on channel ;-)
+#(13:16:41) mfojtik_: so first of all you need to define a new feature in 
"lib/deltacloud/base_driver/features.rb"
+#(13:16:55) mfojtik_: fir example:
+#(13:16:56) mfojtik_:     declare_feature :instances, :authentication_password 
do
+#(13:16:56) mfojtik_:       operation :create do
+#(13:16:56) mfojtik_:         param :password, :string, :optional
+#(13:16:56) mfojtik_:       end
+#(13:16:58) mfojtik_:     end
+#(13:17:32) mfojtik_: so now, this feature is accessible to all drivers
+#(13:17:47) mfojtik_: then you open ec2_driver and declare that feature here:
+#(13:17:49) mfojtik_:   feature :instances, :authentication_key
+#(13:18:39) mfojtik_: that's all, now this feature will be advertised in /api
+#(13:18:46) marios: great... thats very cool
+#(13:18:56) mfojtik_: then next, if you want add a new fields into Instance 
class
+#(13:19:06) mfojtik_: you can do this in driver:
+#(13:19:14) mfojtik_: class Instance attr_accessor :keyname attr_accessor 
:authn_error
+#(13:19:16) mfojtik_: err.
+#(13:19:19) mfojtik_: again:
+#(13:19:21) mfojtik_: class Instance
+#(13:19:29) mfojtik_: attr_accessor :security_group
+#(13:19:30) mfojtik_: end
+
+
+
diff --git a/server/lib/deltacloud/drivers/terremark/terremark_driver.rb 
b/server/lib/deltacloud/drivers/terremark/terremark_driver.rb
index ae3c554..fe27eb3 100644
--- a/server/lib/deltacloud/drivers/terremark/terremark_driver.rb
+++ b/server/lib/deltacloud/drivers/terremark/terremark_driver.rb
@@ -32,8 +32,8 @@ module Deltacloud
 
 class TerremarkDriver < Deltacloud::BaseDriver
 
-  feature :instances, :user_name
-
+feature :instances, :user_name
+feature :access_rules, :show
 #--
 # Vapp State Map... for use with convert_instance (get an integer back from 
terremark)
 #--
@@ -95,7 +95,7 @@ VAPP_STATE_MAP = { "0" =>  "PENDING", "1" =>  "PENDING", "2" 
=>  "STOPPED", "4"
         if(current_item['type'] == 'application/vnd.vmware.vcloud.vApp+xml')
            vapp_id =  current_item['href'].split('/').last
            vapp = terremark_client.get_vapp(vapp_id)
-           instances  << convert_instance(vapp, terremark_client, 
credentials.user)
+           instances  << convert_instance(vapp, terremark_client, 
{'account_name' => credentials.user})
         end
       }#end vdc_items.each
       instances = filter_on( instances, :id, opts )
@@ -140,7 +140,7 @@ VAPP_STATE_MAP = { "0" =>  "PENDING", "1" =>  "PENDING", 
"2" =>  "STOPPED", "4"
 #######
     vapp_id = terremark_client.instantiate_vapp_template(name, image_id, 
vapp_opts).body['href'].split('/').last
     new_vapp = terremark_client.get_vapp(vapp_id)
-    return convert_instance(new_vapp, terremark_client, credentials.user) 
#return an Instance object
+    return convert_instance(new_vapp, terremark_client, {'account_name' => 
credentials.user}) #return an Instance object
   end
 
 #--
@@ -148,15 +148,19 @@ VAPP_STATE_MAP = { "0" =>  "PENDING", "1" =>  "PENDING", 
"2" =>  "STOPPED", "4"
 #--
   def reboot_instance(credentials, id)
     terremark_client =  new_client(credentials)
+    vapp = terremark_client.get_vapp(id)
     terremark_client.power_reset(id)
+    return convert_instance(vapp, terremark_client, {'vapp_status' => '4', 
'account_name' => credentials.user})
   end
-
+#status == 0/1->BEING_CREATED 2->OFF 4->ON
 #--
 # START INSTANCE
 #--
 def start_instance(credentials, id)
     terremark_client =  new_client(credentials)
+    vapp = terremark_client.get_vapp(id)
     terremark_client.power_on(id)
+    return convert_instance(vapp, terremark_client, {'vapp_status' => '4', 
'account_name' => credentials.user})
 end
 
 #--
@@ -164,7 +168,9 @@ end
 #--
 def stop_instance(credentials, id)
     terremark_client = new_client(credentials)
+    vapp = terremark_client.get_vapp(id)
     terremark_client.power_shutdown(id)
+    return convert_instance(vapp, terremark_client, {'vapp_status' => '2', 
'account_name' => credentials.user})
 end
 
 #--
@@ -177,12 +183,99 @@ def destroy_instance(credentials, id)
 end
 
 #--
+# ACCESS RULES
+#--
+  def access_rules(credentials, opts=nil)
+    access_rules = []
+    terremark_client = new_client(credentials)
+    services = 
terremark_client.get_internet_services(terremark_client.default_vdc_id).body['InternetServices'].each
 do |service|
+      port = service['Port']
+      s_id = service['Id'].to_s
+      protocol = service['Protocol']
+      nodes = terremark_client.get_node_services(s_id).body['NodeServices']
+      unless nodes.empty?
+        nodes.each do |node|
+          rule_id = "#{s_id}_#{node['IpAddress']}"
+          access_rules << AccessRule.new({  :id => rule_id,
+                                            :port => port,
+                                            :instance_group => 
"#{service['PublicIpAddress']['Name']}",
+                                            :protocol => protocol
+                                          })
+        end #nodes.each do
+      end #unless nodes empty
+    end #services.each do
+    access_rules = filter_on( access_rules, :id, opts )
+    access_rules
+  end
+
+#--
+# DELETE ACCESS RULE
+#--
+ def delete_access_rule(credentials, opts=nil)
+   service_id = opts[:id].to_s.split("_").first # "xxx_111.222.111.222" where 
xxx is tmark service Id
+   terremark_client = new_client(credentials)
+   nodes = terremark_client.get_node_services(service_id).body['NodeServices']
+   unless nodes.empty?
+     nodes.each do |node|
+       terremark_client.delete_node_service(node['Id'])
+     end
+   end
+   terremark_client.delete_internet_service(service_id)
+ end
+
+#--
+# CREATE NEW ACCESS RULE
+#--
+#--expects opts['port'], opts['protocol'], opts['instance_group']
+  def create_access_rule(credentials, opts={})
+    terremark_client = new_client(credentials)
+    port = opts['port']
+    protocol = opts['protocol']
+    instance_group = opts['instance_group']
+    #need the public ip address for the internet service
+    ip_id = nil #id of the IP address (from terremark)
+    service_id=nil
+    ip_addresses = 
terremark_client.get_public_ips(terremark_client.default_vdc_id).body['PublicIpAddresses']
+    ip_addresses.each do |ip_address|
+      ip_id = ip_address['id'].to_s
+      service_id = internet_service_exists(terremark_client, 
ip_address['name'], port, protocol)
+      if service_id 
+        break 
+      end
+    end #ip_addresses.each
+    unless service_id #in which case we create a new internet service
+      service_name ||= opts['service_name']
+      service_name ||= "svc" + (rand(1000)*Time.now.to_i).to_s.slice(0,7)
+      service_id = terremark_client.add_internet_service(ip_id, service_name, 
protocol, port).body['Id'].to_s
+    end
+    node_name ||= opts['node_name']
+    node_name ||= "nod" + (rand(1000)*Time.now.to_i).to_s.slice(0,7)
+    private_port = port #use same private port as public one...?
+    terremark_client.add_node_service(service_id, instance_group, node_name, 
private_port)
+  end
+
+#--
 # PRIVATE METHODS:
 #--
 
  private
 
 #--
+# INTERNET_SERVICE_EXISTS
+#-- helper to check if a given public IP/Port combination are defined as an 
existing internet service
+#-- used by the create_access_rule method
+def internet_service_exists(terremark_client, public_address, public_port, 
protocol)
+    services = 
terremark_client.get_internet_services(terremark_client.default_vdc_id)
+    services.body['InternetServices'].each do |current_service|
+      if ( (current_service['PublicIpAddress']['Name'] == public_address) && 
(current_service['Port'].to_s == public_port) &&
+            (current_service['Protocol'].upcase == protocol.upcase) )
+            return current_service['Id']
+      end
+    end
+    nil #either return the service id or nil
+end
+
+#--
 # CONVERT IMAGE
 #--
 #gets a vapp_template from a catalog and makes it a Image
@@ -204,10 +297,13 @@ end
 #--
 # CONVERT INSTANCE
 #--
-  def convert_instance(vapp, terremark_client, account_name)
+  def convert_instance(vapp, terremark_client, opts={})
       vapp_private_ip = vapp.body['IpAddress']
       vapp_public_ip = 
terremark_client.get_public_ips(terremark_client.default_vdc_id).body['PublicIpAddresses'].first['name']#get_public_address(terremark_client,
 vapp_private_ip)
-      vapp_status = vapp.body['status']
+      unless opts['vapp_status'] 
+        vapp_status = vapp.body['status']
+      end
+      vapp_status ||= opts['vapp_status']
       current_state = VAPP_STATE_MAP[vapp_status] #status == 0->BEING_CREATED 
2->OFF 4->ON
       profile = InstanceProfile.new("default")
       name = vapp.body['name']
@@ -226,7 +322,7 @@ end
       end
       Instance.new( {
                     :id => vapp.body['href'].split('/').last,
-                    :owner_id => "#{account_name}",
+                    :owner_id => "#{opts['account_name']}",
                     #:image_id => "n/a", #cant get this... see 
https://community.vcloudexpress.terremark.com/en-us/discussion_forums/f/60/t/376.aspx
                     :name => name,
                     :realm_id => "US-Miami",
-- 
1.6.6.1

_______________________________________________
deltacloud-devel mailing list
[email protected]
https://fedorahosted.org/mailman/listinfo/deltacloud-devel

Reply via email to