Class: Fog::Compute::Ovirt::V4::Real
- Inherits:
-
Object
- Object
- Fog::Compute::Ovirt::V4::Real
- Extended by:
- Shared
- Includes:
- Shared
- Defined in:
- lib/fog/ovirt/compute/v4.rb,
lib/fog/ovirt/requests/compute/v4/create_vm.rb,
lib/fog/ovirt/requests/compute/v4/get_quota.rb,
lib/fog/ovirt/requests/compute/v4/update_vm.rb,
lib/fog/ovirt/requests/compute/v4/vm_action.rb,
lib/fog/ovirt/requests/compute/v4/vm_ticket.rb,
lib/fog/ovirt/requests/compute/v4/add_volume.rb,
lib/fog/ovirt/requests/compute/v4/destroy_vm.rb,
lib/fog/ovirt/requests/compute/v4/datacenters.rb,
lib/fog/ovirt/requests/compute/v4/get_cluster.rb,
lib/fog/ovirt/requests/compute/v4/list_quotas.rb,
lib/fog/ovirt/requests/compute/v4/get_template.rb,
lib/fog/ovirt/requests/compute/v4/list_volumes.rb,
lib/fog/ovirt/requests/compute/v4/add_interface.rb,
lib/fog/ovirt/requests/compute/v4/list_clusters.rb,
lib/fog/ovirt/requests/compute/v4/list_networks.rb,
lib/fog/ovirt/requests/compute/v4/update_volume.rb,
lib/fog/ovirt/requests/compute/v4/destroy_volume.rb,
lib/fog/ovirt/requests/compute/v4/list_templates.rb,
lib/fog/ovirt/requests/compute/v4/get_api_version.rb,
lib/fog/ovirt/requests/compute/v4/list_vm_volumes.rb,
lib/fog/ovirt/requests/compute/v4/storage_domains.rb,
lib/fog/ovirt/requests/compute/v4/update_interface.rb,
lib/fog/ovirt/requests/compute/v4/destroy_interface.rb,
lib/fog/ovirt/requests/compute/v4/get_instance_type.rb,
lib/fog/ovirt/requests/compute/v4/list_vm_interfaces.rb,
lib/fog/ovirt/requests/compute/v4/get_virtual_machine.rb,
lib/fog/ovirt/requests/compute/v4/list_instance_types.rb,
lib/fog/ovirt/requests/compute/v4/list_template_volumes.rb,
lib/fog/ovirt/requests/compute/v4/list_virtual_machines.rb,
lib/fog/ovirt/requests/compute/v4/list_operating_systems.rb,
lib/fog/ovirt/requests/compute/v4/vm_start_with_cloudinit.rb,
lib/fog/ovirt/requests/compute/v4/list_template_interfaces.rb
Instance Method Summary collapse
-
#add_interface(id, options = {}) ⇒ Object
rubocop:disable Metrics/AbcSize.
-
#add_options_defaults(options) ⇒ Object
rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity.
- #add_volume(id, options = {}) ⇒ Object
-
#api_version ⇒ Object
rubocop:enable Metrics/AbcSize.
- #blank_template ⇒ Object
- #check_for_option(opts, name) ⇒ Object
-
#create_vm(attrs) ⇒ Object
rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity.
- #datacenter ⇒ Object
- #datacenter_hash ⇒ Object
- #datacenters(filter = {}) ⇒ Object
- #destroy_interface(id, options) ⇒ Object
- #destroy_vm(options = {}) ⇒ Object
- #destroy_volume(id, options) ⇒ Object
- #get_cluster(id) ⇒ Object
- #get_instance_type(id) ⇒ Object
- #get_quota(id) ⇒ Object
- #get_template(id) ⇒ Object
- #get_virtual_machine(id) ⇒ Object
-
#initialize(options = {}) ⇒ Real
constructor
rubocop:disable Metrics/AbcSize.
- #list_clusters(filters = {}) ⇒ Object
- #list_instance_types(filters = {}) ⇒ Object
- #list_networks(cluster_id) ⇒ Object
- #list_operating_systems ⇒ Object
- #list_quotas(filters = {}) ⇒ Object
- #list_template_interfaces(vm_id) ⇒ Object
- #list_template_volumes(template_id) ⇒ Object
- #list_templates(filters = {}) ⇒ Object
- #list_virtual_machines(filters = {}) ⇒ Object
- #list_vm_interfaces(vm_id) ⇒ Object
- #list_vm_volumes(vm_id) ⇒ Object
- #list_volumes ⇒ Object
-
#process_vm_opts(opts) ⇒ Object
rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity.
- #storage_domains(filter = {}) ⇒ Object
- #update_interface(id, options) ⇒ Object
-
#update_vm(attrs) ⇒ Object
rubocop:disable Metrics/AbcSize.
- #update_volume(id, options) ⇒ Object
- #vm_action(options = {}) ⇒ Object
- #vm_start_with_cloudinit(options = {}) ⇒ Object
- #vm_ticket(id, options = {}) ⇒ Object
-
#wrap_attribute(attrs, attribute, klass) ⇒ Object
rubocop:enable Metrics/AbcSize.
Methods included from Shared
check_arguments, get_attr_value, ovirt_attrs
Constructor Details
#initialize(options = {}) ⇒ Real
rubocop:disable Metrics/AbcSize
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 |
# File 'lib/fog/ovirt/compute/v4.rb', line 137 def initialize( = {}) require "ovirtsdk4" username = [:ovirt_username] password = [:ovirt_password] server = [:ovirt_server] port = [:ovirt_port] || 8080 api_path = [:ovirt_api_path] || "/api" url = [:ovirt_url] || "https://#{server}:#{port}#{api_path}" connection_opts = { :url => url, :username => username, :password => password } @datacenter = [:ovirt_datacenter] connection_opts[:ca_file] = [:ca_file] connection_opts[:ca_certs] = [OpenSSL::X509::Certificate.new([:public_key])] if [:public_key].present? @client = ExceptionWrapper.new(OvirtSDK4::Connection.new(connection_opts)) end |
Instance Method Details
#add_interface(id, options = {}) ⇒ Object
rubocop:disable Metrics/AbcSize
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
# File 'lib/fog/ovirt/requests/compute/v4/add_interface.rb', line 7 def add_interface(id, = {}) raise ArgumentError, "instance id is a required parameter" unless id vm = client.system_service.vms_service.vm_service(id) nics_service = vm.nics_service = .dup if [:network].present? network = client.system_service.networks_service.network_service([:network]).get profiles = client.follow_link(network.vnic_profiles) profile = profiles.detect { |x| x.name == network.name } profile ||= profiles.min_by(&:name) .delete(:network) [:vnic_profile] = { :id => profile.id } end interface = OvirtSDK4::Nic.new() nics_service.add(interface) end |
#add_options_defaults(options) ⇒ Object
rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
# File 'lib/fog/ovirt/requests/compute/v4/add_volume.rb', line 17 def () = .dup search = [:search] || format("datacenter=%<datacenter>s", :datacenter => datacenter) [:bootable] ||= "true" [:interface] ||= OvirtSDK4::DiskInterface::VIRTIO [:provisioned_size] = [:size_gb].to_i * Fog::Compute::Ovirt::DISK_SIZE_TO_GB if [:size_gb] [:storage_domain_id] = [:storage_domain] || storagedomains(:role => "data", :search => search).first.id # If no size is given, default to a volume size of 8GB [:provisioned_size] ||= 8 * Fog::Compute::Ovirt::DISK_SIZE_TO_GB [:type] ||= OvirtSDK4::DiskType::DATA [:format] ||= OvirtSDK4::DiskFormat::COW [:sparse] = true unless [:sparse].present? [:quota] = [:quota].present? ? client.system_service.data_centers_service.data_center_service(datacenter).quotas_service.quota_service([:quota]).get : nil [:disk] ||= {} [:disk][:storage_domains] ||= [client.system_service.storage_domains_service.storage_domain_service([:storage_domain_id]).get] [:disk][:provisioned_size] ||= .delete(:provisioned_size) [:disk][:type] ||= .delete(:type) [:disk][:format] ||= .delete(:format) [:disk][:sparse] = .delete(:sparse) unless [:disk][:sparse].present? end |
#add_volume(id, options = {}) ⇒ Object
6 7 8 9 10 11 12 13 14 |
# File 'lib/fog/ovirt/requests/compute/v4/add_volume.rb', line 6 def add_volume(id, = {}) raise ArgumentError, "instance id is a required parameter" unless id = () = client.system_service.vms_service.vm_service(id). disk = OvirtSDK4::DiskAttachment.new() .add(disk) end |
#api_version ⇒ Object
rubocop:enable Metrics/AbcSize
160 161 162 163 |
# File 'lib/fog/ovirt/compute/v4.rb', line 160 def api_version api = client.system_service.get api.product_info.version.full_version end |
#blank_template ⇒ Object
173 174 175 |
# File 'lib/fog/ovirt/compute/v4.rb', line 173 def blank_template @blank_template ||= client.system_service.get.special_objects.blank_template end |
#check_for_option(opts, name) ⇒ Object
6 7 8 |
# File 'lib/fog/ovirt/requests/compute/v4/create_vm.rb', line 6 def check_for_option(opts, name) opts[name.to_sym] || opts[(name + "_name").to_sym] end |
#create_vm(attrs) ⇒ Object
rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
# File 'lib/fog/ovirt/requests/compute/v4/create_vm.rb', line 28 def create_vm(attrs) attrs = attrs.dup if attrs[:cluster].present? attrs[:cluster] = client.system_service.clusters_service.cluster_service(attrs[:cluster]).get else if attrs[:cluster_name].present? cluster = client.system_service.clusters_service.list(:search => "name=#{attrs[:cluster_name]}").first else cluster = client.system_service.clusters_service.list(:search => "datacenter=#{datacenter_hash[:name]}").first attrs[:cluster_name] = cluster.name end attrs[:cluster] = cluster end vms_service = client.system_service.vms_service attrs[:instance_type] = attrs[:instance_type].present? ? client.system_service.instance_types_service.instance_type_service(attrs[:instance_type]).get : nil attrs[:template] = if attrs[:template].present? client.system_service.templates_service.template_service(attrs[:template]).get else client.system_service.get.special_objects.blank_template end attrs[:comment] ||= "" attrs[:quota] = attrs[:quota].present? ? client.system_service.data_centers_service.data_center_service(datacenter).quotas_service.quota_service(attrs[:quota]).get : nil if attrs[:cores].present? || attrs[:sockets].present? cpu_topology = OvirtSDK4::CpuTopology.new(:cores => attrs.fetch(:cores, "1"), :sockets => attrs.fetch(:sockets, "1")) attrs[:cpu] = OvirtSDK4::Cpu.new(:topology => cpu_topology) end attrs[:memory_policy] = OvirtSDK4::MemoryPolicy.new(:guaranteed => attrs[:memory]) if attrs[:memory].to_i < Fog::Compute::Ovirt::DISK_SIZE_TO_GB # TODO: handle cloning from template process_vm_opts(attrs) new_vm = OvirtSDK4::Vm.new(attrs) vms_service.add(new_vm) end |
#datacenter ⇒ Object
165 166 167 |
# File 'lib/fog/ovirt/compute/v4.rb', line 165 def datacenter @datacenter ||= datacenter_hash[:id] end |
#datacenter_hash ⇒ Object
169 170 171 |
# File 'lib/fog/ovirt/compute/v4.rb', line 169 def datacenter_hash @datacenter_hash ||= datacenters.first end |
#datacenters(filter = {}) ⇒ Object
6 7 8 |
# File 'lib/fog/ovirt/requests/compute/v4/datacenters.rb', line 6 def datacenters(filter = {}) client.system_service.data_centers_service.list(filter).map { |ovirt_obj| ovirt_attrs ovirt_obj } end |
#destroy_interface(id, options) ⇒ Object
6 7 8 9 10 11 |
# File 'lib/fog/ovirt/requests/compute/v4/destroy_interface.rb', line 6 def destroy_interface(id, ) raise ArgumentError, "instance id is a required parameter" unless id raise ArgumentError, "interface id is a required parameter for destroy-interface" unless .key? :id vm = client.system_service.vms_service.vm_service(id) vm.nics_service.nic_service([:id]).remove end |
#destroy_vm(options = {}) ⇒ Object
6 7 8 9 10 11 |
# File 'lib/fog/ovirt/requests/compute/v4/destroy_vm.rb', line 6 def destroy_vm( = {}) raise ArgumentError, "instance id is a required parameter" unless .key? :id client.system_service.vms_service.vm_service([:id]).remove true end |
#destroy_volume(id, options) ⇒ Object
6 7 8 9 10 11 12 |
# File 'lib/fog/ovirt/requests/compute/v4/destroy_volume.rb', line 6 def destroy_volume(id, ) raise ArgumentError, "instance id is a required parameter" unless id raise ArgumentError, "volume id is a required parameter for destroy-volume" unless .key? :id disks_service = client.system_service.disks_service disks_service.disk_service([:id]).remove end |
#get_cluster(id) ⇒ Object
6 7 8 |
# File 'lib/fog/ovirt/requests/compute/v4/get_cluster.rb', line 6 def get_cluster(id) ovirt_attrs client.system_service.clusters_service.cluster_service(id).get end |
#get_instance_type(id) ⇒ Object
6 7 8 |
# File 'lib/fog/ovirt/requests/compute/v4/get_instance_type.rb', line 6 def get_instance_type(id) ovirt_attrs client.system_service.instance_types_service.instance_type_service(id).get end |
#get_quota(id) ⇒ Object
6 7 8 9 |
# File 'lib/fog/ovirt/requests/compute/v4/get_quota.rb', line 6 def get_quota(id) quota = client.system_service.data_centers_service.data_center_service(datacenter).quotas_service.quota_service(id).get ovirt_attrs quota end |
#get_template(id) ⇒ Object
6 7 8 |
# File 'lib/fog/ovirt/requests/compute/v4/get_template.rb', line 6 def get_template(id) ovirt_attrs client.system_service.templates_service.template_service(id).get end |
#get_virtual_machine(id) ⇒ Object
6 7 8 |
# File 'lib/fog/ovirt/requests/compute/v4/get_virtual_machine.rb', line 6 def get_virtual_machine(id) ovirt_attrs client.system_service.vms_service.vm_service(id).get end |
#list_clusters(filters = {}) ⇒ Object
6 7 8 |
# File 'lib/fog/ovirt/requests/compute/v4/list_clusters.rb', line 6 def list_clusters(filters = {}) client.system_service.clusters_service.list(filters).map { |ovirt_obj| ovirt_attrs ovirt_obj } end |
#list_instance_types(filters = {}) ⇒ Object
6 7 8 |
# File 'lib/fog/ovirt/requests/compute/v4/list_instance_types.rb', line 6 def list_instance_types(filters = {}) client.system_service.instance_types_service.list(filters).map { |ovirt_obj| ovirt_attrs ovirt_obj } end |
#list_networks(cluster_id) ⇒ Object
6 7 8 |
# File 'lib/fog/ovirt/requests/compute/v4/list_networks.rb', line 6 def list_networks(cluster_id) client.system_service.clusters_service.cluster_service(cluster_id).networks_service.list end |
#list_operating_systems ⇒ Object
6 7 8 |
# File 'lib/fog/ovirt/requests/compute/v4/list_operating_systems.rb', line 6 def client.system_service..list.map { |ovirt_obj| ovirt_attrs ovirt_obj } end |
#list_quotas(filters = {}) ⇒ Object
6 7 8 9 |
# File 'lib/fog/ovirt/requests/compute/v4/list_quotas.rb', line 6 def list_quotas(filters = {}) data_center = client.system_service.data_centers_service.data_center_service(datacenter) data_center.quotas_service.list(filters).map { |ovirt_obj| ovirt_attrs ovirt_obj } end |
#list_template_interfaces(vm_id) ⇒ Object
6 7 8 |
# File 'lib/fog/ovirt/requests/compute/v4/list_template_interfaces.rb', line 6 def list_template_interfaces(vm_id) client.system_service.templates_service.template_service(vm_id).nics_service.list.map { |ovirt_obj| ovirt_attrs ovirt_obj } end |
#list_template_volumes(template_id) ⇒ Object
6 7 8 9 10 11 12 13 14 |
# File 'lib/fog/ovirt/requests/compute/v4/list_template_volumes.rb', line 6 def list_template_volumes(template_id) template = client.system_service.templates_service.template_service(template_id).get = client.follow_link(template.) .map do || ovirt_attrs client.follow_link(.disk) end end |
#list_templates(filters = {}) ⇒ Object
6 7 8 |
# File 'lib/fog/ovirt/requests/compute/v4/list_templates.rb', line 6 def list_templates(filters = {}) client.system_service.templates_service.list(filters).map { |ovirt_obj| ovirt_attrs ovirt_obj } end |
#list_virtual_machines(filters = {}) ⇒ Object
6 7 8 9 10 11 12 13 14 15 |
# File 'lib/fog/ovirt/requests/compute/v4/list_virtual_machines.rb', line 6 def list_virtual_machines(filters = {}) filters = filters.dup page = filters.delete(:page) without_details = filters.delete(:without_details) filters[:all_content] = true unless without_details filters[:search] ||= "" filters[:search] += " page #{page}" client.system_service.vms_service.list(filters).map { |ovirt_obj| ovirt_attrs ovirt_obj } end |
#list_vm_interfaces(vm_id) ⇒ Object
6 7 8 |
# File 'lib/fog/ovirt/requests/compute/v4/list_vm_interfaces.rb', line 6 def list_vm_interfaces(vm_id) client.system_service.vms_service.vm_service(vm_id).nics_service.list.map { |ovirt_obj| ovirt_attrs ovirt_obj } end |
#list_vm_volumes(vm_id) ⇒ Object
6 7 8 9 10 11 12 13 14 15 16 17 |
# File 'lib/fog/ovirt/requests/compute/v4/list_vm_volumes.rb', line 6 def list_vm_volumes(vm_id) # disk_attachments_service = client.system_service.vms_service.vm_service(vm_id).disk_attachments_service # disk_attachments_service.list.map {|ovirt_obj| ovirt_attrs client.system_service.disks_service.disk_service(ovirt_obj.id).get} vm = client.system_service.vms_service.vm_service(vm_id).get = client.follow_link(vm.) .map do || ovirt_attrs client.follow_link(.disk) end end |
#list_volumes ⇒ Object
6 7 8 |
# File 'lib/fog/ovirt/requests/compute/v4/list_volumes.rb', line 6 def list_volumes client.system_service.disks_service.list.map { |ovirt_obj| ovirt_attrs ovirt_obj } end |
#process_vm_opts(opts) ⇒ Object
rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
# File 'lib/fog/ovirt/requests/compute/v4/create_vm.rb', line 11 def process_vm_opts(opts) return unless check_for_option(opts, "template") && check_for_option(opts, "storagedomain") template_id = opts[:template] || client.system_service.templates_service.search(:name => opts[:template_name]).first.id template_disks = client.system_service.templates_service.template_service(template_id).get. storagedomain_id = opts[:storagedomain] || storagedomains.select { |s| s.name == opts[:storagedomain_name] }.first.id # Make sure the 'clone' option is set if any of the disks defined by # the template is stored on a different storage domain than requested opts[:clone] = true unless opts[:clone] == true || template_disks.empty? || template_disks.all? { |d| d.storage_domain == storagedomain_id } # Create disks map opts[:disks] = template_disks.collect { |d| { :id => d.id, :storagedomain => storagedomain_id } } end |
#storage_domains(filter = {}) ⇒ Object
6 7 8 9 10 11 12 13 |
# File 'lib/fog/ovirt/requests/compute/v4/storage_domains.rb', line 6 def storage_domains(filter = {}) filter = filter.dup role_filter = filter.delete(:role) client.system_service.storage_domains_service.list(filter).collect do |sd| # Filter by role is not supported by the search language. The work around is to list all, then filter. role_filter.nil? || sd.type == role_filter ? sd : nil end.compact end |
#update_interface(id, options) ⇒ Object
15 16 17 18 19 20 21 |
# File 'lib/fog/ovirt/requests/compute/v4/update_interface.rb', line 15 def update_interface(id, ) check_arguments(id, ) interface_id = [:id] nic = client.system_service.vms_service.vm_service(id).nics_service.nic_service(interface_id) nic.update(nic, ) end |
#update_vm(attrs) ⇒ Object
rubocop:disable Metrics/AbcSize
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
# File 'lib/fog/ovirt/requests/compute/v4/update_vm.rb', line 7 def update_vm(attrs) attrs = attrs.dup vm_service = client.system_service.vms_service.vm_service(attrs[:id]) if attrs[:cores].present? cpu_topology = OvirtSDK4::CpuTopology.new(:cores => attrs[:cores], :sockets => "1") attrs[:cpu] = OvirtSDK4::Cpu.new(:topology => cpu_topology) end wrap_attribute(attrs, :cluster, OvirtSDK4::Cluster) attrs[:template] = if attrs[:template].present? OvirtSDK4::Template.new(:id => attrs[:template]) else blank_template end wrap_attribute(attrs, :large_icon, OvirtSDK4::Icon) wrap_attribute(attrs, :small_icon, OvirtSDK4::Icon) wrap_attribute(attrs, :cpu_profile, OvirtSDK4::CpuProfile) wrap_attribute(attrs, :host, OvirtSDK4::Host) wrap_attribute(attrs, :quota, OvirtSDK4::Quota) wrap_attribute(attrs, :instance_type, OvirtSDK4::InstanceType) attrs[:high_availability] = OvirtSDK4::HighAvailability.new(:enabled => attrs[:ha]) unless attrs[:ha].nil? attrs[:original_template] = if attrs[:original_template].present? OvirtSDK4::Template.new(:id => attrs[:original_template]) else blank_template end vm_service.update(attrs) end |
#update_volume(id, options) ⇒ Object
15 16 17 18 19 20 21 22 |
# File 'lib/fog/ovirt/requests/compute/v4/update_volume.rb', line 15 def update_volume(id, ) check_arguments(id, ) disk_id = [:id] = client.system_service.vms_service.vm_service(id)..(disk_id) .update(, ) true # If we come here, expect success and return true end |
#vm_action(options = {}) ⇒ Object
6 7 8 9 10 11 12 13 |
# File 'lib/fog/ovirt/requests/compute/v4/vm_action.rb', line 6 def vm_action( = {}) raise ArgumentError, "instance id is a required parameter" unless .key? :id raise ArgumentError, "action is a required parameter" unless .key? :action vm_service = client.system_service.vms_service.vm_service([:id]) vm_service.public_send([:action]) vm_service.get.status end |
#vm_start_with_cloudinit(options = {}) ⇒ Object
6 7 8 9 10 11 |
# File 'lib/fog/ovirt/requests/compute/v4/vm_start_with_cloudinit.rb', line 6 def vm_start_with_cloudinit( = {}) raise ArgumentError, "instance id is a required parameter" unless .key? :id vm_service = client.system_service.vms_service.vm_service([:id]) vm_service.start(:use_cloud_init => true, :vm => { :initialization => [:user_data] }) end |
#vm_ticket(id, options = {}) ⇒ Object
6 7 8 |
# File 'lib/fog/ovirt/requests/compute/v4/vm_ticket.rb', line 6 def vm_ticket(id, = {}) client.system_service.vms_service.vm_service(id).ticket() end |
#wrap_attribute(attrs, attribute, klass) ⇒ Object
rubocop:enable Metrics/AbcSize
38 39 40 41 42 43 44 |
# File 'lib/fog/ovirt/requests/compute/v4/update_vm.rb', line 38 def wrap_attribute(attrs, attribute, klass) if attrs[attribute].present? attrs[attribute] = klass.new(:id => attrs[attribute]) else attrs.delete(attribute) end end |