[Ovirt-devel] [PATCH server 07/10] use service layer for Network controller.

Scott Seago sseago at redhat.com
Tue May 19 14:23:14 UTC 2009


There's still room for additional refactoring as we may want to eventually split out nic, bonding, and ip address manipulation into their own controller/svc module, but that would be a much more extensive redesign than we want to deal with for the overall service layer creation refactoring.

Signed-off-by: Scott Seago <sseago at redhat.com>
---
 src/app/controllers/network_controller.rb |  521 ++++++-----------------------
 src/app/models/ip_address.rb              |   11 +
 src/app/models/network.rb                 |   12 +
 src/app/models/physical_network.rb        |    4 +
 src/app/models/vlan.rb                    |    5 +
 src/app/services/network_service.rb       |  392 ++++++++++++++++++++++
 6 files changed, 534 insertions(+), 411 deletions(-)
 create mode 100644 src/app/services/network_service.rb

diff --git a/src/app/controllers/network_controller.rb b/src/app/controllers/network_controller.rb
index 244d041..5af0a73 100644
--- a/src/app/controllers/network_controller.rb
+++ b/src/app/controllers/network_controller.rb
@@ -18,471 +18,170 @@
 #
 
 class NetworkController < ApplicationController
+  include NetworkService
    ########################## Networks related actions
 
-  before_filter :pre_list, :only => [:list]
-
-   def authorize_admin
-     # TODO more robust permission system
-     #  either by subclassing network from pool
-     #  or by extending permission model to accomodate
-     #  any object
-     @default_pool = HardwarePool.get_default_pool
-     set_perms(@default_pool)
-     super('You do not have permission to access networks')
-   end
-
-   def pre_list
-     @networks = Network.find(:all)
-     authorize_admin
-   end
-
-   def list
-     respond_to do |format|
-       format.html {
-         render :layout => 'tabs-and-content' if params[:ajax]
-         render :layout => 'help-and-content' if params[:nolayout]
-       }
-       format.xml {
-         render :xml => @pool.to_xml(XML_OPTS)
-       }
-     end
-   end
-
-   def networks_json
-      json_list(Network.find(:all), [:id, :name, :type, [:boot_type, :label]])
-   end
+  def list
+    svc_list()
+    respond_to do |format|
+      format.html {
+        render :layout => 'tabs-and-content' if params[:ajax]
+        render :layout => 'help-and-content' if params[:nolayout]
+      }
+      format.xml {
+        render :xml => @pool.to_xml(XML_OPTS)
+      }
+    end
+  end
 
-   def pre_show
-     @network = Network.find(params[:id])
-     authorize_admin
-   end
+  def networks_json
+    svc_list
+    json_list(@networks, [:id, :name, :type, [:boot_type, :label]])
+  end
 
-   def show
+  def show
+    svc_show(params[:id])
     respond_to do |format|
       format.html { render :layout => 'selection' }
       format.xml { render :xml => @network.to_xml }
     end
-   end
+  end
 
-   def new
+  def new
+    svc_new()
     @boot_types = BootType.find(:all)
     @usage_types = Usage.find(:all)
     render :layout => 'popup'
-   end
+  end
 
-   def create
-    begin
-     @network = PhysicalNetwork.new(params[:network]) if params[:network][:type] == 'PhysicalNetwork'
-     @network = Vlan.new(params[:network]) if params[:network][:type] == 'Vlan'
-     @network.save!
-     alert = "Network was successfully created."
-     render :json => { :object => "network", :success => true,
-                       :alert => alert  }
-    rescue
-     render :json => { :object => "network", :success => false,
-                        :errors =>
-                        @network.errors.localize_error_messages.to_a }
-    end
-   end
+  def create
+    alert = svc_create(params[:network])
+    render :json => { :object => "network", :success => true, :alert => alert  }
+  end
 
-   def edit
-    @network = Network.find(params[:id])
+  def edit
+    svc_modify(params[:id])
     @usage_types = Usage.find(:all)
     @boot_types = BootType.find(:all)
     render :layout => 'popup'
-   end
-
-   def update
-    begin
-     @network = Network.find(params[:id])
-     if @network.type == 'PhysicalNetwork'
-       @network = PhysicalNetwork.find(params[:id])
-     else
-       @network = Vlan.find(params[:id])
-     end
+  end
 
-     @network.usages.delete_all
-     @network.update_attributes!(params[:network])
+  def update
+    alert = svc_update(params[:id], params[:network])
+    render :json => { :object => "network", :success => true, :alert => alert }
+  end
 
-     alert = "Network was successfully updated."
-     render :json => { :object => "network", :success => true,
-                       :alert => alert  }
-    rescue Exception => e
-     render :json => { :object => "network", :success => false,
-                        :errors =>
-                        @network.errors.localize_error_messages.to_a }
+  def delete
+    network_ids = params[:network_ids].split(",")
+    successes = []
+    failures = {}
+    network_ids.each do |network_id|
+      begin
+        svc_destroy(network_id)
+        successes << @network
+      rescue PermissionError => perm_error
+        failures[@network] = perm_error.message
+      rescue ActionError => ex
+        failures[@network] = ex.message
+      rescue Exception => ex
+        failures[@network] = ex.message
+      end
     end
-   end
-
-   def delete
-     failed_networks = []
-     networks_ids_str = params[:network_ids]
-     network_ids = networks_ids_str.split(",").collect {|x| x.to_i}
-     network_ids.each{ |x|
-       network = Network.find(x)
-       unless network.type.to_s == 'Vlan' &&
-               Vlan.find(x).bondings.size != 0 ||
-              network.type.to_s == 'PhysicalNetwork' &&
-               PhysicalNetwork.find(x).nics.size != 0
-         begin
-            Network.destroy(x)
-         rescue
-           failed_networks.push x
-         end
-       else
-         failed_networks.push x
-       end
-     }
-     if failed_networks.size == 0
-      render :json => { :object => "network",
-                        :success => true,
-                        :alert => "Successfully deleted networks" }
-     else
-      render :json => { :object => "network",
-                        :success => false,
-                        :alert => "Failed deleting " +
-                                  failed_networks.size.to_s +
-                             " networks due to existing bondings/nics" }
-     end
-   end
+    unless failures.empty?
+      raise PartialSuccessError.new("Delete failed for some networks",
+                                    failures, successes)
+    end
+    render :json => { :object => "network", :success => true,
+                      :alert => "Networks were successfully deleted." }
+  end
 
-   def edit_network_ip_addresses
-    @network = Network.find(params[:id])
+  def edit_network_ip_addresses
+    svc_modify(params[:id])
     render :layout => 'popup'
-   end
+  end
 
 
    ########################## Ip Address related actions
 
-   def ip_addresses_json
-    @parent_type = params[:parent_type]
-    if @parent_type == 'network'
-      ip_addresses = Network.find(params[:id]).ip_addresses
-    elsif @parent_type == 'nic'
-      ip_addresses = Nic.find(params[:id]).ip_addresses
-    elsif @parent_type == 'bonding' and params[:id]
-      ip_addresses = Bonding.find(params[:id]).ip_addresses
-    else
-      ip_addresses = []
-    end
-
+  def ip_addresses_json
+    svc_ip_addresses(params[:parent_type], params[:id])
     ip_addresses_json = []
-    ip_addresses.each{ |x|
+    @ip_addresses.each{ |x|
           ip_addresses_json.push({:id => x.id, :name => x.address}) }
     render :json => ip_addresses_json
    end
 
    def new_ip_address
-    @parent_type = params[:parent_type]
-    @network = Network.find(params[:id]) if @parent_type == 'network'
-    @nic = Nic.find(params[:id]) if @parent_type == 'nic'
-    @bonding = Bonding.find(params[:id]) if @parent_type == 'bonding' and params[:id]
-
+    svc_ip_addresses(params[:parent_type], params[:id])
     render :layout => false
    end
 
-  def _create_ip_address
-    if params[:ip_address][:type] == "IpV4Address"
-      @ip_address = IpV4Address.new(params[:ip_address])
-    else
-      @ip_address = IpV6Address.new(params[:ip_address])
-    end
-    @ip_address.save!
-  end
-
   def create_ip_address
-   begin
-    _create_ip_address
-    alert = "Ip Address was successfully created."
-    render :json => { :object => "ip_address", :success => true,
-                      :alert => alert  }
-   rescue
-    render :json => { :object => "ip_address", :success => false,
-                      :errors =>
-                        @ip_address.errors.localize_error_messages.to_a }
-    end
-   end
-
-   def edit_ip_address
-    @ip_address = IpAddress.find(params[:id])
-
-    @parent_type = params[:parent_type]
-    @network = @ip_address.network if @ip_address.network_id
-    @nic = @ip_address.nic if @ip_address.nic_id
-    @bonding = @ip_address.bonding if @ip_address.bonding_id
+    alert = svc_create_ip_address(params[:ip_address])
+    render :json => {:object => "ip_address", :success => true, :alert => alert}
+  end
 
+  def edit_ip_address
+    svc_modify_ip_address(params[:parent_type], params[:id])
     render :layout => false
-   end
-
-   def _update_ip_address(id)
-     @ip_address = IpAddress.find(id)
-
-     # special case if we are switching types
-     if @ip_address.type != params[:ip_address][:type]
-       if params[:ip_address][:type] == 'IpV4Address'
-          @ip_address = IpV4Address.new(params[:ip_address])
-          @ip_address.save!
-          IpV6Address.delete(id)
-       else
-          @ip_address = IpV6Address.new(params[:ip_address])
-          @ip_address.save!
-          IpV4Address.delete(id)
-       end
-     else
-       if @ip_address.type == 'IpV4Address'
-          @ip_address = IpV4Address.find(id)
-       else
-          @ip_address = IpV6Address.find(id)
-       end
-       @ip_address.update_attributes!(params[:ip_address])
-     end
-
-   end
-
-   def update_ip_address
-    begin
-     _update_ip_address(params[:id])
-     alert = "IpAddress was successfully updated."
-     render :json => { :object => "network", :success => true,
-                       :alert => alert  }
-    rescue
-     render :json => { :object => "ip_address", :success => false,
-                        :errors =>
-                        @ip_address.errors.localize_error_messages.to_a }
-    end
-   end
+  end
 
-   def destroy_ip_address
-    begin
-     IpAddress.delete(params[:id])
-     alert = "Ip Address was successfully deleted."
-     render :json => { :object => "ip_address", :success => true,
-                       :alert => alert  }
-    rescue
-     render :json => { :object => "ip_address", :success => false,
-                      :alert => 'Ip Address Deletion Failed' }
-     end
-   end
+  def update_ip_address
+    alert = svc_update_ip_address(params[:id], params[:ip_address])
+    render :json => {:object => "ip_address", :success => true, :alert => alert}
+  end
 
+  def destroy_ip_address
+    alert = svc_destroy_ip_address(params[:id])
+    render :json => {:object => "ip_address", :success => true, :alert => alert}
+  end
 
    ########################## NICs related actions
 
-   def edit_nic
-     @nic = Nic.find(params[:id])
-     @network = @nic.physical_network
-
-     # filter out networks already assigned to nics on host
-     network_conditions = []
-     @nic.host.nics.each { |nic|
-        unless nic.physical_network.nil? || nic.id == @nic.id
-          network_conditions.push(" id != " + nic.physical_network.id.to_s)
-        end
-     }
-     network_conditions = network_conditions.join(" AND ")
-
-     @networks = PhysicalNetwork.find(:all, :conditions => network_conditions)
-     network_options
-
-     render :layout => false
-   end
-
-   def update_nic
-    begin
-     network_options
-
-     unless params[:nic][:physical_network_id].nil? || params[:nic][:physical_network_id].to_i == 0
-      @network = Network.find(params[:nic][:physical_network_id])
-      if @network.boot_type.id == @static_boot_type.id
-        if params[:ip_address][:id] == "New"
-          _create_ip_address
-        elsif params[:ip_address][:id] != ""
-          _update_ip_address(params[:ip_address][:id])
-        end
-      end
-     end
-
-     @nic = Nic.find(params[:id])
-     @nic.update_attributes!(params[:nic])
+  def edit_nic
+    svc_modify_nic(params[:id])
+    render :layout => false
+  end
 
-     alert = "Nic was successfully updated."
-     render :json => { :object => "nic", :success => true,
-                       :alert => alert  }
-    rescue Exception => e
-     if @ip_address and @ip_address.errors.size != 0
-        render :json => { :object => "ip_address", :success => false,
-                          :errors =>
-                            @ip_address.errors.localize_error_messages.to_a}
-     else
-        render :json => { :object => "nic", :success => false,
-                          :errors =>
-                          @nic.errors.localize_error_messages.to_a }
-     end
-    end
-   end
+  def update_nic
+    alert = svc_update_nic(params[:id], params[:nic], params[:ip_address])
+    render :json => { :object => "nic", :success => true, :alert => alert}
+  end
 
    ########################## Bonding related actions
 
-   def new_bonding
-    unless params[:host_id]
-      flash[:notice] = "Host is required."
-      redirect_to :controller => 'dashboard'
-    end
-
-    @host = Host.find(params[:host_id])
-
-    # FIXME when bonding_nics table is removed, and
-    # bondings_id column added to nics table, simplify
-    # (select where bonding.nil?)
-    @nics = []
-    @host.nics.each{ |nic|
-      @nics.push(nic) if nic.bondings.nil? || nic.bondings.size == 0
-    }
-
-    # filter out networks already assigned to bondings on host
-    network_conditions = []
-    @host.bondings.each { |bonding|
-       unless bonding.vlan.nil?
-         network_conditions.push(" id != " + bonding.vlan.id.to_s)
-       end
-    }
-    network_conditions = network_conditions.join(" AND ")
-
-    @networks = Vlan.find(:all, :conditions => network_conditions)
-    network_options
-
+  def new_bonding
+    raise ActionError.new("Host is required") unless params[:host_id]
+    svc_new_bonding(params[:host_id])
     render :layout => false
    end
 
-   def create_bonding
-    begin
-     network_options
-
-     unless params[:bonding][:vlan_id].nil? || params[:bonding][:vlan_id].to_i == 0
-       @network = Network.find(params[:bonding][:vlan_id])
-       if @network.boot_type.id == @static_boot_type.id
-         if params[:ip_address][:id] == "New"
-           _create_ip_address
-         elsif params[:ip_address][:id] != ""
-           _update_ip_address(params[:ip_address][:id])
-         end
-       end
-     end
-
-    @bonding = Bonding.new(params[:bonding])
-    @bonding.ip_addresses << @ip_address if @ip_address
-    @bonding.save!
-
-    if @ip_address
-       @ip_address.bonding_id = @bonding.id
-       @ip_address.save!
-    end
-
-     alert = "Bonding was successfully created."
-     render :json => { :object => "bonding", :success => true,
-                       :alert => alert  }
-    rescue
-     if @ip_address and @ip_address.errors.size != 0
-        render :json => { :object => "ip_address", :success => false,
-                          :errors =>
-                            @ip_address.errors.localize_error_messages.to_a}
-     else
-        render :json => { :object => "bonding", :success => false,
-                          :errors =>
-                          @bonding.errors.localize_error_messages.to_a }
-     end
-    end
-   end
-
-   def edit_bonding
-     @bonding = Bonding.find(params[:id])
-     @network = @bonding.vlan
-
-     @host = @bonding.host
-
-     # FIXME when bonding_nics table is removed, and
-     # bondings_id column added to nics table, simplify
-     # (select where bonding.nil? or bonding has nic)
-     @nics = []
-     @host.nics.each{ |nic|
-       if nic.bondings.nil? ||
-          nic.bondings.size == 0 ||
-          nic.bondings[0].id == @bonding.id
-        @nics.push(nic)
-       end
-     }
-
-     # filter out networks already assigned to bondings on host
-     network_conditions = []
-     @host.bondings.each { |bonding|
-        unless bonding.vlan.nil? || bonding.id == @bonding.id
-          network_conditions.push(" id != " + bonding.vlan.id.to_s)
-        end
-     }
-     network_conditions = network_conditions.join(" AND ")
-
-     @networks = Vlan.find(:all, :conditions => network_conditions)
-     network_options
-
-     render :layout => false
-   end
-
-   def update_bonding
-    begin
-     network_options
-
-     unless params[:bonding][:vlan_id].nil? || params[:bonding][:vlan_id].to_i == 0
-       @network = Network.find(params[:bonding][:vlan_id])
-       if @network.boot_type.id == @static_boot_type.id
-         if params[:ip_address][:id] == "New"
-           _create_ip_address
-         elsif params[:ip_address][:id] != ""
-           _update_ip_address(params[:ip_address][:id])
-         end
-       end
-     end
-
-     @bonding = Bonding.find(params[:id])
-     @bonding.nics.delete_all
-     @bonding.update_attributes!(params[:bonding])
-
-     alert = "Bonding was successfully updated."
-     render :json => { :object => "bonding", :success => true,
-                       :alert => alert  }
-    rescue Exception => e
-     if @ip_address and @ip_address.errors.size != 0
-        render :json => { :object => "ip_address", :success => false,
-                          :errors =>
-                            @ip_address.errors.localize_error_messages.to_a}
-     else
-       render :json => { :object => "bonding", :success => false,
-                          :errors =>
-                          @bonding.errors.localize_error_messages.to_a }
-     end
-    end
-   end
-
-   def destroy_bonding
-    begin
-     Bonding.destroy(params[:id])
-     alert = "Bonding was successfully deleted."
-     render :json => { :object => "bonding", :success => true,
-                       :alert => alert  }
-    rescue
-     render :json => { :object => "bonding", :success => false,
-                      :alert => 'Bonding Deletion Failed' }
-     end
+  def create_bonding
+    alert = svc_create_bonding(params[:bonding], params[:ip_address])
+    render :json => { :object => "bonding", :success => true, :alert => alert}
+  end
 
-   end
+  def edit_bonding
+    svc_modify_bonding(params[:id])
+    render :layout => false
+  end
 
+  def update_bonding
+    alert = svc_update_bonding(params[:id], params[:bonding], params[:ip_address])
+    render :json => { :object => "bonding", :success => true, :alert => alert}
+  end
 
-   ########################## Misc methods
+  def destroy_bonding
+    alert = svc_destroy_bonding(params[:id])
+    render :json => {:object => "bonding", :success => true, :alert => alert}
+  end
 
   protected
-   def network_options
-    @bonding_types = BondingType.find(:all)
-    @static_boot_type = BootType.find(:first,
-                                 :conditions => { :proto => 'static' })
-   end
+  # FIXME: remove these when service transition is complete. these are here
+  # to keep from running permissions checks and other setup steps twice
+  def tmp_pre_update
+  end
+  def tmp_authorize_admin
+  end
 
 end
diff --git a/src/app/models/ip_address.rb b/src/app/models/ip_address.rb
index 5d2e6af..4e4c7d3 100644
--- a/src/app/models/ip_address.rb
+++ b/src/app/models/ip_address.rb
@@ -24,4 +24,15 @@ class IpAddress < ActiveRecord::Base
    belongs_to :network
    belongs_to :nic
    belongs_to :bonding
+
+  def self.factory(params = {})
+    case params[:type]
+    when "IpV4Address"
+      return IpV4Address.new(params)
+    when "IpV6Address"
+      return IpV6Address.new(params)
+    else
+      return nil
+    end
+  end
 end
diff --git a/src/app/models/network.rb b/src/app/models/network.rb
index 0ad38bb..1c6fe97 100644
--- a/src/app/models/network.rb
+++ b/src/app/models/network.rb
@@ -31,4 +31,16 @@ class Network < ActiveRecord::Base
   validates_presence_of :boot_type_id,
     :message => 'A boot type must be specified.'
 
+  def self.factory(params = {})
+    case params[:type]
+    when 'PhysicalNetwork'
+      return PhysicalNetwork.new(params)
+    when 'Vlan'
+      return Vlan.new(params)
+    else
+      return nil
+    end
+  end
+
+
 end
diff --git a/src/app/models/physical_network.rb b/src/app/models/physical_network.rb
index 6923e40..52a748a 100644
--- a/src/app/models/physical_network.rb
+++ b/src/app/models/physical_network.rb
@@ -18,4 +18,8 @@
 
 class PhysicalNetwork < Network
    has_many :nics
+
+  def is_destroyable?
+    nics.empty?
+  end
 end
diff --git a/src/app/models/vlan.rb b/src/app/models/vlan.rb
index f7889f4..2f6acba 100644
--- a/src/app/models/vlan.rb
+++ b/src/app/models/vlan.rb
@@ -21,4 +21,9 @@ class Vlan < Network
 
   validates_presence_of :number,
     :message => 'A number must be specified.'
+
+  def is_destroyable?
+    bondings.empty?
+  end
+
 end
diff --git a/src/app/services/network_service.rb b/src/app/services/network_service.rb
new file mode 100644
index 0000000..551b60c
--- /dev/null
+++ b/src/app/services/network_service.rb
@@ -0,0 +1,392 @@
+#
+# Copyright (C) 2009 Red Hat, Inc.
+# Written by Scott Seago <sseago at redhat.com>,
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA  02110-1301, USA.  A copy of the GNU General Public License is
+# also available at http://www.gnu.org/copyleft/gpl.html.
+# Mid-level API: Business logic around networks
+module NetworkService
+  include ApplicationService
+
+  # Loads a list of networks for viewing
+  #
+  # === Instance variables
+  # [<tt>@networks</tt>] stores a list of all Networks
+  # === Required permissions
+  # [<tt>Privilege::MODIFY</tt>] on the default HW pool
+  def svc_list()
+    authorize
+    @networks = Network.find(:all)
+  end
+
+  # Load the Network with +id+ for viewing
+  #
+  # === Instance variables
+  # [<tt>@network</tt>] stores the Network with +id+
+  # === Required permissions
+  # [<tt>Privilege::MODIFY</tt>] on the default HW pool
+  def svc_show(id)
+    authorize(id)
+  end
+
+  # Load the Network with +id+ for editing
+  #
+  # === Instance variables
+  # [<tt>@network</tt>] stores the Network with +id+
+  # === Required permissions
+  # [<tt>Privilege::MODIFY</tt>] on default HW pool
+  def svc_modify(id)
+    authorize(id)
+  end
+
+  # update attributes for the Network with +id+
+  #
+  # === Instance variables
+  # [<tt>@network</tt>] stores the Network with +id+
+  # === Required permissions
+  # [<tt>Privilege::MODIFY</tt>] on default HW pool
+  def svc_update(id, network_hash)
+    authorize(id)
+    @network.usages.delete_all
+    @network.update_attributes!(network_hash)
+    return "Network was successfully updated."
+  end
+
+  # Load a new Network for creating
+  #
+  # === Instance variables
+  # [<tt>@network</tt>] loads a new Network object into memory
+  # === Required permissions
+  # [<tt>Privilege::MODIFY</tt>] on default HW pool
+  def svc_new()
+    authorize
+  end
+
+  # Save a new Network
+  #
+  # === Instance variables
+  # [<tt>@network</tt>] the newly-created Network
+  # === Required permissions
+  # [<tt>Privilege::MODIFY</tt>] on default HW pool
+  def svc_create(network_hash)
+    authorize
+    @network = Network.factory(network_hash)
+    @network.save!
+    return "Network was successfully created."
+  end
+
+  # Destroys the Network with +id+
+  #
+  # === Instance variables
+  # [<tt>@network</tt>] stores the network with +id+
+  # === Required permissions
+  # [<tt>Privilege::MODIFY</tt>] on default HW pool
+  def svc_destroy(id)
+    authorize(id)
+    unless @network.is_destroyable?
+      raise ActionError.new("Network has existing bondings or NICs")
+    end
+    @network.destroy
+    return "Network was successfully deleted."
+  end
+
+  # Load the IP addresses for object of type +parent_type+ and +id+
+  #
+  # === Instance variables
+  # [<tt>@parent_type</tt>] +parent_type+
+  # [<tt>@ip_addresses</tt>] IP addresses for selected object
+  # [<tt>@network</tt>] network with +id+ if <tt>@parent_type</tt> is network
+  # [<tt>@nic</tt>] nic with +id+ if <tt>@parent_type</tt> is nic
+  # [<tt>@bonding</tt>] bonding with +id+ if <tt>@parent_type</tt> is bonding
+  # === Required permissions
+  # [<tt>Privilege::MODIFY</tt>] on the default HW pool
+  def svc_ip_addresses(parent_type, id)
+    authorize
+    @parent_type = parent_type
+    if @parent_type == 'network'
+      @network = Network.find(id)
+      @ip_addresses = @network.ip_addresses
+    elsif @parent_type == 'nic'
+      @nic = Nic.find(id)
+      @ip_addresses = @nic.ip_addresses
+    elsif @parent_type == 'bonding' and id
+      @bonding = Bonding.find(id)
+      @ip_addresses = @bonding.ip_addresses
+    else
+      @ip_addresses = []
+    end
+  end
+
+  # create new IP address
+  #
+  # === Instance variables
+  # [<tt>@ip_address</tt>] create new IP address
+  # === Required permissions
+  # [<tt>Privilege::MODIFY</tt>] on the default HW pool
+  def svc_create_ip_address(ip_hash)
+    authorize
+    @ip_address = IpAddress.factory(ip_hash)
+    @ip_address.save!
+    return "Ip Address was successfully created."
+  end
+
+  # Load IP address +id+ for editing
+  #
+  # === Instance variables
+  # [<tt>@ip_address</tt>] IP Address with +id+
+  # [<tt>@network</tt>] network for <tt>@ip_address</tt> if it exists
+  # [<tt>@nic</tt>] nic for <tt>@ip_address</tt> if it exists
+  # [<tt>@bonding</tt>] bonding for <tt>@ip_address</tt> if it exists
+  # === Required permissions
+  # [<tt>Privilege::MODIFY</tt>] on the default HW pool
+  def svc_modify_ip_address(parent_type, id)
+    authorize
+    @ip_address = IpAddress.find(id)
+    @parent_type = parent_type
+    @network = @ip_address.network if @ip_address.network_id
+    @nic = @ip_address.nic if @ip_address.nic_id
+    @bonding = @ip_address.bonding if @ip_address.bonding_id
+  end
+
+  # Update IP address +id+
+  #
+  # === Instance variables
+  # [<tt>@ip_address</tt>] IP Address with +id+
+  # === Required permissions
+  # [<tt>Privilege::MODIFY</tt>] on the default HW pool
+  def svc_update_ip_address(id, ip_hash)
+    authorize
+    @ip_address = IpAddress.find(id)
+    # special case if we are switching types
+    # FIXME: this doesn't work if all attributes aren't specified
+    # We should probably not support changing type here but instead require
+    # deletion and re-creation -- either that or don't use inheritence for
+    # IP address type
+    if @ip_address.type != ip_hash[:type]
+      @ip_address = IpAddress.factory(ip_hash)
+      @ip_address.save!
+      IpAddress.delete(id)
+    else
+      @ip_address.update_attributes!(ip_hash)
+    end
+    return "IpAddress was successfully updated."
+  end
+
+  # Destroys the IP Address with +id+
+  #
+  # === Instance variables
+  # [<tt>@ip_address</tt>] stores the IP Address with +id+
+  # === Required permissions
+  # [<tt>Privilege::MODIFY</tt>] on default HW pool
+  def svc_destroy_ip_address(id)
+    authorize
+    IpAddress.destroy(id)
+    return "IP Address was successfully deleted."
+  end
+
+  # Load NIC +id+ for editing
+  #
+  # === Instance variables
+  # [<tt>@nic</tt>] NIC with +id+
+  # [<tt>@network</tt>] network for <tt>@nic</tt>
+  # [<tt>@networks</tt>] available networks for <tt>@nic</tt>
+  # === Required permissions
+  # [<tt>Privilege::MODIFY</tt>] on the default HW pool
+  def svc_modify_nic(id)
+    authorize
+    @nic = Nic.find(id)
+    @network = @nic.physical_network
+    network_options
+    # filter out networks already assigned to nics on host
+    network_conditions = []
+    @nic.host.nics.each { |nic|
+      unless nic.physical_network.nil? || nic.id == @nic.id
+        network_conditions.push(" id != " + nic.physical_network.id.to_s)
+      end
+    }
+    network_conditions = network_conditions.join(" AND ")
+    @networks = PhysicalNetwork.find(:all, :conditions => network_conditions)
+  end
+
+  # Update NIC +id+
+  #
+  # === Instance variables
+  # [<tt>@nic</tt>] NIC with +id+
+  # [<tt>@network</tt>] network for <tt>@nic</tt>
+  # === Required permissions
+  # [<tt>Privilege::MODIFY</tt>] on the default HW pool
+  def svc_update_nic(id, nic_hash, ip_hash)
+    authorize
+    network_options
+    unless nic_hash[:physical_network_id].to_i == 0
+      @network = Network.find(nic_hash[:physical_network_id])
+      if @network.boot_type.id == @static_boot_type.id
+        if ip_hash[:id] == "New"
+          svc_create_ip_address(ip_hash)
+        elsif ip_hash[:id] != ""
+          svc_update_ip_address(ip_hash[:id], ip_hash)
+        end
+      end
+    end
+    @nic = Nic.find(id)
+    @nic.update_attributes!(nic_hash)
+    return "Nic was successfully updated."
+  end
+
+  # load new bonding for creation
+  #
+  # === Instance variables
+  # [<tt>@host</tt>] Host with +host_id+
+  # [<tt>@nics</tt>] available nics on <tt>@host</tt>
+  # [<tt>@networks</tt>] available networks
+  # === Required permissions
+  # [<tt>Privilege::MODIFY</tt>] on the default HW pool
+  def svc_new_bonding(host_id)
+    authorize
+    network_options
+    @host = Host.find(host_id)
+    # FIXME when bonding_nics table is removed, and
+    # bondings_id column added to nics table, simplify
+    # (select where bonding.nil?)
+    @nics = []
+    @host.nics.each{ |nic| @nics.push(nic) if nic.bondings.empty? }
+    # filter out networks already assigned to bondings on host
+    network_conditions = []
+    @host.bondings.each { |bonding|
+       unless bonding.vlan.nil?
+         network_conditions.push(" id != " + bonding.vlan.id.to_s)
+       end
+    }
+    network_conditions = network_conditions.join(" AND ")
+    @networks = Vlan.find(:all, :conditions => network_conditions)
+  end
+
+  # create new bonding
+  #
+  # === Instance variables
+  # [<tt>@bonding</tt>] newly created bonding
+  # [<tt>@network</tt>] network for newly created bonding (if vlan specified)
+  # [<tt>@ip_address</tt>] ip address for newly created bonding (if vlan
+  #                        and static boot type specified)
+  # [<tt>@host</tt>] Host with +host_id+
+  # === Required permissions
+  # [<tt>Privilege::MODIFY</tt>] on the default HW pool
+  def svc_create_bonding(bonding_hash, ip_hash)
+    pre_create_or_update_bonding(bonding_hash, ip_hash)
+    @bonding = Bonding.new(bonding_hash)
+    @bonding.ip_addresses << @ip_address if @ip_address
+    @bonding.save!
+    if @ip_address
+      @ip_address.bonding_id = @bonding.id
+      @ip_address.save!
+    end
+    return "Bonding was successfully created."
+  end
+
+  # Load Bonding +id+ for editing
+  #
+  # === Instance variables
+  # [<tt>@bonding</tt>] bonding with +id+
+  # [<tt>@host</tt>] host for <tt>@bonding</tt>
+  # [<tt>@network</tt>] network for <tt>@bonding</tt>
+  # [<tt>@networks</tt>] available networks
+  # [<tt>@nics</tt>] available nics
+  # === Required permissions
+  # [<tt>Privilege::MODIFY</tt>] on the default HW pool
+  def svc_modify_bonding(id)
+    authorize
+    @bonding = Bonding.find(id)
+    @network = @bonding.vlan
+    @host = @bonding.host
+
+    # FIXME when bonding_nics table is removed, and
+    # bondings_id column added to nics table, simplify
+    # (select where bonding.nil? or bonding has nic)
+    @nics = []
+    @host.nics.each{ |nic|
+      if nic.bondings.empty? ||
+          nic.bondings[0].id == @bonding.id
+        @nics.push(nic)
+      end
+    }
+
+    # filter out networks already assigned to bondings on host
+    network_conditions = []
+    @host.bondings.each { |bonding|
+      unless bonding.vlan.nil? || bonding.id == @bonding.id
+        network_conditions.push(" id != " + bonding.vlan.id.to_s)
+      end
+    }
+    network_conditions = network_conditions.join(" AND ")
+
+    @networks = Vlan.find(:all, :conditions => network_conditions)
+    network_options
+  end
+
+  # Update Bonding +id+
+  #
+  # === Instance variables
+  # [<tt>@bonding</tt>] bonding with +id+
+  # [<tt>@network</tt>] network for <tt>@bonding</tt>
+  # [<tt>@ip_address</tt>] ip address for newly created bonding (if vlan
+  #                        and static boot type specified)
+  # === Required permissions
+  # [<tt>Privilege::MODIFY</tt>] on the default HW pool
+  def svc_update_bonding(id, bonding_hash, ip_hash)
+    pre_create_or_update_bonding(bonding_hash, ip_hash)
+    @bonding = Bonding.find(id)
+    @bonding.nics.delete_all
+    @bonding.update_attributes!(bonding_hash)
+    return "Bonding was successfully updated."
+  end
+
+  # Destroys the Bonding with +id+
+  #
+  # === Instance variables
+  # [<tt>@bonding</tt>] stores the Bonding with +id+
+  # === Required permissions
+  # [<tt>Privilege::MODIFY</tt>] on default HW pool
+  def svc_destroy_bonding(id)
+    authorize
+    Bonding.destroy(id)
+    return "Bonding was successfully deleted."
+  end
+
+  private
+  # for now we only check for deafult pool admin auth
+  def authorize(id=nil)
+    authorized!(Privilege::MODIFY,HardwarePool.get_default_pool)
+    @network = Network.find(id) if id
+  end
+  def network_options
+    @bonding_types = BondingType.find(:all)
+    @static_boot_type = BootType.find(:first,
+                                      :conditions => { :proto => 'static' })
+  end
+  def pre_create_or_update_bonding(bonding_hash, ip_hash)
+    authorize
+    network_options
+    unless bonding_hash[:vlan_id].to_i == 0
+      @network = Network.find(bonding_hash[:vlan_id])
+      if @network.boot_type.id == @static_boot_type.id
+        if ip_hash[:id] == "New"
+          svc_create_ip_address(ip_hash)
+        elsif ip_hash[:id] != ""
+          svc_update_ip_address(ip_hash[:id], ip_hash)
+        end
+      end
+    end
+  end
+end
-- 
1.6.0.6




More information about the ovirt-devel mailing list