Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Oracle support in Cloud Controller #44

Merged
merged 13 commits into from May 16, 2013
Merged
2 changes: 1 addition & 1 deletion .ruby-version
@@ -1 +1 @@
1.9.3
1.9.3-p392
16 changes: 9 additions & 7 deletions Gemfile.lock
Expand Up @@ -18,10 +18,10 @@ GIT

GIT
remote: https://github.com/cloudfoundry/vcap-common.git
revision: 89680342db9e6993123d8925dbd0fa3905d4739c
revision: 129ef520424a81155c097b7a79aa13bb8b736fd7
specs:
vcap_common (2.0.10)
em-http-request (~> 1.0.0.beta3, < 1.0.0.beta4)
em-http-request (~> 1.0)
eventmachine
httpclient
membrane (~> 0.0.2)
Expand All @@ -45,13 +45,14 @@ GEM
activesupport (3.2.8)
i18n (~> 0.6)
multi_json (~> 1.0)
addressable (2.3.3)
addressable (2.3.4)
backports (2.6.1)
bcrypt-ruby (3.0.1)
builder (3.0.0)
ci_reporter (1.7.0)
builder (>= 2.1.2)
columnize (0.3.6)
cookiejar (0.3.0)
crack (0.3.1)
daemons (1.1.9)
debugger (1.5.0)
Expand All @@ -61,11 +62,12 @@ GEM
debugger-linecache (1.2.0)
debugger-ruby_core_source (1.2.0)
diff-lcs (1.1.3)
em-http-request (1.0.0.beta.3)
em-http-request (1.0.3)
addressable (>= 2.2.3)
cookiejar
em-socksify
eventmachine
http_parser.rb (>= 0.5.1)
eventmachine (>= 1.0.0.beta.4)
http_parser.rb (>= 0.5.3)
em-socksify (0.2.1)
eventmachine (>= 1.0.0.beta.4)
eventmachine (1.0.3)
Expand Down Expand Up @@ -103,7 +105,7 @@ GEM
listen (0.5.3)
machinist (1.0.6)
membrane (0.0.2)
mime-types (1.22)
mime-types (1.23)
multi_json (1.3.6)
multi_xml (0.5.1)
multipart-post (1.2.0)
Expand Down
2 changes: 2 additions & 0 deletions README.md
Expand Up @@ -118,3 +118,5 @@ However, if querying for `empty` Oracle will not match `null`.
- Oracle doesn't provide an auto increment PK type. To compensate for this Sequel will automatically
create a sequence and a trigger to update the PK with the latest sequence value. This works great.
However, when renaming a table you will need to rename the sequence and re-make the trigger for that table.
- Count query limitation. For some reason Oracle-Sequel doesn't support filter parameters in count(). So, queries
like `Models::Organization.count(:id => org.id)` need to change to `Models::Organization.filter(:id => org.id).count`
18 changes: 15 additions & 3 deletions config/cloud_controller.yml
Expand Up @@ -5,11 +5,15 @@ pid_filename: /tmp/cloud_controller.pid
nats_uri: nats://127.0.0.1:4222

external_domain: api2.vcap.me
system_domains:
- vcap.me

bootstrap_admin_email: sre@vmware.com

system_domain_organization: the-system_domain-org-name
system_domain: vcap.me
app_domains:
- customer-app-domain1.com
- customer-app-domain2.com

info:
name: "vcap"
build: "2222"
Expand Down Expand Up @@ -61,6 +65,11 @@ quota_definitions:
non_basic_services_allowed: true
total_services: 500
memory_limit: 204800 # 200 GB
trial:
non_basic_services_allowed: false
total_services: 2
memory_limit: 512 # 0.5 GB
trial_db_allowed: true

default_quota_definition: free

Expand All @@ -82,4 +91,7 @@ droplets:
provider: Local
local_root: /tmp

db_encryption_key: "asdfasdfasdf"
db_encryption_key: "asdfasdfasdf"

trial_db:
guid: "78ad16cf-3c22-4427-a982-b9d35d746914"
3 changes: 1 addition & 2 deletions config/nginx.conf
Expand Up @@ -80,8 +80,7 @@ http {
upload_cleanup 400-505;
}

# Droplet uploads from the stager should be authenticated
location ~ /staging/(buildpack_cache|droplets)/ {
location ~ /staging/(buildpack_cache|droplets)/.*/upload/ {
# Pass along auth header
set $auth_header $upstream_http_x_auth;
proxy_set_header Authorization $auth_header;
Expand Down
@@ -0,0 +1,7 @@
Sequel.migration do
change do
alter_table :quota_definitions do
rename_column :free_rds, :trial_db_allowed
end
end
end
@@ -0,0 +1,7 @@
Sequel.migration do
change do
alter_table :service_instances do
add_column :dashboard_url, String
end
end
end
2 changes: 1 addition & 1 deletion lib/cloud_controller/api/quota_definition.rb
Expand Up @@ -12,7 +12,7 @@ module VCAP::CloudController
attribute :non_basic_services_allowed, Message::Boolean
attribute :total_services, Integer
attribute :memory_limit, Integer
attribute :free_rds, Message::Boolean, :default => false
attribute :trial_db_allowed, Message::Boolean, :default => false
end

query_parameters :name
Expand Down
6 changes: 4 additions & 2 deletions lib/cloud_controller/api/service_instance.rb
Expand Up @@ -15,6 +15,7 @@ module VCAP::CloudController
to_one :space
to_one :service_plan
to_many :service_bindings
attribute :dashboard_url, String, exclude_in: [:create, :update]
end

query_parameters :name, :space_guid, :service_plan_guid, :service_binding_guid
Expand All @@ -27,12 +28,13 @@ def before_create

def self.translate_validation_exception(e, attributes)
space_and_name_errors = e.errors.on([:space_id, :name])
quota_errors = e.errors.on(:space)
quota_errors = e.errors.on(:org)
service_plan_errors = e.errors.on(:service_plan)
if space_and_name_errors && space_and_name_errors.include?(:unique)
Errors::ServiceInstanceNameTaken.new(attributes["name"])
elsif quota_errors
if quota_errors.include?(:free_quota_exceeded)
if quota_errors.include?(:free_quota_exceeded) ||
quota_errors.include?(:trial_quota_exceeded)
Errors::ServiceInstanceFreeQuotaExceeded.new
elsif quota_errors.include?(:paid_quota_exceeded)
Errors::ServiceInstancePaidQuotaExceeded.new
Expand Down
21 changes: 10 additions & 11 deletions lib/cloud_controller/api/staging.rb
Expand Up @@ -60,7 +60,7 @@ def buildpack_cache_upload_uri(guid)

def droplet_download_uri(guid)
if local?
staging_uri("#{DROPLET_PATH}/#{guid}")
staging_uri("#{DROPLET_PATH}/#{guid}/download")
else
droplet_uri(guid)
end
Expand Down Expand Up @@ -116,7 +116,7 @@ def local?

def buildpack_cache_download_uri(guid)
if AppPackage.local?
staging_uri("#{BUILDPACK_CACHE_PATH}/#{guid}")
staging_uri("#{BUILDPACK_CACHE_PATH}/#{guid}/download")
else
package_uri(guid, :buildpack_cache)
end
Expand Down Expand Up @@ -155,11 +155,8 @@ def store_package(guid, path, type)
end

def upload_uri(guid, type)
if type == :buildpack_cache
staging_uri("#{BUILDPACK_CACHE_PATH}/#{guid}")
else
staging_uri("#{DROPLET_PATH}/#{guid}")
end
prefix = type == :buildpack_cache ? BUILDPACK_CACHE_PATH : DROPLET_PATH
staging_uri("#{prefix}/#{guid}/upload")
end

def package_uri(guid, type)
Expand Down Expand Up @@ -371,10 +368,12 @@ def tmpdir
end

get "/staging/apps/:guid", :download_app
post "#{DROPLET_PATH}/:guid", :upload_droplet
get "#{DROPLET_PATH}/:guid", :download_droplet

post "#{BUILDPACK_CACHE_PATH}/:guid", :upload_buildpack_cache
get "#{BUILDPACK_CACHE_PATH}/:guid", :download_buildpack_cache
# Make sure that nginx upload path rules do not apply to download paths!
post "#{DROPLET_PATH}/:guid/upload", :upload_droplet
get "#{DROPLET_PATH}/:guid/download", :download_droplet

post "#{BUILDPACK_CACHE_PATH}/:guid/upload", :upload_buildpack_cache
get "#{BUILDPACK_CACHE_PATH}/:guid/download", :download_buildpack_cache
end
end
11 changes: 9 additions & 2 deletions lib/cloud_controller/config.rb
Expand Up @@ -17,7 +17,9 @@ class VCAP::CloudController::Config < VCAP::Config
:description => String,
},

:system_domains => [ String ],
:system_domain => String,
:system_domain_organization => enum(String, NilClass),
:app_domains => [ String ],

optional(:allow_debug) => bool,

Expand Down Expand Up @@ -123,7 +125,11 @@ class VCAP::CloudController::Config < VCAP::Config
}
},

:db_encryption_key => String
:db_encryption_key => String,

optional(:trial_db) => {
:guid => String,
},
}
end

Expand Down Expand Up @@ -154,6 +160,7 @@ def self.configure(config)

VCAP::CloudController::Models::QuotaDefinition.configure(config)
VCAP::CloudController::Models::Stack.configure(config[:stacks_file])
VCAP::CloudController::Models::ServicePlan.configure(config[:trial_db])
end

class << self
Expand Down
20 changes: 17 additions & 3 deletions lib/cloud_controller/models/domain.rb
Expand Up @@ -129,10 +129,10 @@ def self.default_serving_domain

def self.default_serving_domain_name=(name)
@default_serving_domain_name = name
unless name
@default_serving_domain = nil
else
if name
@default_serving_domain = find_or_create_shared_domain(name)
else
@default_serving_domain = nil
end
name
end
Expand All @@ -158,5 +158,19 @@ def self.find_or_create_shared_domain(name)

return d
end

def self.populate_from_config(config, organization)
config[:app_domains].each do |domain|
find_or_create_shared_domain(domain)
end

unless config[:app_domains].include?(config[:system_domain])
find_or_create(
:name => config[:system_domain],
:wildcard => true,
:owning_organization => organization
)
end
end
end
end
43 changes: 39 additions & 4 deletions lib/cloud_controller/models/organization.rb
Expand Up @@ -119,17 +119,52 @@ def service_instance_quota_remaining?
service_instances.count < quota_definition.total_services
end

def service_plan_quota_remaining?(service_plan)
if service_plan && service_plan.trial_rds?
return quota_definition.free_rds && !spaces.collect(&:service_instances).flatten.collect(&:service_plan).collect(&:unique_id).include?("aws_rds_mysql_10mb")
def check_quota?(service_plan)
return check_quota_for_trial_db if service_plan.trial_db?
check_quota_without_trial_db(service_plan)
end

def check_quota_for_trial_db
if trial_db_allowed?
return {:type => :org, :name => :trial_quota_exceeded} if trial_db_allocated?
elsif paid_services_allowed?
return {:type => :org, :name => :paid_quota_exceeded} unless service_instance_quota_remaining?
else
return {:type => :service_plan, :name => :paid_services_not_allowed }
end
false

{}
end

def check_quota_without_trial_db(service_plan)
if paid_services_allowed?
return {:type => :org, :name => :paid_quota_exceeded } unless service_instance_quota_remaining?
elsif service_plan.free
return {:type => :org, :name => :free_quota_exceeded } unless service_instance_quota_remaining?
else
return {:type => :service_plan, :name => :paid_services_not_allowed }
end

{}
end

def paid_services_allowed?
quota_definition.non_basic_services_allowed
end

def trial_db_allowed?
quota_definition.trial_db_allowed
end

# Does any service instance in any space have a trial DB plan?
def trial_db_allocated?
service_instances.each do |svc_instance|
return true if svc_instance.service_plan.trial_db?
end

false
end

def memory_remaining
memory_used = apps_dataset.sum(:memory * :instances) || 0
quota_definition.memory_limit - memory_used
Expand Down
15 changes: 3 additions & 12 deletions lib/cloud_controller/models/quota_definition.rb
Expand Up @@ -8,11 +8,10 @@ class QuotaDefinition < Sequel::Model
add_association_dependencies :organizations => :destroy

export_attributes :name, :non_basic_services_allowed, :total_services,
:memory_limit, :free_rds
:memory_limit, :trial_db_allowed
import_attributes :name, :non_basic_services_allowed, :total_services,
:memory_limit, :free_rds

ci_attributes :name
:memory_limit, :trial_db_allowed
ci_attributes :name

def validate
validates_presence :name
Expand All @@ -22,14 +21,6 @@ def validate
validates_presence :memory_limit
end

def self.populate_from_config(config)
config[:quota_definitions].each do |k, v|
QuotaDefinition.update_or_create(:name => k.to_s) do |r|
r.update_from_hash(v)
end
end
end

def self.configure(config)
@default_quota_name = config[:default_quota_definition]
end
Expand Down