Closed wzymaster closed 9 years ago
The value returned by
SoftLayer::ProductPackage.virtual_server_package(@client)
is not a service object, but a Ruby object in the Model Layer (http://softlayer.github.io/softlayer-ruby/doc/Model%20Layer_md.html) representing the Package (http://softlayer.github.io/softlayer-ruby/doc/SoftLayer/ProductPackage.html)
As such it responds to a limited set of methods itself. Some of the information you are requesting is available from that object using the "configuration()" method and the features of the SoftLayer::ProductItemCategory class (http://softlayer.github.io/softlayer-ruby/doc/SoftLayer/ProductItemCategory.html).
However if you simply wish to translate your code so that it calls through to the network API, ask the ProductPackage object for it's "service":
available_disks = package.service.getAvailableStorageUnits
all_categories = package.service.object_mask("itemCategory","isRequired").getConfiguration
item_prices = package.service.object_mask("id", "item.description", "categories.id", "isRequired").getItemPrices
thanks for the quick response, however I still get error for object mask like below :
2.0.0-p481 :006 > all_categories = pkg.service.object_mask("itemCategory","isRequired").getConfiguration SoftLayer::ObjectMaskParserError: Object Mask must begin with a 'mask' or 'filterMask' root property
Oh... sorry. Object masks must now be formatted using the "Extended Object Mask" format (http://sldn.softlayer.com/article/Object-Masks)
In this case, your mask should be object_mask("mask[itemCategory, isRequired]")
The mask on item_prices will have to be adjusted similarly.
thanks for your quick reply. Yes, it works for me now after using the new mask format, however, I got error like below for item_prices :
2.0.0-p481 :009 > item_prices = pkg.service.object_mask("mask[id, item.description, categories.id, isRequired]").getItemPrices XMLRPC::FaultException: Property 'isRequired' not valid for 'SoftLayer_Product_Item_Price'.
I am wondering if 'isRequired' property is removed from new API ?
The low-level networking API (the one you get to by talking to services directly) has not changed. Version 2 (and later) of the softlayer_api gem builds high-level classes on top of the existing network API.
One of those changes is the use of "extended" object masks instead of the old-style object masks. Looking in SLDN, a "SoftLayer_Product_Item_Price" has never had the 'isRequired' property. However, the extended object masks are more strict about validating properties. Asking for that property in that mask has always been invalid... but it was not checked in the past.
It might be interesting to see what you are doing with the item prices you are getting back from the API with these calls. It seems like you're doing a lot of the same work that some of the high level classes could be doing for you.
Yeah, what I am doing here is to retrieve all required category and associated item prices and build a local cache of packages.
Do you have any samples of high level classes to help me achieve that goal instead of using the low-level API calls ?
Have you tried looking at the bare metal package ordering example:
https://github.com/softlayer/softlayer-ruby/blob/master/examples/order_bare_metal_package.rb
It is concerned with ordering a bare metal server, but it uses the high-level package classes to do some of the work.
Here's another example:
require 'softlayer_api'
require 'pp'
SoftLayer::Client.default_client = SoftLayer::Client.new()
package = SoftLayer::ProductPackage.virtual_server_package()
required_categories = package.configuration()
required_categories.each { |category|
puts "#{category.name}"
category.configuration_options.each { |item|
puts "\t#{item.description}"
}
}
(Note that I have a ".softlayer" configuration file in my home directory so I don't have to provide separate credentials when creating a client)
thanks very much. I am wondering if low level functions are supported in the enhanced SoftLayer API gem ?
like , verify order with one or multiple disk RAIDs ? Any example for that ?
Oh sure. You can still get at all the low level stuff. You don't need to use the high-level interfaces at all if you don't want to.
If you want to use your original code you could get the SoftLayer_Product_Package service using:
@client = # code you have above for creating the client
@softlayer_product_package = @client[:Product_Package] # note that specifying "SoftLayer_" is not required
At that point I think the rest of your code would be unchanged... except needing to translate your object masks to extended format.
At the same time, if you want to use the high level interfaces (SoftLayer::VirtualServerOrder for example) there are ways to plug into the ordering system (verify and place_order! accept blocks that can modify the order templates) so you could add things like RAID systems to the orders without having the directly supported by the order objects.
according to your suggested sample, it isn't an object ? @softlayer_product_package = @client[:Product_Package]
2.0.0-p481 :010 > softlayer_product_package.getItemPrices XMLRPC::FaultException: Object does not exist to execute method on. (SoftLayer_Product_Package::getItemPrices)
Sorry. I shouldn't type code into the browser without trying it "for real". Here's your original code translated using the low-level API functionality:
require 'softlayer_api'
client = SoftLayer::Client.new(
# username: @sl_user_name
# api_key: @sl_api_key
)
softlayer_product_package = client[:Product_Package]
package = softlayer_product_package.object_with_id 46
available_disks = package.getAvailableStorageUnits
all_categories = package.object_mask("mask[itemCategory,isRequired]").getConfiguration
item_prices = package.object_mask("mask[id,item.description,categories.id]").getItemPrices
puts available_disks
puts all_categories.inspect
puts item_prices.inspect
thanks for your quick response. In my understanding , @client[:Product_Package] is kind of initialization for softlayer_product_pakcage service , which is equal to the below ?
SoftLayer::Service.new("SoftLayer_Product_Package", username: @sl_user_name, api_key: @sl_api_key)
The similar rule is applied to other services , like SoftLayer_Product_Order, SoftLayer_Account, SoftLayer_Security_Ssh_Key , SoftLayer_Virtual_Guest, SoftLayer_Hardware ?
Yes. Any service can (and should) be created through the client. You may use brackets as shown, or you can call the "servicenamed" method. You can provide strings or symbols and adding "SoftLayer" on the front is optional.
It seems that you're back on track so I'm going to close this issue. Please feel free to get back if you have further trouble.
thanks very much !
@SLsthompson when will you guys release 3.0 ? very soon ?
We have some folks that are looking at the 3.0 release to make sure there are no problems. If you'd like to try it yourself you should be able to do 'gem install softlayer_api -v "3.0.b2" --pre' (or you can grab the v.3.0 branch and "rake gem; gem install pkg/softlayer_api-3.0.b2.gem")
Once the internal review is done we'll look at doing a full-blown release. Should be next week, I hope.
I was using 1.0.8 gem for my rails app, however I found that API calls are breaking after upgrade from 1.0.8 to 2.2.0 gem.
My existing codes look like below :
@softlayer_product_package = SoftLayer::Service.new("SoftLayer_Product_Package",
In order to accommodate 2.2.0, I have updated codes to
@client |= SoftLayer::Client.new( username: @sl_user_name, # enter your username here api_key: @sl_api_key # enter your api key here ) package = SoftLayer::ProductPackage.virtual_server_package(@client) available_disks = package.getAvailableStorageUnits all_categories = package.object_mask("itemCategory","isRequired").getConfiguration item_prices = package.object_mask("id", "item.description", "categories.id", "isRequired").getItemPrices
but I got errors like below :
NoMethodError: undefined method `getAvailableStorageUnits' for #SoftLayer::ProductPackage:0x007fe4d497fdb8
NoMethodError: undefined method `object_mask' for #SoftLayer::ProductPackage:0x007fe4d4b77e40
Can you provide some examples on how I can upgrade my rails app to accommodate 2.2.0 here ?