networks = []
vn_pool.each do |vn|
- id = vn.id
- title = vn.name
- network = Network.new(id: id, title: title)
- networks << network.to_hash
+ begin
+ network = parse_network(vn)
+ networks << network.to_hash
+ rescue NowError => e
+ logger.warn "[code #{e.code}] #{e.message}, skipping"
+ end
end
return networks
vn = OpenNebula::VirtualNetwork.new(vn_generic, @ctx)
check(vn.info)
- id = vn.id
- title = vn.name
- logger.debug "OpenNebula get(#{network_id}) ==> #{id}, #{title}"
- network = Network.new(id: id, title: title)
+ network = parse_network(vn)
return network.to_hash
end
raise NowError.new(code), return_code.message
end
+ def parse_range(vn_id, ar)
+ id = ar['AR_ID']
+ type = ar['TYPE']
+ size = ar['SIZE']
+ case type
+ when 'IP4'
+ ip = ar['IP']
+ addr_size = 32
+ if ip.nil? || ip.empty?
+ raise NowError.new(422), "Missing 'IP' in the address range #{id} of network #{vn_id}"
+ end
+ when 'IP6', 'IP4_6'
+ ip = ar['GLOBAL_PREFIX'] || ar['ULA_PREFIX']
+ addr_size = 128
+ if ip.nil? || ip.empty?
+ raise NowError.new(422), "Missing 'GLOBAL_PREFIX' in the address range #{id} of network #{vn_id}"
+ end
+ else
+ raise NowError.new(501), "Unknown type '#{type}' in the address range #{id} of network #{vn_id}"
+ end
+ if size.nil? || size.empty?
+ raise NowError.new(422), "Missing 'SIZE' in the address range #{id} of network #{vn_id}"
+ end
+ size = size.to_i
+ mask = addr_size - Math.log(size, 2).ceil
+ logger.debug "[parse_range] id=#{id}, address=#{ip}/#{mask} (size #{size})"
+
+ return Now::Range.new(address: "#{ip}/#{mask}", allocation: 'dynamic')
+ end
+
+ def parse_ranges(vn_id, vn)
+ range = nil
+ vn.each('AR_POOL/AR') do |ar|
+ if !range.nil?
+ raise NowError.new(501), "Multiple address ranges found in network #{vn_id}"
+ end
+ range = parse_range(vn_id, ar)
+ end
+ return range
+ end
+
+ def parse_cluster(vn_id, vn)
+ cluster = nil
+ vn.each('CLUSTERS/ID') do |cluster_xml|
+ id = cluster_xml.text
+ logger.debug "[parse_cluster] cluster: #{id}"
+ if !cluster.nil?
+ raise NowError.new(501), "Multiple clusters assigned to network #{vn_id}"
+ end
+ cluster = id
+ end
+ return cluster
+ end
+
+ def parse_network(vn)
+ logger.debug "[parse_network] #{vn.to_hash}"
+
+ id = vn.id
+ title = vn.name
+ desc = vn['SUMMARY']
+ if desc.nil? || desc.empty?
+ desc = nil
+ end
+ vlan = vn['VLAN_ID']
+ if vlan.nil? || vlan.empty?
+ vlan = nil
+ end
+
+ range = parse_ranges(id, vn)
+ zone = parse_cluster(id, vn)
+ network = Network.new(
+ id: id,
+ title: title,
+ description: desc,
+ user: vn['UNAME'],
+ bridge: vn['BRIDGE'],
+ vlan: vlan,
+ range: range,
+ zone: zone,
+ )
+
+ return network
+ end
+
end
end
require 'date'
module Now
-
+ # Network object
class Network
+ # OpenNebula ID
attr_accessor :id
+ # Network title
attr_accessor :title
+ # Network summary
+ attr_accessor :description
+
+ # Owner
attr_accessor :user
+ # VLAN ID
+ attr_accessor :vlan
+
+ attr_accessor :range
+
+ # Network state (active, inactive, error)
+ attr_accessor :state
+
+ # Availability zone (cluster)
+ attr_accessor :zone
+
# Attribute mapping from ruby-style variable name to JSON key.
def self.attribute_map
{
:'id' => :'id',
:'title' => :'title',
- :'user' => :'user'
+ :'description' => :'description',
+ :'user' => :'user',
+ :'vlan' => :'vlan',
+ :'range' => :'range',
+ :'state' => :'state',
+ :'zone' => :'zone'
}
end
{
:'id' => :'Integer',
:'title' => :'String',
- :'user' => :'String'
+ :'description' => :'String',
+ :'user' => :'String',
+ :'vlan' => :'Integer',
+ :'range' => :'Range',
+ :'state' => :'String',
+ :'zone' => :'String'
}
end
self.title = attributes[:'title']
end
+ if attributes.has_key?(:'description')
+ self.description = attributes[:'description']
+ end
+
if attributes.has_key?(:'user')
self.user = attributes[:'user']
end
+ if attributes.has_key?(:'vlan')
+ self.vlan = attributes[:'vlan']
+ end
+
+ if attributes.has_key?(:'range')
+ self.range = attributes[:'range']
+ end
+
+ if attributes.has_key?(:'state')
+ self.state = attributes[:'state']
+ end
+
+ if attributes.has_key?(:'zone')
+ self.zone = attributes[:'zone']
+ end
+
end
# Show invalid properties with the reasons. Usually used together with valid?
self.class == o.class &&
id == o.id &&
title == o.title &&
- user == o.user
+ description == o.description &&
+ user == o.user &&
+ vlan == o.vlan &&
+ range == o.range &&
+ state == o.state &&
+ zone == o.zone
end
# @see the `==` method
# Calculates hash code according to all attributes.
# @return [Fixnum] Hash code
def hash
- [id, title, user].hash
+ [id, title, description, user, vlan, range, state, zone].hash
end
# Builds the object from hash
--- /dev/null
+=begin
+Network Orchestrator API
+
+OpenAPI spec version: 0.0.0
+
+Partially generated by: https://github.com/swagger-api/swagger-codegen.git
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+=end
+
+require 'date'
+
+module Now
+ # Address range
+ class Range
+ # Address range (CIDR notation)
+ attr_accessor :address
+
+ # Address allocation type (static, dynamic)
+ attr_accessor :allocation
+
+
+ # Attribute mapping from ruby-style variable name to JSON key.
+ def self.attribute_map
+ {
+ :'address' => :'address',
+ :'allocation' => :'allocation'
+ }
+ end
+
+ # Attribute type mapping.
+ def self.swagger_types
+ {
+ :'address' => :'String',
+ :'allocation' => :'String'
+ }
+ end
+
+ # Initializes the object
+ # @param [Hash] attributes Model attributes in the form of hash
+ def initialize(attributes = {})
+ return unless attributes.is_a?(Hash)
+
+ # convert string to symbol for hash key
+ attributes = attributes.each_with_object({}){|(k,v), h| h[k.to_sym] = v}
+
+ if attributes.has_key?(:'address')
+ self.address = attributes[:'address']
+ end
+
+ if attributes.has_key?(:'allocation')
+ self.allocation = attributes[:'allocation']
+ end
+
+ end
+
+ # Show invalid properties with the reasons. Usually used together with valid?
+ # @return Array for valid properies with the reasons
+ def list_invalid_properties
+ invalid_properties = Array.new
+ return invalid_properties
+ end
+
+ # Check to see if the all the properties in the model are valid
+ # @return true if the model is valid
+ def valid?
+ return true
+ end
+
+ # Checks equality by comparing each attribute.
+ # @param [Object] Object to be compared
+ def ==(o)
+ return true if self.equal?(o)
+ self.class == o.class &&
+ address == o.address &&
+ allocation == o.allocation
+ end
+
+ # @see the `==` method
+ # @param [Object] Object to be compared
+ def eql?(o)
+ self == o
+ end
+
+ # Calculates hash code according to all attributes.
+ # @return [Fixnum] Hash code
+ def hash
+ [address, allocation].hash
+ end
+
+ # Builds the object from hash
+ # @param [Hash] attributes Model attributes in the form of hash
+ # @return [Object] Returns the model itself
+ def build_from_hash(attributes)
+ return nil unless attributes.is_a?(Hash)
+ self.class.swagger_types.each_pair do |key, type|
+ if type =~ /^Array<(.*)>/i
+ # check to ensure the input is an array given that the the attribute
+ # is documented as an array but the input is not
+ if attributes[self.class.attribute_map[key]].is_a?(Array)
+ self.send("#{key}=", attributes[self.class.attribute_map[key]].map{ |v| _deserialize($1, v) } )
+ end
+ elsif !attributes[self.class.attribute_map[key]].nil?
+ self.send("#{key}=", _deserialize(type, attributes[self.class.attribute_map[key]]))
+ end # or else data not found in attributes(hash), not an issue as the data can be optional
+ end
+
+ self
+ end
+
+ # Deserializes the data based on type
+ # @param string type Data type
+ # @param string value Value to be deserialized
+ # @return [Object] Deserialized data
+ def _deserialize(type, value)
+ case type.to_sym
+ when :DateTime
+ DateTime.parse(value)
+ when :Date
+ Date.parse(value)
+ when :String
+ value.to_s
+ when :Integer
+ value.to_i
+ when :Float
+ value.to_f
+ when :BOOLEAN
+ if value.to_s =~ /^(true|t|yes|y|1)$/i
+ true
+ else
+ false
+ end
+ when :Object
+ # generic object (usually a Hash), return directly
+ value
+ when /\AArray<(?<inner_type>.+)>\z/
+ inner_type = Regexp.last_match[:inner_type]
+ value.map { |v| _deserialize(inner_type, v) }
+ when /\AHash<(?<k_type>.+), (?<v_type>.+)>\z/
+ k_type = Regexp.last_match[:k_type]
+ v_type = Regexp.last_match[:v_type]
+ {}.tap do |hash|
+ value.each do |k, v|
+ hash[_deserialize(k_type, k)] = _deserialize(v_type, v)
+ end
+ end
+ else # model
+ temp_model = Now.const_get(type).new
+ temp_model.build_from_hash(value)
+ end
+ end
+
+ # Returns the string representation of the object
+ # @return [String] String presentation of the object
+ def to_s
+ to_hash.to_s
+ end
+
+ # to_body is an alias to to_hash (backward compatibility)
+ # @return [Hash] Returns the object in the form of hash
+ def to_body
+ to_hash
+ end
+
+ # Returns the object in the form of hash
+ # @return [Hash] Returns the object in the form of hash
+ def to_hash
+ hash = {}
+ self.class.attribute_map.each_pair do |attr, param|
+ value = self.send(attr)
+ next if value.nil?
+ hash[param] = _to_hash(value)
+ end
+ hash
+ end
+
+ # Outputs non-array value in the form of hash
+ # For object, use to_hash. Otherwise, just return the value
+ # @param [Object] value Any valid value
+ # @return [Hash] Returns the value in the form of hash
+ def _to_hash(value)
+ if value.is_a?(Array)
+ value.compact.map{ |v| _to_hash(v) }
+ elsif value.is_a?(Hash)
+ {}.tap do |hash|
+ value.each { |k, v| hash[k] = _to_hash(v) }
+ end
+ elsif value.respond_to? :to_hash
+ value.to_hash
+ else
+ value
+ end
+ end
+
+ end
+
+end