Skip to content

Commit 82ea82b

Browse files
committed
Merge pull request #168 from opdemand/develop
Merge develop into master for 0.0.7 release
2 parents 5f28a25 + fe0283e commit 82ea82b

15 files changed

Lines changed: 488 additions & 80 deletions

File tree

Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
# -*- coding: utf-8 -*-
2+
import datetime
3+
from south.db import db
4+
from south.v2 import SchemaMigration
5+
from django.db import models
6+
7+
8+
class Migration(SchemaMigration):
9+
10+
def forwards(self, orm):
11+
# Adding unique constraint on 'Key', fields ['public']
12+
db.create_unique(u'api_key', ['public'])
13+
14+
15+
def backwards(self, orm):
16+
# Removing unique constraint on 'Key', fields ['public']
17+
db.delete_unique(u'api_key', ['public'])
18+
19+
20+
models = {
21+
u'api.build': {
22+
'Meta': {'ordering': "[u'-created']", 'unique_together': "((u'formation', u'uuid'),)", 'object_name': 'Build'},
23+
'checksum': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
24+
'config': ('api.fields.EnvVarsField', [], {'default': "u'null'", 'blank': 'True'}),
25+
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
26+
'dockerfile': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
27+
'formation': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['api.Formation']"}),
28+
'output': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
29+
'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"}),
30+
'procfile': ('api.fields.ProcfileField', [], {'default': "u'null'", 'blank': 'True'}),
31+
'sha': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
32+
'size': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
33+
'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
34+
'url': ('django.db.models.fields.URLField', [], {'max_length': '200'}),
35+
'uuid': ('api.fields.UuidField', [], {'unique': 'True', 'max_length': '32', 'primary_key': 'True'})
36+
},
37+
u'api.config': {
38+
'Meta': {'ordering': "[u'-created']", 'unique_together': "((u'formation', u'version'),)", 'object_name': 'Config'},
39+
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
40+
'formation': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['api.Formation']"}),
41+
'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"}),
42+
'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
43+
'uuid': ('api.fields.UuidField', [], {'unique': 'True', 'max_length': '32', 'primary_key': 'True'}),
44+
'values': ('api.fields.EnvVarsField', [], {'default': "u'{}'", 'blank': 'True'}),
45+
'version': ('django.db.models.fields.PositiveIntegerField', [], {})
46+
},
47+
u'api.container': {
48+
'Meta': {'ordering': "[u'created']", 'unique_together': "((u'formation', u'type', u'num'),)", 'object_name': 'Container'},
49+
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
50+
'formation': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['api.Formation']"}),
51+
'node': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['api.Node']"}),
52+
'num': ('django.db.models.fields.PositiveIntegerField', [], {}),
53+
'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"}),
54+
'status': ('django.db.models.fields.CharField', [], {'default': "u'up'", 'max_length': '64'}),
55+
'type': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
56+
'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
57+
'uuid': ('api.fields.UuidField', [], {'unique': 'True', 'max_length': '32', 'primary_key': 'True'})
58+
},
59+
u'api.flavor': {
60+
'Meta': {'unique_together': "((u'owner', u'id'),)", 'object_name': 'Flavor'},
61+
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
62+
'id': ('django.db.models.fields.SlugField', [], {'max_length': '64'}),
63+
'init': ('api.fields.CloudInitField', [], {}),
64+
'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"}),
65+
'params': ('api.fields.ParamsField', [], {'default': "u'null'"}),
66+
'provider': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['api.Provider']"}),
67+
'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
68+
'uuid': ('api.fields.UuidField', [], {'unique': 'True', 'max_length': '32', 'primary_key': 'True'})
69+
},
70+
u'api.formation': {
71+
'Meta': {'unique_together': "((u'owner', u'id'),)", 'object_name': 'Formation'},
72+
'containers': ('json_field.fields.JSONField', [], {'default': "u'{}'", 'blank': 'True'}),
73+
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
74+
'id': ('django.db.models.fields.SlugField', [], {'max_length': '64'}),
75+
'layers': ('json_field.fields.JSONField', [], {'default': "u'{}'", 'blank': 'True'}),
76+
'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"}),
77+
'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
78+
'uuid': ('api.fields.UuidField', [], {'unique': 'True', 'max_length': '32', 'primary_key': 'True'})
79+
},
80+
u'api.key': {
81+
'Meta': {'unique_together': "((u'owner', u'id'),)", 'object_name': 'Key'},
82+
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
83+
'id': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
84+
'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"}),
85+
'public': ('django.db.models.fields.TextField', [], {'unique': 'True'}),
86+
'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
87+
'uuid': ('api.fields.UuidField', [], {'unique': 'True', 'max_length': '32', 'primary_key': 'True'})
88+
},
89+
u'api.layer': {
90+
'Meta': {'unique_together': "((u'formation', u'id'),)", 'object_name': 'Layer'},
91+
'chef_version': ('django.db.models.fields.CharField', [], {'default': "u'11.4.4'", 'max_length': '32'}),
92+
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
93+
'environment': ('django.db.models.fields.CharField', [], {'default': "u'_default'", 'max_length': '64'}),
94+
'flavor': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['api.Flavor']"}),
95+
'formation': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['api.Formation']"}),
96+
'id': ('django.db.models.fields.SlugField', [], {'max_length': '64'}),
97+
'initial_attributes': ('json_field.fields.JSONField', [], {'default': "u'{}'", 'blank': 'True'}),
98+
'level': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
99+
'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"}),
100+
'run_list': ('django.db.models.fields.CharField', [], {'max_length': '512'}),
101+
'ssh_private_key': ('django.db.models.fields.TextField', [], {}),
102+
'ssh_public_key': ('django.db.models.fields.TextField', [], {}),
103+
'ssh_username': ('django.db.models.fields.CharField', [], {'default': "u'ubuntu'", 'max_length': '64'}),
104+
'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
105+
'uuid': ('api.fields.UuidField', [], {'unique': 'True', 'max_length': '32', 'primary_key': 'True'})
106+
},
107+
u'api.node': {
108+
'Meta': {'unique_together': "((u'formation', u'id'),)", 'object_name': 'Node'},
109+
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
110+
'formation': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['api.Formation']"}),
111+
'fqdn': ('django.db.models.fields.CharField', [], {'max_length': '256', 'null': 'True', 'blank': 'True'}),
112+
'id': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
113+
'layer': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['api.Layer']"}),
114+
'num': ('django.db.models.fields.PositiveIntegerField', [], {}),
115+
'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"}),
116+
'provider_id': ('django.db.models.fields.SlugField', [], {'max_length': '64', 'null': 'True', 'blank': 'True'}),
117+
'status': ('api.fields.NodeStatusField', [], {'default': "u'null'", 'null': 'True', 'blank': 'True'}),
118+
'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
119+
'uuid': ('api.fields.UuidField', [], {'unique': 'True', 'max_length': '32', 'primary_key': 'True'})
120+
},
121+
u'api.provider': {
122+
'Meta': {'unique_together': "((u'owner', u'id'),)", 'object_name': 'Provider'},
123+
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
124+
'creds': ('api.fields.CredentialsField', [], {'default': "u'null'", 'blank': 'True'}),
125+
'id': ('django.db.models.fields.SlugField', [], {'max_length': '64'}),
126+
'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"}),
127+
'type': ('django.db.models.fields.SlugField', [], {'max_length': '16'}),
128+
'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
129+
'uuid': ('api.fields.UuidField', [], {'unique': 'True', 'max_length': '32', 'primary_key': 'True'})
130+
},
131+
u'api.release': {
132+
'Meta': {'ordering': "[u'-created']", 'unique_together': "((u'formation', u'version'),)", 'object_name': 'Release'},
133+
'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['api.Build']", 'null': 'True', 'blank': 'True'}),
134+
'config': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['api.Config']"}),
135+
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
136+
'formation': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['api.Formation']"}),
137+
'image': ('django.db.models.fields.CharField', [], {'default': "u'deis/buildstep'", 'max_length': '256'}),
138+
'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"}),
139+
'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
140+
'uuid': ('api.fields.UuidField', [], {'unique': 'True', 'max_length': '32', 'primary_key': 'True'}),
141+
'version': ('django.db.models.fields.PositiveIntegerField', [], {})
142+
},
143+
u'auth.group': {
144+
'Meta': {'object_name': 'Group'},
145+
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
146+
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
147+
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
148+
},
149+
u'auth.permission': {
150+
'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
151+
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
152+
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
153+
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
154+
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
155+
},
156+
u'auth.user': {
157+
'Meta': {'object_name': 'User'},
158+
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
159+
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
160+
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
161+
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
162+
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
163+
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
164+
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
165+
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
166+
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
167+
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
168+
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
169+
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
170+
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
171+
},
172+
u'contenttypes.contenttype': {
173+
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
174+
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
175+
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
176+
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
177+
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
178+
}
179+
}
180+
181+
complete_apps = ['api']

api/models.py

Lines changed: 48 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ class Key(UuidAuditedModel):
7171

7272
owner = models.ForeignKey(settings.AUTH_USER_MODEL)
7373
id = models.CharField(max_length=128)
74-
public = models.TextField()
74+
public = models.TextField(unique=True)
7575

7676
class Meta:
7777
verbose_name = 'SSH Key'
@@ -124,7 +124,8 @@ def __str__(self):
124124
class FlavorManager(models.Manager):
125125
"""Manage database interactions for :class:`Flavor`."""
126126

127-
def load_cloud_config_base(self):
127+
@staticmethod
128+
def load_cloud_config_base():
128129
"""Read the base configuration file and return YAML data."""
129130
# load cloud-config-base yaml_
130131
_cloud_config_path = os.path.abspath(
@@ -137,30 +138,38 @@ def seed(self, user, **kwargs):
137138
"""Seed the database with default Flavors for each cloud region."""
138139
# TODO: add optimized AMIs to default flavors
139140
flavors = (
140-
{'id': 'ec2-us-east-1',
141-
'provider': 'ec2',
142-
'params': json.dumps({'region': 'us-east-1'})},
143-
{'id': 'ec2-us-west-1',
144-
'provider': 'ec2',
145-
'params': json.dumps({'region': 'us-west-1'})},
146-
{'id': 'ec2-us-west-2',
147-
'provider': 'ec2',
148-
'params': json.dumps({'region': 'us-west-2'})},
149-
{'id': 'ec2-eu-west-1',
150-
'provider': 'ec2',
151-
'params': json.dumps({'region': 'eu-west-1'})},
152-
{'id': 'ec2-ap-northeast-1',
153-
'provider': 'ec2',
154-
'params': json.dumps({'region': 'ap-northeast-1'})},
155-
{'id': 'ec2-ap-southeast-1',
156-
'provider': 'ec2',
157-
'params': json.dumps({'region': 'ap-southeast-1'})},
158-
{'id': 'ec2-ap-southeast-2',
159-
'provider': 'ec2',
160-
'params': json.dumps({'region': 'ap-southeast-2'})},
161-
{'id': 'ec2-sa-east-1',
162-
'provider': 'ec2',
163-
'params': json.dumps({'region': 'sa-east-1'})},
141+
{'id': 'ec2-us-east-1', 'provider': 'ec2',
142+
'params': json.dumps({
143+
'region': 'us-east-1', 'image': Flavor.IMAGE_MAP['us-east-1'],
144+
'zone': 'any', 'size': 'm1.medium'})},
145+
{'id': 'ec2-us-west-1', 'provider': 'ec2',
146+
'params': json.dumps({
147+
'region': 'us-west-1', 'image': Flavor.IMAGE_MAP['us-west-1'],
148+
'zone': 'any', 'size': 'm1.medium'})},
149+
{'id': 'ec2-us-west-2', 'provider': 'ec2',
150+
'params': json.dumps({
151+
'region': 'us-west-2', 'image': Flavor.IMAGE_MAP['us-west-2'],
152+
'zone': 'any', 'size': 'm1.medium'})},
153+
{'id': 'ec2-eu-west-1', 'provider': 'ec2',
154+
'params': json.dumps({
155+
'region': 'eu-west-1', 'image': Flavor.IMAGE_MAP['eu-west-1'],
156+
'zone': 'any', 'size': 'm1.medium'})},
157+
{'id': 'ec2-ap-northeast-1', 'provider': 'ec2',
158+
'params': json.dumps({
159+
'region': 'ap-northeast-1', 'image': Flavor.IMAGE_MAP['ap-northeast-1'],
160+
'zone': 'any', 'size': 'm1.medium'})},
161+
{'id': 'ec2-ap-southeast-1', 'provider': 'ec2',
162+
'params': json.dumps({
163+
'region': 'ap-southeast-1', 'image': Flavor.IMAGE_MAP['ap-southeast-1'],
164+
'zone': 'any', 'size': 'm1.medium'})},
165+
{'id': 'ec2-ap-southeast-2', 'provider': 'ec2',
166+
'params': json.dumps({
167+
'region': 'ap-southeast-2', 'image': Flavor.IMAGE_MAP['ap-southeast-2'],
168+
'zone': 'any', 'size': 'm1.medium'})},
169+
{'id': 'ec2-sa-east-1', 'provider': 'ec2',
170+
'params': json.dumps({
171+
'region': 'sa-east-1', 'image': Flavor.IMAGE_MAP['sa-east-1'],
172+
'zone': 'any', 'size': 'm1.medium'})},
164173
)
165174
cloud_config = self.load_cloud_config_base()
166175
for flavor in flavors:
@@ -184,6 +193,19 @@ class Flavor(UuidAuditedModel):
184193
params = fields.ParamsField()
185194
init = fields.CloudInitField()
186195

196+
# Deis-optimized EC2 amis -- with 3.8 kernel, chef 11 deps,
197+
# and large docker images (e.g. buildstep) pre-installed
198+
IMAGE_MAP = {
199+
'ap-northeast-1': 'ami-6da8356c',
200+
'ap-southeast-1': 'ami-a66f24f4',
201+
'ap-southeast-2': 'ami-d5f66bef',
202+
'eu-west-1': 'ami-acbf5adb',
203+
'sa-east-1': 'ami-f9fd5ae4',
204+
'us-east-1': 'ami-69f3bc00',
205+
'us-west-1': 'ami-f0695cb5',
206+
'us-west-2': 'ami-ea1e82da',
207+
}
208+
187209
class Meta:
188210
unique_together = (('owner', 'id'),)
189211

0 commit comments

Comments
 (0)