diff --git a/src/rockstor/storageadmin/migrations/0040_auto__add_dcontainerenv__add_unique_dcontainerenv_container_key__add_f.py b/src/rockstor/storageadmin/migrations/0040_auto__add_dcontainerenv__add_unique_dcontainerenv_container_key__add_f.py new file mode 100644 index 000000000..7f4eeef23 --- /dev/null +++ b/src/rockstor/storageadmin/migrations/0040_auto__add_dcontainerenv__add_unique_dcontainerenv_container_key__add_f.py @@ -0,0 +1,565 @@ +# -*- coding: utf-8 -*- +from south.utils import datetime_utils as datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + + +class Migration(SchemaMigration): + + def forwards(self, orm): + # Adding model 'DContainerEnv' + db.create_table(u'storageadmin_dcontainerenv', ( + (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('container', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['storageadmin.DContainer'])), + ('key', self.gf('django.db.models.fields.CharField')(max_length=1024)), + ('val', self.gf('django.db.models.fields.CharField')(max_length=1024, null=True)), + ('description', self.gf('django.db.models.fields.CharField')(max_length=2048, null=True)), + ('label', self.gf('django.db.models.fields.CharField')(max_length=64, null=True)), + )) + db.send_create_signal('storageadmin', ['DContainerEnv']) + + # Adding unique constraint on 'DContainerEnv', fields ['container', 'key'] + db.create_unique(u'storageadmin_dcontainerenv', ['container_id', 'key']) + + # Adding field 'DContainer.uid' + db.add_column(u'storageadmin_dcontainer', 'uid', + self.gf('django.db.models.fields.IntegerField')(null=True), + keep_default=False) + + + def backwards(self, orm): + # Removing unique constraint on 'DContainerEnv', fields ['container', 'key'] + db.delete_unique(u'storageadmin_dcontainerenv', ['container_id', 'key']) + + # Deleting model 'DContainerEnv' + db.delete_table(u'storageadmin_dcontainerenv') + + # Deleting field 'DContainer.uid' + db.delete_column(u'storageadmin_dcontainer', 'uid') + + + models = { + u'auth.group': { + 'Meta': {'object_name': 'Group'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) + }, + u'auth.permission': { + 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + u'auth.user': { + 'Meta': {'object_name': 'User'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + u'contenttypes.contenttype': { + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + u'oauth2_provider.application': { + 'Meta': {'object_name': 'Application'}, + 'authorization_grant_type': ('django.db.models.fields.CharField', [], {'max_length': '32'}), + 'client_id': ('django.db.models.fields.CharField', [], {'default': "u'XIsUzfCj6XywVaoouJukWytqIYKRttTKUAyx0k4p'", 'unique': 'True', 'max_length': '100', 'db_index': 'True'}), + 'client_secret': ('django.db.models.fields.CharField', [], {'default': "u'PEskqf4naFRo89agOUI36xYuzf0t16n7tMolLeAsz7o51DLeXoGmWDuXJ2KjjrVr8ojLKUvjqn68zDCZgXOkVt7PpnC6LCj70uNWDIvdJcP29Q4fmIA4XhYLOsAkNFIK'", 'max_length': '255', 'db_index': 'True', 'blank': 'True'}), + 'client_type': ('django.db.models.fields.CharField', [], {'max_length': '32'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'redirect_uris': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'skip_authorization': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'oauth2_provider_application'", 'to': u"orm['auth.User']"}) + }, + 'storageadmin.advancednfsexport': { + 'Meta': {'object_name': 'AdvancedNFSExport'}, + 'export_str': ('django.db.models.fields.CharField', [], {'max_length': '4096'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + 'storageadmin.apikeys': { + 'Meta': {'object_name': 'APIKeys'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '10'}), + 'user': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '8'}) + }, + 'storageadmin.appliance': { + 'Meta': {'object_name': 'Appliance'}, + 'client_id': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True'}), + 'client_secret': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), + 'current_appliance': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'hostname': ('django.db.models.fields.CharField', [], {'default': "'Rockstor'", 'max_length': '128'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'ip': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '4096'}), + 'mgmt_port': ('django.db.models.fields.IntegerField', [], {'default': '443'}), + 'uuid': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '64'}) + }, + 'storageadmin.configbackup': { + 'Meta': {'object_name': 'ConfigBackup'}, + 'config_backup': ('django.db.models.fields.files.FileField', [], {'max_length': '100', 'null': 'True'}), + 'filename': ('django.db.models.fields.CharField', [], {'max_length': '64'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'md5sum': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), + 'size': ('django.db.models.fields.IntegerField', [], {'null': 'True'}) + }, + 'storageadmin.containeroption': { + 'Meta': {'object_name': 'ContainerOption'}, + 'container': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['storageadmin.DContainer']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '1024'}), + 'val': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'blank': 'True'}) + }, + 'storageadmin.dashboardconfig': { + 'Meta': {'object_name': 'DashboardConfig'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']", 'unique': 'True'}), + 'widgets': ('django.db.models.fields.CharField', [], {'max_length': '4096'}) + }, + 'storageadmin.dcontainer': { + 'Meta': {'object_name': 'DContainer'}, + 'dimage': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['storageadmin.DImage']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'launch_order': ('django.db.models.fields.IntegerField', [], {'default': '1'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '1024'}), + 'rockon': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['storageadmin.RockOn']"}), + 'uid': ('django.db.models.fields.IntegerField', [], {'null': 'True'}) + }, + 'storageadmin.dcontainerenv': { + 'Meta': {'unique_together': "(('container', 'key'),)", 'object_name': 'DContainerEnv'}, + 'container': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['storageadmin.DContainer']"}), + 'description': ('django.db.models.fields.CharField', [], {'max_length': '2048', 'null': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'key': ('django.db.models.fields.CharField', [], {'max_length': '1024'}), + 'label': ('django.db.models.fields.CharField', [], {'max_length': '64', 'null': 'True'}), + 'val': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True'}) + }, + 'storageadmin.dcontainerlink': { + 'Meta': {'unique_together': "(('destination', 'name'),)", 'object_name': 'DContainerLink'}, + 'destination': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'destination_container'", 'to': "orm['storageadmin.DContainer']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '64', 'null': 'True'}), + 'source': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['storageadmin.DContainer']", 'unique': 'True'}) + }, + 'storageadmin.dcustomconfig': { + 'Meta': {'unique_together': "(('rockon', 'key'),)", 'object_name': 'DCustomConfig'}, + 'description': ('django.db.models.fields.CharField', [], {'max_length': '2048', 'null': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'key': ('django.db.models.fields.CharField', [], {'max_length': '1024'}), + 'label': ('django.db.models.fields.CharField', [], {'max_length': '64', 'null': 'True'}), + 'rockon': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['storageadmin.RockOn']"}), + 'val': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True'}) + }, + 'storageadmin.dimage': { + 'Meta': {'object_name': 'DImage'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '1024'}), + 'repo': ('django.db.models.fields.CharField', [], {'max_length': '1024'}), + 'tag': ('django.db.models.fields.CharField', [], {'max_length': '1024'}) + }, + 'storageadmin.disk': { + 'Meta': {'object_name': 'Disk'}, + 'btrfs_uuid': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '64'}), + 'offline': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'parted': ('django.db.models.fields.BooleanField', [], {}), + 'pool': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['storageadmin.Pool']", 'null': 'True', 'on_delete': 'models.SET_NULL'}), + 'serial': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True'}), + 'size': ('django.db.models.fields.BigIntegerField', [], {'default': '0'}), + 'smart_available': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'smart_enabled': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'transport': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True'}), + 'vendor': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True'}) + }, + 'storageadmin.dport': { + 'Meta': {'unique_together': "(('container', 'containerp'),)", 'object_name': 'DPort'}, + 'container': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['storageadmin.DContainer']"}), + 'containerp': ('django.db.models.fields.IntegerField', [], {}), + 'description': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True'}), + 'hostp': ('django.db.models.fields.IntegerField', [], {'unique': 'True'}), + 'hostp_default': ('django.db.models.fields.IntegerField', [], {'null': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'label': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True'}), + 'protocol': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), + 'uiport': ('django.db.models.fields.BooleanField', [], {'default': 'False'}) + }, + 'storageadmin.dvolume': { + 'Meta': {'unique_together': "(('container', 'dest_dir'),)", 'object_name': 'DVolume'}, + 'container': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['storageadmin.DContainer']"}), + 'description': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True'}), + 'dest_dir': ('django.db.models.fields.CharField', [], {'max_length': '1024'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'label': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True'}), + 'min_size': ('django.db.models.fields.IntegerField', [], {'null': 'True'}), + 'share': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['storageadmin.Share']", 'null': 'True'}), + 'uservol': ('django.db.models.fields.BooleanField', [], {'default': 'False'}) + }, + 'storageadmin.emailclient': { + 'Meta': {'object_name': 'EmailClient'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '1024'}), + 'receiver': ('django.db.models.fields.CharField', [], {'max_length': '1024'}), + 'sender': ('django.db.models.fields.CharField', [], {'max_length': '1024'}), + 'smtp_server': ('django.db.models.fields.CharField', [], {'max_length': '1024'}) + }, + 'storageadmin.group': { + 'Meta': {'object_name': 'Group'}, + 'admin': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'gid': ('django.db.models.fields.IntegerField', [], {'unique': 'True'}), + 'groupname': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + 'storageadmin.installedplugin': { + 'Meta': {'object_name': 'InstalledPlugin'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'install_date': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), + 'plugin_meta': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['storageadmin.Plugin']"}) + }, + 'storageadmin.iscsitarget': { + 'Meta': {'object_name': 'IscsiTarget'}, + 'dev_name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '128'}), + 'dev_size': ('django.db.models.fields.IntegerField', [], {}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'share': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['storageadmin.Share']"}), + 'tid': ('django.db.models.fields.IntegerField', [], {'unique': 'True'}), + 'tname': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '128'}) + }, + 'storageadmin.netatalkshare': { + 'Meta': {'object_name': 'NetatalkShare'}, + 'description': ('django.db.models.fields.CharField', [], {'default': "'afp on rockstor'", 'max_length': '1024'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'path': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '4096'}), + 'share': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'netatalkshare'", 'unique': 'True', 'to': "orm['storageadmin.Share']"}), + 'time_machine': ('django.db.models.fields.CharField', [], {'default': "'yes'", 'max_length': '3'}) + }, + 'storageadmin.networkinterface': { + 'Meta': {'object_name': 'NetworkInterface'}, + 'autoconnect': ('django.db.models.fields.CharField', [], {'max_length': '8', 'null': 'True'}), + 'ctype': ('django.db.models.fields.CharField', [], {'max_length': '64', 'null': 'True'}), + 'dname': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True'}), + 'dns_servers': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True'}), + 'dspeed': ('django.db.models.fields.CharField', [], {'max_length': '64', 'null': 'True'}), + 'dtype': ('django.db.models.fields.CharField', [], {'max_length': '64', 'null': 'True'}), + 'gateway': ('django.db.models.fields.CharField', [], {'max_length': '64', 'null': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'ipaddr': ('django.db.models.fields.CharField', [], {'max_length': '64', 'null': 'True'}), + 'itype': ('django.db.models.fields.CharField', [], {'default': "'io'", 'max_length': '100'}), + 'mac': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True'}), + 'method': ('django.db.models.fields.CharField', [], {'max_length': '64', 'null': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True'}), + 'netmask': ('django.db.models.fields.CharField', [], {'max_length': '64', 'null': 'True'}), + 'state': ('django.db.models.fields.CharField', [], {'max_length': '64', 'null': 'True'}) + }, + 'storageadmin.nfsexport': { + 'Meta': {'object_name': 'NFSExport'}, + 'export_group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['storageadmin.NFSExportGroup']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'mount': ('django.db.models.fields.CharField', [], {'max_length': '4096'}), + 'share': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['storageadmin.Share']"}) + }, + 'storageadmin.nfsexportgroup': { + 'Meta': {'object_name': 'NFSExportGroup'}, + 'admin_host': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True'}), + 'editable': ('django.db.models.fields.CharField', [], {'default': "'rw'", 'max_length': '2'}), + 'enabled': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'host_str': ('django.db.models.fields.CharField', [], {'max_length': '4096'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'mount_security': ('django.db.models.fields.CharField', [], {'default': "'insecure'", 'max_length': '8'}), + 'nohide': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'syncable': ('django.db.models.fields.CharField', [], {'default': "'async'", 'max_length': '5'}) + }, + 'storageadmin.oauthapp': { + 'Meta': {'object_name': 'OauthApp'}, + 'application': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['oauth2_provider.Application']", 'unique': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '128'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['storageadmin.User']"}) + }, + 'storageadmin.plugin': { + 'Meta': {'object_name': 'Plugin'}, + 'css_file_name': ('django.db.models.fields.CharField', [], {'max_length': '4096'}), + 'description': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '4096'}), + 'display_name': ('django.db.models.fields.CharField', [], {'default': "''", 'unique': 'True', 'max_length': '4096'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'js_file_name': ('django.db.models.fields.CharField', [], {'max_length': '4096'}), + 'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '4096'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '4096'}) + }, + 'storageadmin.pool': { + 'Meta': {'object_name': 'Pool'}, + 'compression': ('django.db.models.fields.CharField', [], {'max_length': '256', 'null': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'mnt_options': ('django.db.models.fields.CharField', [], {'max_length': '4096', 'null': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '4096'}), + 'raid': ('django.db.models.fields.CharField', [], {'max_length': '10'}), + 'size': ('django.db.models.fields.BigIntegerField', [], {'default': '0'}), + 'toc': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), + 'uuid': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True'}) + }, + 'storageadmin.poolbalance': { + 'Meta': {'object_name': 'PoolBalance'}, + 'end_time': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'message': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True'}), + 'percent_done': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'pool': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['storageadmin.Pool']"}), + 'start_time': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), + 'status': ('django.db.models.fields.CharField', [], {'default': "'started'", 'max_length': '10'}), + 'tid': ('django.db.models.fields.CharField', [], {'max_length': '36', 'null': 'True'}) + }, + 'storageadmin.poolscrub': { + 'Meta': {'object_name': 'PoolScrub'}, + 'corrected_errors': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'csum_discards': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'csum_errors': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'data_extents_scrubbed': ('django.db.models.fields.BigIntegerField', [], {'default': '0'}), + 'end_time': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'kb_scrubbed': ('django.db.models.fields.BigIntegerField', [], {'null': 'True'}), + 'last_physical': ('django.db.models.fields.BigIntegerField', [], {'default': '0'}), + 'malloc_errors': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'no_csum': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'pid': ('django.db.models.fields.IntegerField', [], {}), + 'pool': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['storageadmin.Pool']"}), + 'read_errors': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'start_time': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), + 'status': ('django.db.models.fields.CharField', [], {'default': "'started'", 'max_length': '10'}), + 'super_errors': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'tree_bytes_scrubbed': ('django.db.models.fields.BigIntegerField', [], {'default': '0'}), + 'tree_extents_scrubbed': ('django.db.models.fields.BigIntegerField', [], {'default': '0'}), + 'uncorrectable_errors': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'unverified_errors': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'verify_errors': ('django.db.models.fields.IntegerField', [], {'default': '0'}) + }, + 'storageadmin.posixacls': { + 'Meta': {'object_name': 'PosixACLs'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'owner': ('django.db.models.fields.CharField', [], {'max_length': '5'}), + 'perms': ('django.db.models.fields.CharField', [], {'max_length': '3'}), + 'smb_share': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['storageadmin.SambaShare']"}) + }, + 'storageadmin.rockon': { + 'Meta': {'object_name': 'RockOn'}, + 'description': ('django.db.models.fields.CharField', [], {'max_length': '2048'}), + 'https': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'icon': ('django.db.models.fields.URLField', [], {'max_length': '1024', 'null': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'link': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True'}), + 'more_info': ('django.db.models.fields.CharField', [], {'max_length': '4096', 'null': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '1024'}), + 'state': ('django.db.models.fields.CharField', [], {'max_length': '2048'}), + 'status': ('django.db.models.fields.CharField', [], {'max_length': '2048'}), + 'ui': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'version': ('django.db.models.fields.CharField', [], {'max_length': '2048'}), + 'volume_add_support': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'website': ('django.db.models.fields.CharField', [], {'max_length': '2048', 'null': 'True'}) + }, + 'storageadmin.sambacustomconfig': { + 'Meta': {'object_name': 'SambaCustomConfig'}, + 'custom_config': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'smb_share': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['storageadmin.SambaShare']"}) + }, + 'storageadmin.sambashare': { + 'Meta': {'object_name': 'SambaShare'}, + 'browsable': ('django.db.models.fields.CharField', [], {'default': "'yes'", 'max_length': '3'}), + 'comment': ('django.db.models.fields.CharField', [], {'default': "'foo bar'", 'max_length': '100'}), + 'guest_ok': ('django.db.models.fields.CharField', [], {'default': "'no'", 'max_length': '3'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'path': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '4096'}), + 'read_only': ('django.db.models.fields.CharField', [], {'default': "'no'", 'max_length': '3'}), + 'shadow_copy': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'share': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'sambashare'", 'unique': 'True', 'to': "orm['storageadmin.Share']"}), + 'snapshot_prefix': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}) + }, + 'storageadmin.setup': { + 'Meta': {'object_name': 'Setup'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'setup_disks': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'setup_network': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'setup_system': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'setup_user': ('django.db.models.fields.BooleanField', [], {'default': 'False'}) + }, + 'storageadmin.sftp': { + 'Meta': {'object_name': 'SFTP'}, + 'editable': ('django.db.models.fields.CharField', [], {'default': "'ro'", 'max_length': '2'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'share': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['storageadmin.Share']", 'unique': 'True'}) + }, + 'storageadmin.share': { + 'Meta': {'object_name': 'Share'}, + 'compression_algo': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True'}), + 'eusage': ('django.db.models.fields.BigIntegerField', [], {'default': '0'}), + 'group': ('django.db.models.fields.CharField', [], {'default': "'root'", 'max_length': '4096'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '4096'}), + 'owner': ('django.db.models.fields.CharField', [], {'default': "'root'", 'max_length': '4096'}), + 'perms': ('django.db.models.fields.CharField', [], {'default': "'755'", 'max_length': '9'}), + 'pool': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['storageadmin.Pool']"}), + 'pqgroup': ('django.db.models.fields.CharField', [], {'default': "'-1/-1'", 'max_length': '32'}), + 'qgroup': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'replica': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'rusage': ('django.db.models.fields.BigIntegerField', [], {'default': '0'}), + 'size': ('django.db.models.fields.BigIntegerField', [], {'default': '0'}), + 'subvol_name': ('django.db.models.fields.CharField', [], {'max_length': '4096'}), + 'toc': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), + 'uuid': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True'}) + }, + 'storageadmin.smartattribute': { + 'Meta': {'object_name': 'SMARTAttribute'}, + 'aid': ('django.db.models.fields.IntegerField', [], {}), + 'atype': ('django.db.models.fields.CharField', [], {'max_length': '64'}), + 'failed': ('django.db.models.fields.CharField', [], {'max_length': '64'}), + 'flag': ('django.db.models.fields.CharField', [], {'max_length': '64'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'info': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['storageadmin.SMARTInfo']"}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '256'}), + 'normed_value': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'raw_value': ('django.db.models.fields.CharField', [], {'max_length': '256'}), + 'threshold': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'updated': ('django.db.models.fields.CharField', [], {'max_length': '64'}), + 'worst': ('django.db.models.fields.IntegerField', [], {'default': '0'}) + }, + 'storageadmin.smartcapability': { + 'Meta': {'object_name': 'SMARTCapability'}, + 'capabilities': ('django.db.models.fields.CharField', [], {'max_length': '2048'}), + 'flag': ('django.db.models.fields.CharField', [], {'max_length': '64'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'info': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['storageadmin.SMARTInfo']"}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '1024'}) + }, + 'storageadmin.smarterrorlog': { + 'Meta': {'object_name': 'SMARTErrorLog'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'info': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['storageadmin.SMARTInfo']"}), + 'line': ('django.db.models.fields.CharField', [], {'max_length': '128'}) + }, + 'storageadmin.smarterrorlogsummary': { + 'Meta': {'object_name': 'SMARTErrorLogSummary'}, + 'details': ('django.db.models.fields.CharField', [], {'max_length': '1024'}), + 'error_num': ('django.db.models.fields.IntegerField', [], {}), + 'etype': ('django.db.models.fields.CharField', [], {'max_length': '256'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'info': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['storageadmin.SMARTInfo']"}), + 'lifetime_hours': ('django.db.models.fields.IntegerField', [], {}), + 'state': ('django.db.models.fields.CharField', [], {'max_length': '64'}) + }, + 'storageadmin.smartidentity': { + 'Meta': {'object_name': 'SMARTIdentity'}, + 'assessment': ('django.db.models.fields.CharField', [], {'max_length': '64'}), + 'ata_version': ('django.db.models.fields.CharField', [], {'max_length': '64'}), + 'capacity': ('django.db.models.fields.CharField', [], {'max_length': '64'}), + 'device_model': ('django.db.models.fields.CharField', [], {'max_length': '64'}), + 'enabled': ('django.db.models.fields.CharField', [], {'max_length': '64'}), + 'firmware_version': ('django.db.models.fields.CharField', [], {'max_length': '64'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'in_smartdb': ('django.db.models.fields.CharField', [], {'max_length': '64'}), + 'info': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['storageadmin.SMARTInfo']"}), + 'model_family': ('django.db.models.fields.CharField', [], {'max_length': '64'}), + 'rotation_rate': ('django.db.models.fields.CharField', [], {'max_length': '64'}), + 'sata_version': ('django.db.models.fields.CharField', [], {'max_length': '64'}), + 'scanned_on': ('django.db.models.fields.CharField', [], {'max_length': '64'}), + 'sector_size': ('django.db.models.fields.CharField', [], {'max_length': '64'}), + 'serial_number': ('django.db.models.fields.CharField', [], {'max_length': '64'}), + 'supported': ('django.db.models.fields.CharField', [], {'max_length': '64'}), + 'version': ('django.db.models.fields.CharField', [], {'max_length': '64'}), + 'world_wide_name': ('django.db.models.fields.CharField', [], {'max_length': '64'}) + }, + 'storageadmin.smartinfo': { + 'Meta': {'object_name': 'SMARTInfo'}, + 'disk': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['storageadmin.Disk']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'toc': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}) + }, + 'storageadmin.smarttestlog': { + 'Meta': {'object_name': 'SMARTTestLog'}, + 'description': ('django.db.models.fields.CharField', [], {'max_length': '64'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'info': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['storageadmin.SMARTInfo']"}), + 'lba_of_first_error': ('django.db.models.fields.CharField', [], {'max_length': '1024'}), + 'lifetime_hours': ('django.db.models.fields.IntegerField', [], {}), + 'pct_completed': ('django.db.models.fields.IntegerField', [], {}), + 'status': ('django.db.models.fields.CharField', [], {'max_length': '256'}), + 'test_num': ('django.db.models.fields.IntegerField', [], {}) + }, + 'storageadmin.smarttestlogdetail': { + 'Meta': {'object_name': 'SMARTTestLogDetail'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'info': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['storageadmin.SMARTInfo']"}), + 'line': ('django.db.models.fields.CharField', [], {'max_length': '128'}) + }, + 'storageadmin.snapshot': { + 'Meta': {'unique_together': "(('share', 'name'),)", 'object_name': 'Snapshot'}, + 'eusage': ('django.db.models.fields.BigIntegerField', [], {'default': '0'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '4096'}), + 'qgroup': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'real_name': ('django.db.models.fields.CharField', [], {'default': "'unknownsnap'", 'max_length': '4096'}), + 'rusage': ('django.db.models.fields.BigIntegerField', [], {'default': '0'}), + 'share': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['storageadmin.Share']"}), + 'size': ('django.db.models.fields.BigIntegerField', [], {'default': '0'}), + 'snap_type': ('django.db.models.fields.CharField', [], {'default': "'admin'", 'max_length': '64'}), + 'toc': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'uvisible': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'writable': ('django.db.models.fields.BooleanField', [], {'default': 'False'}) + }, + 'storageadmin.supportcase': { + 'Meta': {'object_name': 'SupportCase'}, + 'case_type': ('django.db.models.fields.CharField', [], {'max_length': '6'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'notes': ('django.db.models.fields.TextField', [], {}), + 'status': ('django.db.models.fields.CharField', [], {'max_length': '9'}), + 'zipped_log': ('django.db.models.fields.CharField', [], {'max_length': '128'}) + }, + 'storageadmin.tlscertificate': { + 'Meta': {'object_name': 'TLSCertificate'}, + 'certificate': ('django.db.models.fields.CharField', [], {'max_length': '12288', 'null': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'key': ('django.db.models.fields.CharField', [], {'max_length': '12288', 'null': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '1024'}) + }, + 'storageadmin.updatesubscription': { + 'Meta': {'object_name': 'UpdateSubscription'}, + 'appliance': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['storageadmin.Appliance']"}), + 'description': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '64'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '64', 'null': 'True'}), + 'status': ('django.db.models.fields.CharField', [], {'max_length': '64'}), + 'url': ('django.db.models.fields.CharField', [], {'max_length': '512'}) + }, + 'storageadmin.user': { + 'Meta': {'object_name': 'User'}, + 'admin': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'email': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}), + 'gid': ('django.db.models.fields.IntegerField', [], {'default': '5000'}), + 'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['storageadmin.Group']", 'null': 'True', 'blank': 'True'}), + 'homedir': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'public_key': ('django.db.models.fields.CharField', [], {'max_length': '4096', 'null': 'True', 'blank': 'True'}), + 'shell': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True'}), + 'smb_shares': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'admin_users'", 'null': 'True', 'to': "orm['storageadmin.SambaShare']"}), + 'uid': ('django.db.models.fields.IntegerField', [], {'default': '5000'}), + 'user': ('django.db.models.fields.related.OneToOneField', [], {'blank': 'True', 'related_name': "'suser'", 'unique': 'True', 'null': 'True', 'to': u"orm['auth.User']"}), + 'username': ('django.db.models.fields.CharField', [], {'default': "''", 'unique': 'True', 'max_length': '4096'}) + } + } + + complete_apps = ['storageadmin'] \ No newline at end of file diff --git a/src/rockstor/storageadmin/models/__init__.py b/src/rockstor/storageadmin/models/__init__.py index cad3bd277..ff30c40b7 100644 --- a/src/rockstor/storageadmin/models/__init__.py +++ b/src/rockstor/storageadmin/models/__init__.py @@ -44,7 +44,8 @@ from pool_balance import PoolBalance from tls_certificate import TLSCertificate from rockon import (RockOn, DImage, DContainer, DPort, DVolume, - ContainerOption, DCustomConfig, DContainerLink) + ContainerOption, DCustomConfig, DContainerLink, + DContainerEnv) from smart import (SMARTAttribute, SMARTCapability, SMARTErrorLog, SMARTErrorLogSummary, SMARTTestLog, SMARTTestLogDetail, SMARTIdentity, SMARTInfo) diff --git a/src/rockstor/storageadmin/models/rockon.py b/src/rockstor/storageadmin/models/rockon.py index 6876c5c2b..9f93a44ec 100644 --- a/src/rockstor/storageadmin/models/rockon.py +++ b/src/rockstor/storageadmin/models/rockon.py @@ -62,6 +62,10 @@ class DContainer(models.Model): dimage = models.ForeignKey(DImage) name = models.CharField(max_length=1024, unique=True) launch_order = models.IntegerField(default=1) + #if uid is None, container's owner is not set. defaults to root. + #if it's -1, then owner is set to the owner of first volume, if any. + #if it's an integer other than -1, like 0, then owner is set to that uid. + uid = models.IntegerField(null=True) class Meta: app_label = 'storageadmin' @@ -131,3 +135,15 @@ class DCustomConfig(models.Model): class Meta: unique_together = ('rockon', 'key',) app_label = 'storageadmin' + + +class DContainerEnv(models.Model): + container = models.ForeignKey(DContainer) + key = models.CharField(max_length=1024) + val = models.CharField(max_length=1024, null=True) + description = models.CharField(max_length=2048, null=True) + label = models.CharField(max_length=64, null=True) + + class Meta: + unique_together = ('container', 'key') + app_label = 'storageadmin' diff --git a/src/rockstor/storageadmin/serializers.py b/src/rockstor/storageadmin/serializers.py index f93bf5b6d..092c21cdb 100644 --- a/src/rockstor/storageadmin/serializers.py +++ b/src/rockstor/storageadmin/serializers.py @@ -24,11 +24,12 @@ NFSExportGroup, SFTP, AdvancedNFSExport, OauthApp, NetatalkShare, Group, PoolBalance, SambaCustomConfig, TLSCertificate, RockOn, - DVolume, DPort, DCustomConfig, SMARTAttribute, - SMARTCapability, SMARTInfo, SMARTErrorLog, - SMARTErrorLogSummary, SMARTTestLog, - SMARTTestLogDetail, SMARTIdentity, - ConfigBackup, EmailClient, UpdateSubscription) + DVolume, DPort, DCustomConfig, DContainerEnv, + SMARTAttribute, SMARTCapability, SMARTInfo, + SMARTErrorLog, SMARTErrorLogSummary, + SMARTTestLog, SMARTTestLogDetail, + SMARTIdentity, ConfigBackup, EmailClient, + UpdateSubscription) from django.contrib.auth.models import User as DjangoUser @@ -209,6 +210,9 @@ class RockOnCustomConfigSerializer(serializers.ModelSerializer): class Meta: model = DCustomConfig +class RockOnEnvironmentSerializer(serializers.ModelSerializer): + class Meta: + model = DContainerEnv class SMARTCapabilitySerializer(serializers.ModelSerializer): class Meta: diff --git a/src/rockstor/storageadmin/static/storageadmin/js/models/models.js b/src/rockstor/storageadmin/static/storageadmin/js/models/models.js index 171568d5b..4fcb54d49 100644 --- a/src/rockstor/storageadmin/static/storageadmin/js/models/models.js +++ b/src/rockstor/storageadmin/static/storageadmin/js/models/models.js @@ -642,6 +642,27 @@ var RockOnCustomConfigCollection = RockStorPaginatedCollection.extend({ } }); +var RockOnEnvironment = Backbone.Model.extend({ + urlRoot: '/api/rockon/environment/' + this.rid +}); + +var RockOnEnvironmentCollection = RockStorPaginatedCollection.extend({ + model: RockOnEnvironment, + initialize: function(models, options) { + this.constructor.__super__.initialize.apply(this, arguments); + if (options) { + this.rid = options.rid; + } + }, + baseUrl: function() { + if (this.rid) { + return '/api/rockons/environment/' + this.rid; + } else { + return '/api/rockons/environment'; + } + } +}); + var EmailAccount = Backbone.Model.extend({ urlRoot: '/api/email' }); diff --git a/src/rockstor/storageadmin/static/storageadmin/js/rockstor.js b/src/rockstor/storageadmin/static/storageadmin/js/rockstor.js index c49b9eca3..03d6a3293 100644 --- a/src/rockstor/storageadmin/static/storageadmin/js/rockstor.js +++ b/src/rockstor/storageadmin/static/storageadmin/js/rockstor.js @@ -493,7 +493,7 @@ RockstorWizardPage = Backbone.View.extend({ render: function() { $(this.el).html(this.template({ - model: this.model, + model: this.model })); return this; }, diff --git a/src/rockstor/storageadmin/static/storageadmin/js/templates/rockons/more_info.jst b/src/rockstor/storageadmin/static/storageadmin/js/templates/rockons/more_info.jst index 06ea2360b..fa70887af 100644 --- a/src/rockstor/storageadmin/static/storageadmin/js/templates/rockons/more_info.jst +++ b/src/rockstor/storageadmin/static/storageadmin/js/templates/rockons/more_info.jst @@ -1 +1 @@ -{{rockonMoreInfo}} +{{{rockonMoreInfo}}} diff --git a/src/rockstor/storageadmin/static/storageadmin/js/views/rockons.js b/src/rockstor/storageadmin/static/storageadmin/js/views/rockons.js index 21e558055..4441727e7 100644 --- a/src/rockstor/storageadmin/static/storageadmin/js/views/rockons.js +++ b/src/rockstor/storageadmin/static/storageadmin/js/views/rockons.js @@ -27,1066 +27,1167 @@ RockonsView = RockstorLayoutView.extend({ - initialize: function() { - this.constructor.__super__.initialize.apply(this, arguments); - this.template = window.JST.rockons_rockons; - this.rockons = new RockOnCollection({}); - this.service = new Service({ name: 'docker' }); - this.dependencies.push(this.rockons, this.service); - this.updateFreq = 15000; - this.defTab = 0; - this.initHandlebarHelpers(); - }, - - events: { - 'switchChange.bootstrapSwitch': 'rockonToggle', - 'click #js-install-rockon': 'installRockon', - 'click #js-uninstall-rockon': 'uninstallRockon', - 'click #js-rockons-installed': 'installedRockons', - 'click #js-update-rockons': 'updateRockons', - 'click #js-rockon-settings': 'rockonSettings', - 'click #js-rockon-info': 'rockonInfo' - }, - - render: function() { - this.service.fetch(); - this.rockons.fetch(); - this.updateStatus(); - - return this; - }, - - renderRockons: function() { - var _this = this; - - var ui_map = {}; - var uis = this.rockons.filter(function(rockon) { - ui_map[rockon.get('id')] = null; - if (rockon.get('ui')) { - var protocol = "http://"; - if (rockon.get('https')) { - protocol = "https://"; - } - var ui_link = protocol + window.location.hostname; - if (rockon.get('ui_port')) { - ui_link += ":" + rockon.get('ui_port'); - } - if (rockon.get('link')) { - ui_link += "/" + rockon.get('link'); - } - ui_map[rockon.get('id')] = ui_link; - } - return false; - }); - - $(this.el).html(this.template({ - rockons: this.rockons, - status: this.service.get('status'), - ui_map: ui_map - })); - - if (!this.dockerServiceView) { - this.dockerServiceView = new DockerServiceView({ - parentView: this, - dockerService: this.dockerService - }); + initialize: function() { + this.constructor.__super__.initialize.apply(this, arguments); + this.template = window.JST.rockons_rockons; + this.rockons = new RockOnCollection({}); + this.service = new Service({ name: 'docker' }); + this.dependencies.push(this.rockons, this.service); + this.updateFreq = 15000; + this.defTab = 0; + this.initHandlebarHelpers(); + }, + + events: { + 'switchChange.bootstrapSwitch': 'rockonToggle', + 'click #js-install-rockon': 'installRockon', + 'click #js-uninstall-rockon': 'uninstallRockon', + 'click #js-rockons-installed': 'installedRockons', + 'click #js-update-rockons': 'updateRockons', + 'click #js-rockon-settings': 'rockonSettings', + 'click #js-rockon-info': 'rockonInfo' + }, + + render: function() { + this.service.fetch(); + this.rockons.fetch(); + this.updateStatus(); + + return this; + }, + + renderRockons: function() { + var _this = this; + + var ui_map = {}; + var uis = this.rockons.filter(function(rockon) { + ui_map[rockon.get('id')] = null; + if (rockon.get('ui')) { + var protocol = "http://"; + if (rockon.get('https')) { + protocol = "https://"; } - // Render the Rockons template with a status describing whether - // the Rockons service has been enabled - - $('#docker-service-ph').append(this.dockerServiceView.render().el); - - $('#install-rockon-overlay').overlay({load: false}); - this.$("ul.nav.nav-tabs").tabs("div.css-panes > div"); - this.$('.nav-tabs li:eq(' + this.defTab + ') a').click(); - - //initalize bootstrap switch - this.$("[type='checkbox']").bootstrapSwitch(); - this.$("[type='checkbox']").bootstrapSwitch('onColor','success'); //left side text color - this.$("[type='checkbox']").bootstrapSwitch('offColor','danger'); //right side text color - }, - - installRockon: function(event) { - var _this = this; - this.defTab = 0; - event.preventDefault(); - var button = $(event.currentTarget); - var rockon_id = button.attr('data-name'); - var rockon_o = _this.rockons.get(rockon_id); - var wizardView = new RockonInstallWizardView({ - model: new Backbone.Model({ rockon: rockon_o }), - title: rockon_o.get('name') + ' install wizard', - parent: this - }); - $('.overlay-content', '#install-rockon-overlay').html(wizardView.render().el); - $('#install-rockon-overlay').overlay().load(); - }, - - uninstallRockon: function(event) { - var _this = this; - event.preventDefault(); - var button = $(event.currentTarget); - if (buttonDisabled(button)) return false; - var rockon_id = button.attr('data-name'); - var rockon_o = _this.rockons.get(rockon_id); - if (confirm("Are you sure you want to uninstall this Rock-on (" + rockon_o.get('name') + ")?")) { - disableButton(button); - $.ajax({ - url: '/api/rockons/' + rockon_id + '/uninstall', - type: 'POST', - dataType: 'json', - success: function() { - _this.defTab = 0; - _this.render(); - enableButton(button); - }, - error: function(xhr, status, error) { - enableButton(button); - } - }); + var ui_link = protocol + window.location.hostname; + if (rockon.get('ui_port')) { + ui_link += ":" + rockon.get('ui_port'); } - }, - - updateRockons: function(event) { - var _this = this; - event.preventDefault(); - var button = $(event.currentTarget); - if (buttonDisabled(button)) return false; - disableButton(button); - $.ajax({ - url: '/api/rockons/update', - type: 'POST', - dataType: 'json', - success: function() { - _this.defTab = 1; - _this.render(); - enableButton(button); - }, - error: function(xhr, status, error) { - enableButton(button); - } - }); - }, - - rockonSettings: function(event) { - var _this = this; - event.preventDefault(); - var rockon_id = _this.getRockonId(event); - var rockon_o = _this.rockons.get(rockon_id); - _this.stopPolling(); - var wizardView = new RockonSettingsWizardView({ - model: new Backbone.Model({ rockon: rockon_o}), - title: rockon_o.get('name') + ' Settings', - parent: this - }); - $('.overlay-content', '#install-rockon-overlay').html(wizardView.render().el); - $('#install-rockon-overlay').overlay().load(); - }, - - rockonInfo: function(event) { - var _this = this; - event.preventDefault(); - var rockon_id = _this.getRockonId(event); - var rockon_o = _this.rockons.get(rockon_id); - _this.stopPolling(); - var infoView = new RockonInfoView({ - model: new Backbone.Model({ rockon: rockon_o}), - title: 'Additional information about ' + rockon_o.get('name') + ' Rock-on', - parent: this - }); - $('.overlay-content', '#install-rockon-overlay').html(infoView.render().el); - $('#install-rockon-overlay').overlay().load(); - }, - - getRockonId: function(event) { - var slider = $(event.currentTarget); - return slider.attr('data-rockon-id'); - }, - - rockonToggle: function(event,state){ - var rockonId = $(event.target).attr('data-rockon-id'); - if(state){ - this.startRockon(rockonId); - }else{ - this.stopRockon(rockonId); + if (rockon.get('link')) { + ui_link += "/" + rockon.get('link'); } - }, - - startRockon: function(rockonId) { - console.log(event); - var _this = this; - this.stopPolling(); - $.ajax({ - url: '/api/rockons/' + rockonId + '/start', - type: 'POST', - dataType: 'json', - success: function(data, status, xhr) { - _this.defTab = 0; - _this.updateStatus(); - }, - error: function(data, status, xhr) { - console.log('error while starting rockon'); - } - }); - }, - - stopRockon: function(rockonId) { - var _this = this; - this.stopPolling(); - $.ajax({ - url: '/api/rockons/' + rockonId + '/stop', - type: 'POST', - dataType: 'json', - success: function(data, status, xhr) { - _this.defTab = 0; - _this.updateStatus(); - }, - error: function(data, status, xhr) { - console.log('error while stopping rockon'); - } - }); - }, - - pendingOps: function() { - var pending = this.rockons.find(function(rockon) { - if ((rockon.get('status').search('pending') != -1) || (rockon.get('state').search('pending') != -1)) { - return true; - } - }); - if (pending) { return true; } - return false; - }, - - updateStatus: function() { - var _this = this; - _this.startTime = new Date().getTime(); - _this.rockons.fetch({ - silent: true, - success: function(data, response, options) { - _this.renderRockons(); - if (_this.pendingOps()) { - var ct = new Date().getTime(); - var diff = ct - _this.startTime; - if (diff > _this.updateFreq) { - _this.updateStatus(); - } else { - _this.timeoutId = window.setTimeout( function() { - _this.updateStatus(); - }, _this.updateFreq - diff); - } - } else { - _this.stopPolling(); - } - } - }); - }, - - stopPolling: function() { - if (!_.isUndefined(this.timeoutId)) { - window.clearInterval(this.timeoutId); - } - }, - - installedRockons: function(event) { - if (this.pendingOps()) { - this.updateStatus(); + ui_map[rockon.get('id')] = ui_link; + } + return false; + }); + + $(this.el).html(this.template({ + rockons: this.rockons, + status: this.service.get('status'), + ui_map: ui_map + })); + + if (!this.dockerServiceView) { + this.dockerServiceView = new DockerServiceView({ + parentView: this, + dockerService: this.dockerService + }); + } + // Render the Rockons template with a status describing whether + // the Rockons service has been enabled + + $('#docker-service-ph').append(this.dockerServiceView.render().el); + + $('#install-rockon-overlay').overlay({load: false}); + this.$("ul.nav.nav-tabs").tabs("div.css-panes > div"); + this.$('.nav-tabs li:eq(' + this.defTab + ') a').click(); + + //initalize bootstrap switch + this.$("[type='checkbox']").bootstrapSwitch(); + this.$("[type='checkbox']").bootstrapSwitch('onColor','success'); //left side text color + this.$("[type='checkbox']").bootstrapSwitch('offColor','danger'); //right side text color + }, + + installRockon: function(event) { + var _this = this; + this.defTab = 0; + event.preventDefault(); + var button = $(event.currentTarget); + var rockon_id = button.attr('data-name'); + var rockon_o = _this.rockons.get(rockon_id); + var wizardView = new RockonInstallWizardView({ + model: new Backbone.Model({ rockon: rockon_o }), + title: rockon_o.get('name') + ' install wizard', + parent: this + }); + $('.overlay-content', '#install-rockon-overlay').html(wizardView.render().el); + $('#install-rockon-overlay').overlay().load(); + }, + + uninstallRockon: function(event) { + var _this = this; + event.preventDefault(); + var button = $(event.currentTarget); + if (buttonDisabled(button)) return false; + var rockon_id = button.attr('data-name'); + var rockon_o = _this.rockons.get(rockon_id); + if (confirm("Are you sure you want to uninstall this Rock-on (" + rockon_o.get('name') + ")?")) { + disableButton(button); + $.ajax({ + url: '/api/rockons/' + rockon_id + '/uninstall', + type: 'POST', + dataType: 'json', + success: function() { + _this.defTab = 0; + _this.render(); + enableButton(button); + }, + error: function(xhr, status, error) { + enableButton(button); } - }, - - initHandlebarHelpers: function(){ - Handlebars.registerHelper('display_installedRockons', function(){ - var html = ''; - _this = this; - var installed = 0; - this.rockons.each(function(rockon, index) { - if (rockon.get('state') == 'installed' || rockon.get('state').match('pending')) { - installed += 1; - html += '
'; - if (rockon.get('state').search('pending') > -1 || rockon.get('status').search('pending') > -1) { - var text = 'Installing ...'; - if (rockon.get('state') == 'pending_uninstall') { - text = 'Uninstalling ...'; - } else if (rockon.get('status') == 'pending_start') { - text = 'Starting ...'; - } else if (rockon.get('status') == 'pending_stop') { - text = 'Stopping ...'; - } - html += '
'; - html += '
'; - html += ''; - html += '
'; - html += '

' + text + '

'; - html += '
'; - html += '
'; - html += '
'; - } - html += '
'; - html += '
'; - html += '

' + rockon.get('name') + '

'; - html += '

' + rockon.get('description') + '

'; - html += '

Current status: ' + rockon.get('status') + '

'; - html += '
'; - html += '
'; - html += '
'; - if (rockon.get('state') == 'installed' && !rockon.get('status').match('pending')) { - if (rockon.get('status') == 'started') { - html += ''; - } else { - html += ''; - } - html += '  '; - if (rockon.get('more_info')) { - html += ''; - } - html += '

'; - if (ui_map[rockon.get('id')]) { - if (rockon.get('status') == 'started') { - html += '' + rockon.get('name') + ' UI'; - } else { - html += '' + rockon.get('name') + ' UI'; - } - } - if (rockon.get('status') != 'started') { - html += 'Uninstall'; - } - - } - html += '
'; - html += '
'; - html += '
'; - } - }); - if (installed == 0) { - html += '
'; - html += '
'; - html += '
'; - html += '

There are no Rock-ons installed currently.

'; - html += '
'; - html += '
'; - html += '
'; - } - return new Handlebars.SafeString(html); - }); - - Handlebars.registerHelper('display_allRockons', function(){ - var html = ''; - var all = 0; - this.rockons.each(function(rockon, index) { - if (rockon.get('state') == 'available' || rockon.get('state') == 'install_failed') { - all += 1; - html += '
'; - html += '
'; - html += '
'; - html += '

' + rockon.get('name') + '

'; - html += '

' + rockon.get('description') + '

'; - if (rockon.get('state') == 'install_failed') { - html += 'Failed to install in the previous attempt. Here\'s how you can proceed.'; - html += '
    '; - html += '
  • Check logs in /opt/rockstor/var/log for clues.
  • '; - html += '
  • Install again.
  • '; - html += '
  • If the problem persists, post on the Forum or email support@rockstor.com
  • '; - html += '
'; - } - html += 'Install'; - html += '
'; - html += '
'; - html += '
'; - } - }); - if (all == 0) { - html += '
'; - html += '
'; - html += '
'; - html += '

Click on Update button to check for new Rock-ons.

'; - html += '
'; - html += '
'; - html += '
'; - } - return new Handlebars.SafeString(html); - }); + }); } + }, + + updateRockons: function(event) { + var _this = this; + event.preventDefault(); + var button = $(event.currentTarget); + if (buttonDisabled(button)) return false; + disableButton(button); + $.ajax({ + url: '/api/rockons/update', + type: 'POST', + dataType: 'json', + success: function() { + _this.defTab = 1; + _this.render(); + enableButton(button); + }, + error: function(xhr, status, error) { + enableButton(button); + } + }); + }, + + rockonSettings: function(event) { + var _this = this; + event.preventDefault(); + var rockon_id = _this.getRockonId(event); + var rockon_o = _this.rockons.get(rockon_id); + _this.stopPolling(); + var wizardView = new RockonSettingsWizardView({ + model: new Backbone.Model({ rockon: rockon_o}), + title: rockon_o.get('name') + ' Settings', + parent: this + }); + $('.overlay-content', '#install-rockon-overlay').html(wizardView.render().el); + $('#install-rockon-overlay').overlay().load(); + }, + + rockonInfo: function(event) { + var _this = this; + event.preventDefault(); + var rockon_id = _this.getRockonId(event); + var rockon_o = _this.rockons.get(rockon_id); + _this.stopPolling(); + var infoView = new RockonInfoView({ + model: new Backbone.Model({ rockon: rockon_o}), + title: 'Additional information about ' + rockon_o.get('name') + ' Rock-on', + parent: this + }); + $('.overlay-content', '#install-rockon-overlay').html(infoView.render().el); + $('#install-rockon-overlay').overlay().load(); + }, + + getRockonId: function(event) { + var slider = $(event.currentTarget); + return slider.attr('data-rockon-id'); + }, + + rockonToggle: function(event,state){ + var rockonId = $(event.target).attr('data-rockon-id'); + if(state){ + this.startRockon(rockonId); + }else{ + this.stopRockon(rockonId); + } + }, + + startRockon: function(rockonId) { + console.log(event); + var _this = this; + this.stopPolling(); + $.ajax({ + url: '/api/rockons/' + rockonId + '/start', + type: 'POST', + dataType: 'json', + success: function(data, status, xhr) { + _this.defTab = 0; + _this.updateStatus(); + }, + error: function(data, status, xhr) { + console.log('error while starting rockon'); + } + }); + }, + + stopRockon: function(rockonId) { + var _this = this; + this.stopPolling(); + $.ajax({ + url: '/api/rockons/' + rockonId + '/stop', + type: 'POST', + dataType: 'json', + success: function(data, status, xhr) { + _this.defTab = 0; + _this.updateStatus(); + }, + error: function(data, status, xhr) { + console.log('error while stopping rockon'); + } + }); + }, + + pendingOps: function() { + var pending = this.rockons.find(function(rockon) { + if ((rockon.get('status').search('pending') != -1) || (rockon.get('state').search('pending') != -1)) { + return true; + } + }); + if (pending) { return true; } + return false; + }, + + updateStatus: function() { + var _this = this; + _this.startTime = new Date().getTime(); + _this.rockons.fetch({ + silent: true, + success: function(data, response, options) { + _this.renderRockons(); + if (_this.pendingOps()) { + var ct = new Date().getTime(); + var diff = ct - _this.startTime; + if (diff > _this.updateFreq) { + _this.updateStatus(); + } else { + _this.timeoutId = window.setTimeout( function() { + _this.updateStatus(); + }, _this.updateFreq - diff); + } + } else { + _this.stopPolling(); + } + } + }); + }, -}); - + stopPolling: function() { + if (!_.isUndefined(this.timeoutId)) { + window.clearInterval(this.timeoutId); + } + }, -RockonInstallWizardView = WizardView.extend({ - initialize: function() { - WizardView.prototype.initialize.apply(this, arguments); - this.pages = []; - this.rockon = this.model.get('rockon'); - this.volumes = new RockOnVolumeCollection(null, {rid: this.rockon.id}); - this.ports = new RockOnPortCollection(null, {rid: this.rockon.id}); - this.custom_config = new RockOnCustomConfigCollection(null, {rid: this.rockon.id}); - }, - - fetchVolumes: function() { - var _this = this; - this.volumes.fetch({ - success: function () { - _this.model.set('volumes', _this.volumes); - _this.fetchPorts(); + installedRockons: function(event) { + if (this.pendingOps()) { + this.updateStatus(); + } + }, + + initHandlebarHelpers: function(){ + Handlebars.registerHelper('display_installedRockons', function(){ + var html = ''; + _this = this; + var installed = 0; + this.rockons.each(function(rockon, index) { + if (rockon.get('state') == 'installed' || rockon.get('state').match('pending')) { + installed += 1; + html += '
'; + if (rockon.get('state').search('pending') > -1 || rockon.get('status').search('pending') > -1) { + var text = 'Installing ...'; + if (rockon.get('state') == 'pending_uninstall') { + text = 'Uninstalling ...'; + } else if (rockon.get('status') == 'pending_start') { + text = 'Starting ...'; + } else if (rockon.get('status') == 'pending_stop') { + text = 'Stopping ...'; } - }); - }, - - fetchPorts: function() { - var _this = this; - this.ports.fetch({ - success: function() { - _this.model.set('ports', _this.ports); - _this.fetchCustomConfig(); + html += '
'; + html += '
'; + html += ''; + html += '
'; + html += '

' + text + '

'; + html += '
'; + html += '
'; + html += '
'; + } + html += '
'; + html += '
'; + html += '

' + rockon.get('name') + '

'; + html += '

' + rockon.get('description') + '

'; + html += '

Current status: ' + rockon.get('status') + '

'; + html += '
'; + html += '
'; + html += '
'; + if (rockon.get('state') == 'installed' && !rockon.get('status').match('pending')) { + if (rockon.get('status') == 'started') { + html += ''; + } else { + html += ''; } - }); - }, - - fetchCustomConfig: function() { - var _this = this; - this.custom_config.fetch({ - success: function() { - _this.model.set('custom_config', _this.custom_config); - _this.addPages(); + html += '   '; + if (rockon.get('more_info')) { + html += ''; + } + html += '

'; + if (_this.ui_map[rockon.get('id')]) { + if (rockon.get('status') == 'started') { + html += '' + rockon.get('name') + ' UI'; + } else { + html += '' + rockon.get('name') + ' UI'; + } + } + if (rockon.get('status') != 'started') { + html += 'Uninstall'; } - }); - }, - - render: function() { - this.fetchVolumes(); - return this; - }, - addPages: function() { - if (this.volumes.length > 0) { - this.pages.push(RockonShareChoice); - } - if (this.ports.length > 0) { - this.pages.push(RockonPortChoice); + } + html += '
'; + html += '
'; + html += '
'; } - if (this.custom_config.length > 0) { - this.pages.push(RockonCustomChoice); + }); + if (installed == 0) { + html += '
'; + html += '
'; + html += '
'; + html += '

There are no Rock-ons installed currently.

'; + html += '
'; + html += '
'; + html += '
'; + } + return new Handlebars.SafeString(html); + }); + + Handlebars.registerHelper('display_allRockons', function(){ + var html = ''; + var all = 0; + this.rockons.each(function(rockon, index) { + if (rockon.get('state') == 'available' || rockon.get('state') == 'install_failed') { + all += 1; + html += '
'; + html += '
'; + html += '
'; + html += '

' + rockon.get('name') + '

'; + html += '

' + rockon.get('description') + '

'; + if (rockon.get('state') == 'install_failed') { + html += 'Failed to install in the previous attempt. Here\'s how you can proceed.'; + html += '
    '; + html += '
  • Check logs in /opt/rockstor/var/log for clues.
  • '; + html += '
  • Install again.
  • '; + html += '
  • If the problem persists, post on the Forum or email support@rockstor.com
  • '; + html += '
'; + } + html += 'Install'; + html += '
'; + html += '
'; + html += '
'; } - this.pages.push.apply(this.pages, [RockonInstallSummary, RockonInstallComplete]); - WizardView.prototype.render.apply(this, arguments); - return this; - }, - - setCurrentPage: function() { - this.currentPage = new this.pages[this.currentPageNum]({ - model: this.model, - parent: this, - evAgg: this.evAgg - }); - }, - - modifyButtonText: function() { - if (this.currentPageNum == (this.pages.length - 2)) { - this.$('#next-page').html('Submit'); - } else if (this.currentPageNum == (this.pages.length - 1)) { - this.$('#prev-page').hide(); - this.$('#next-page').html('Close'); - } else if (this.currentPageNum == 0) { - this.$('#prev-page').hide(); - } else { - this.$('#prev-page').show(); - this.$('#next-page').html('Next'); - this.$('#ph-wizard-buttons').show(); - } - }, + }); + if (all == 0) { + html += '
'; + html += '
'; + html += '
'; + html += '

Click on Update button to check for new Rock-ons.

'; + html += '
'; + html += '
'; + html += '
'; + } + return new Handlebars.SafeString(html); + }); + } + +}); - lastPage: function() { - return ((this.pages.length > 1) - && ((this.pages.length-1) == this.currentPageNum)); - }, - finish: function() { - this.parent.$('#install-rockon-overlay').overlay().close(); - this.parent.render(); +RockonInstallWizardView = WizardView.extend({ + initialize: function() { + WizardView.prototype.initialize.apply(this, arguments); + this.pages = []; + this.rockon = this.model.get('rockon'); + this.volumes = new RockOnVolumeCollection(null, {rid: this.rockon.id}); + this.ports = new RockOnPortCollection(null, {rid: this.rockon.id}); + this.custom_config = new RockOnCustomConfigCollection(null, {rid: this.rockon.id}); + this.environment = new RockOnEnvironmentCollection(null, {rid: this.rockon.id}); + }, + + fetchVolumes: function() { + var _this = this; + this.volumes.fetch({ + success: function () { + _this.model.set('volumes', _this.volumes); + _this.fetchPorts(); + } + }); + }, + + fetchPorts: function() { + var _this = this; + this.ports.fetch({ + success: function() { + _this.model.set('ports', _this.ports); + _this.fetchCustomConfig(); + } + }); + }, + + fetchCustomConfig: function() { + var _this = this; + this.custom_config.fetch({ + success: function() { + _this.model.set('custom_config', _this.custom_config); + _this.fetchEnvironment(); + } + }); + }, + + fetchEnvironment: function() { + var _this = this; + this.environment.fetch({ + success: function() { + _this.model.set('environment', _this.environment); + _this.addPages(); + } + }); + }, + + render: function() { + this.fetchVolumes(); + return this; + }, + + addPages: function() { + if (this.volumes.length > 0) { + this.pages.push(RockonShareChoice); + } + if (this.ports.length > 0) { + this.pages.push(RockonPortChoice); + } + if (this.environment.length > 0) { + this.pages.push(RockonEnvironment); + } + if (this.custom_config.length > 0) { + this.pages.push(RockonCustomChoice); } + this.pages.push.apply(this.pages, [RockonInstallSummary, RockonInstallComplete]); + WizardView.prototype.render.apply(this, arguments); + return this; + }, + + setCurrentPage: function() { + this.currentPage = new this.pages[this.currentPageNum]({ + model: this.model, + parent: this, + evAgg: this.evAgg + }); + }, + + modifyButtonText: function() { + if (this.currentPageNum == (this.pages.length - 2)) { + this.$('#next-page').html('Submit'); + } else if (this.currentPageNum == (this.pages.length - 1)) { + this.$('#prev-page').hide(); + this.$('#next-page').html('Close'); + } else if (this.currentPageNum == 0) { + this.$('#prev-page').hide(); + } else { + this.$('#prev-page').show(); + this.$('#next-page').html('Next'); + this.$('#ph-wizard-buttons').show(); + } + }, + + lastPage: function() { + return ((this.pages.length > 1) + && ((this.pages.length-1) == this.currentPageNum)); + }, + finish: function() { + this.parent.$('#install-rockon-overlay').overlay().close(); + this.parent.render(); + } }); RockonShareChoice = RockstorWizardPage.extend({ - initialize: function() { - this.template = window.JST.rockons_install_choice; - this.vol_template = window.JST.rockons_vol_form; - this.rockon = this.model.get('rockon'); - this.volumes = this.model.get('volumes'); - this.shares = new ShareCollection(); - this.shares.setPageSize(100); - RockstorWizardPage.prototype.initialize.apply(this, arguments); - this.shares.on('reset', this.renderVolumes, this); - this.initHandlebarHelpers(); - }, - - render: function() { - RockstorWizardPage.prototype.render.apply(this, arguments); - this.shares.fetch(); - return this; - }, - - renderVolumes: function() { - this.$('#ph-vols-table').html(this.vol_template({volumes: this.volumes, shares: this.shares})); - //form validation - this.volForm = this.$('#vol-select-form'); - var rules = {}; - var messages = {}; - this.volumes.each(function(volume) { - rules[volume.id] = { required: true }; - messages[volume.id] = "Please read the tooltip and make the right selection"; - }); - this.validator = this.volForm.validate({ - rules: rules, - messages: messages - }); - }, - - save: function() { - - // Validate the form - if (!this.volForm.valid()) { - this.validator.showErrors(); - return $.Deferred().reject(); - } + initialize: function() { + this.template = window.JST.rockons_install_choice; + this.vol_template = window.JST.rockons_vol_form; + this.rockon = this.model.get('rockon'); + this.volumes = this.model.get('volumes'); + this.shares = new ShareCollection(); + this.shares.setPageSize(100); + RockstorWizardPage.prototype.initialize.apply(this, arguments); + this.shares.on('reset', this.renderVolumes, this); + this.initHandlebarHelpers(); + }, + + render: function() { + RockstorWizardPage.prototype.render.apply(this, arguments); + this.shares.fetch(); + return this; + }, + + renderVolumes: function() { + this.$('#ph-vols-table').html(this.vol_template({volumes: this.volumes, shares: this.shares})); + //form validation + this.volForm = this.$('#vol-select-form'); + var rules = {}; + var messages = {}; + this.volumes.each(function(volume) { + rules[volume.id] = { required: true }; + messages[volume.id] = "Please read the tooltip and make the right selection"; + }); + this.validator = this.volForm.validate({ + rules: rules, + messages: messages + }); + }, + + save: function() { + + // Validate the form + if (!this.volForm.valid()) { + this.validator.showErrors(); + return $.Deferred().reject(); + } - var share_map = {}; - var volumes = this.volumes.filter(function(volume) { - share_map[volume.get('dest_dir')] = this.$('#' + volume.id).val(); - return volume; - }, this); - this.model.set('share_map', share_map); - return $.Deferred().resolve(); - }, - - initHandlebarHelpers: function(){ - Handlebars.registerHelper('display_volumesForm', function(){ - var html = ''; - var _this = this; - this.volumes.each(function(volume, index) { - html += '
'; - html += ''; - html += '
'; - html += ''; - html += '
'; - html += ''; - html += '
'; - }); - return new Handlebars.SafeString(html); + var share_map = {}; + var volumes = this.volumes.filter(function(volume) { + share_map[volume.get('dest_dir')] = this.$('#' + volume.id).val(); + return volume; + }, this); + this.model.set('share_map', share_map); + return $.Deferred().resolve(); + }, + + initHandlebarHelpers: function(){ + Handlebars.registerHelper('display_volumesForm', function(){ + var html = ''; + var _this = this; + this.volumes.each(function(volume, index) { + html += '
'; + html += ''; + html += '
'; + html += ''; + html += '
'; + html += ''; + html += '
'; + }); + return new Handlebars.SafeString(html); + }); + } }); RockonPortChoice = RockstorWizardPage.extend({ - initialize: function() { - this.template = window.JST.rockons_port_choice; - this.port_template = window.JST.rockons_ports_form; - this.ports = this.model.get('ports'); - RockstorWizardPage.prototype.initialize.apply(this, arguments); - this.initHandlebarHelpers(); - }, - - render: function() { - RockstorWizardPage.prototype.render.apply(this, arguments); - this.$('#ph-ports-form').html(this.port_template({ports: this.ports})); - - // Add form validation - this.portForm = this.$('#port-select-form'); - var rules = {}; - var messages = {}; - this.ports.each(function(port) { - rules[port.id] = { required: true, number: true }; - messages[port.id] = "Please enter a valid port number"; - }); - this.validator = this.portForm.validate({ - rules: rules, - messages: messages - }); - return this; - }, - - save: function() { - - // Validate the form - if (!this.portForm.valid()) { - this.validator.showErrors(); - // return rejected promise so that the wizard doesn't proceed to the next page. - return $.Deferred().reject(); - } - - var port_map = {}; - var cports = this.ports.filter(function(port) { - port_map[this.$('#' + port.id).val()] = port.get('containerp'); - return port; - }, this); - this.model.set('port_map', port_map); - return $.Deferred().resolve(); - }, - - initHandlebarHelpers: function(){ - Handlebars.registerHelper('display_portsForm', function(){ - var html = ''; - this.ports.each(function(port, index) { - html += '
'; - html += ''; - html += '
'; - html += ''; - html += '
'; - html += ''; - html += '
'; - }); - return new Handlebars.SafeString(html); - }); + initialize: function() { + this.template = window.JST.rockons_port_choice; + this.port_template = window.JST.rockons_ports_form; + this.ports = this.model.get('ports'); + RockstorWizardPage.prototype.initialize.apply(this, arguments); + this.initHandlebarHelpers(); + }, + + render: function() { + RockstorWizardPage.prototype.render.apply(this, arguments); + this.$('#ph-ports-form').html(this.port_template({ports: this.ports})); + + // Add form validation + this.portForm = this.$('#port-select-form'); + var rules = {}; + var messages = {}; + this.ports.each(function(port) { + rules[port.id] = { required: true, number: true }; + messages[port.id] = "Please enter a valid port number"; + }); + this.validator = this.portForm.validate({ + rules: rules, + messages: messages + }); + return this; + }, + + save: function() { + + // Validate the form + if (!this.portForm.valid()) { + this.validator.showErrors(); + // return rejected promise so that the wizard doesn't proceed to the next page. + return $.Deferred().reject(); } + + var port_map = {}; + var cports = this.ports.filter(function(port) { + port_map[this.$('#' + port.id).val()] = port.get('containerp'); + return port; + }, this); + this.model.set('port_map', port_map); + return $.Deferred().resolve(); + }, + + initHandlebarHelpers: function(){ + Handlebars.registerHelper('display_portsForm', function(){ + var html = ''; + this.ports.each(function(port, index) { + html += '
'; + html += ''; + html += '
'; + html += ''; + html += '
'; + html += ''; + html += '
'; + }); + return new Handlebars.SafeString(html); + }); + } }); RockonCustomChoice = RockstorWizardPage.extend({ - initialize: function() { - this.template = window.JST.rockons_custom_choice; - this.cc_template = window.JST.rockons_cc_form; - this.custom_config = this.model.get('custom_config'); - RockstorWizardPage.prototype.initialize.apply(this, arguments); - this.initHandlebarHelpers(); - }, - - render: function() { - RockstorWizardPage.prototype.render.apply(this, arguments); - this.$('#ph-cc-form').html(this.cc_template({cc: this.custom_config})); - this.cc_form = this.$('#custom-choice-form'); - var rules = {}; - var messages = {}; - this.custom_config.each(function(cc) { - rules[cc.id] = "required"; - messages[cc.id] = "This is a required field."; - }); - this.validator = this.cc_form.validate({ - rules: rules, - messages: messages - }); - return this; - }, + initialize: function() { + this.template = window.JST.rockons_custom_choice; + this.cc_template = window.JST.rockons_cc_form; + this.custom_config = this.model.get('custom_config'); + RockstorWizardPage.prototype.initialize.apply(this, arguments); + this.initHandlebarHelpers(); + }, + + render: function() { + RockstorWizardPage.prototype.render.apply(this, arguments); + this.$('#ph-cc-form').html(this.cc_template({cc: this.custom_config})); + this.cc_form = this.$('#custom-choice-form'); + var rules = {}; + var messages = {}; + this.custom_config.each(function(cc) { + rules[cc.id] = "required"; + messages[cc.id] = "This is a required field."; + }); + this.validator = this.cc_form.validate({ + rules: rules, + messages: messages + }); + return this; + }, + + save: function() { + if (!this.cc_form.valid()) { + this.validator.showErrors(); + return $.Deferred().reject(); + } + var cc_map = {}; + var cconfigs = this.custom_config.filter(function(cc) { + cc_map[cc.get('key')] = this.$('#' + cc.id).val(); + return cc; + }, this); + this.model.set('cc_map', cc_map); + return $.Deferred().resolve(); + }, + + initHandlebarHelpers: function(){ + Handlebars.registerHelper('display_ccForm', function(){ + var html = ''; + this.cc.each(function(cci, index) { + html += '
'; + html += ''; + html += '
'; + html += '
'; + html += ''; + html += '
  '; + html += ''; + html += '
'; + html += '
'; + }); + return new Handlebars.SafeString(html); + }); + } +}); - save: function() { - if (!this.cc_form.valid()) { - this.validator.showErrors(); - return $.Deferred().reject(); - } - var cc_map = {}; - var cconfigs = this.custom_config.filter(function(cc) { - cc_map[cc.get('key')] = this.$('#' + cc.id).val(); - return cc; - }, this); - this.model.set('cc_map', cc_map); - return $.Deferred().resolve(); - }, - - initHandlebarHelpers: function(){ - Handlebars.registerHelper('display_ccForm', function(){ - var html = ''; - this.cc.each(function(cci, index) { - html += '
'; - html += ''; - html += '
'; - html += '
'; - html += ''; - html += '
  '; - html += ''; - html += '
'; - html += '
'; - }); - return new Handlebars.SafeString(html); - }); +RockonEnvironment = RockstorWizardPage.extend({ + initialize: function() { + this.template = window.JST.rockons_custom_choice; + this.cc_template = window.JST.rockons_cc_form; + this.custom_config = this.model.get('environment'); + RockstorWizardPage.prototype.initialize.apply(this, arguments); + this.initHandlebarHelpers(); + }, + + render: function() { + RockstorWizardPage.prototype.render.apply(this, arguments); + this.$('#ph-cc-form').html(this.cc_template({cc: this.custom_config})); + this.cc_form = this.$('#custom-choice-form'); + var rules = {}; + var messages = {}; + this.custom_config.each(function(cc) { + rules[cc.id] = "required"; + messages[cc.id] = "This is a required field."; + }); + this.validator = this.cc_form.validate({ + rules: rules, + messages: messages + }); + return this; + }, + + initHandlebarHelpers: function(){ + Handlebars.registerHelper('display_ccForm', function(){ + var html = ''; + this.cc.each(function(cci, index) { + html += '
'; + html += ''; + html += '
'; + html += '
'; + html += ''; + html += '
  '; + html += ''; + html += '
'; + html += '
'; + }); + return new Handlebars.SafeString(html); + }); + }, + + save: function() { + if (!this.cc_form.valid()) { + this.validator.showErrors(); + return $.Deferred().reject(); } + var env_map = {}; + var envars = this.custom_config.filter(function(cvar) { + env_map[cvar.get('key')] = this.$('#' + cvar.id).val(); + return cvar; + }, this); + this.model.set('env_map', env_map); + return $.Deferred().resolve(); + } }); RockonInstallSummary = RockstorWizardPage.extend({ - initialize: function() { - this.template = window.JST.rockons_install_summary; - this.table_template = window.JST.rockons_summary_table; - this.share_map = this.model.get('share_map'); - this.port_map = this.model.get('port_map'); - this.cc_map = this.model.get('cc_map'); - this.ports = this.model.get('ports'); - this.cc = this.model.get('custom_config'); - this.rockon = this.model.get('rockon'); - RockstorWizardPage.prototype.initialize.apply(this, arguments); - this.initHandlebarHelpers(); - }, - - render: function() { - RockstorWizardPage.prototype.render.apply(this, arguments); - this.$('#ph-summary-table').html(this.table_template({ - share_map: this.share_map, - port_map: this.port_map, - cc_map: this.cc_map})); - return this; - }, - - save: function() { - var _this = this; - //$('button#next-page').prop('disable', true); - document.getElementById('next-page').disabled = true; - return $.ajax({ - url: '/api/rockons/' + this.rockon.id + '/install', - type: 'POST', - dataType: 'json', - contentType: 'application/json', - data: JSON.stringify({ - 'ports': this.port_map, - 'shares': this.share_map, - 'cc': this.cc_map - }), - success: function() { - document.getElementById('next-page').disabled = false; - }, - error: function(request, status, error) { } - }); - }, - - initHandlebarHelpers: function(){ - Handlebars.registerHelper('display_rockonsSummary_table', function(){ - var html = ''; - for (s in this.share_map) { - html += ''; - html += 'Share'; - html += '' + this.share_map[s] + ''; - html += '' + s + ''; - html += ''; - } - for (p in this.port_map) { - html += ''; - html += 'Port'; - html += '' + this.port_map[p] + ''; - html += '' + p + ''; - html += ''; - } - for (c in this.cc_map) { - html += ''; - html += 'Custom'; - html += '' + this.cc_map[c] + ''; - html += '' + c + ''; - html += ''; - } - return new Handlebars.SafeString(html); - }); - } + initialize: function() { + this.template = window.JST.rockons_install_summary; + this.table_template = window.JST.rockons_summary_table; + this.share_map = this.model.get('share_map'); + this.port_map = this.model.get('port_map'); + this.cc_map = this.model.get('cc_map'); + this.env_map = this.model.get('env_map'); + this.ports = this.model.get('ports'); + this.environment = this.model.get('environment'); + this.cc = this.model.get('custom_config'); + this.rockon = this.model.get('rockon'); + RockstorWizardPage.prototype.initialize.apply(this, arguments); + this.initHandlebarHelpers(); + }, + + render: function() { + RockstorWizardPage.prototype.render.apply(this, arguments); + this.$('#ph-summary-table').html(this.table_template({ + share_map: this.share_map, + port_map: this.port_map, + cc_map: this.cc_map, + env_map: this.env_map})); + return this; + }, + + save: function() { + var _this = this; + //$('button#next-page').prop('disable', true); + document.getElementById('next-page').disabled = true; + return $.ajax({ + url: '/api/rockons/' + this.rockon.id + '/install', + type: 'POST', + dataType: 'json', + contentType: 'application/json', + data: JSON.stringify({ + 'ports': this.port_map, + 'shares': this.share_map, + 'cc': this.cc_map, + 'environment': this.env_map + }), + success: function() { + document.getElementById('next-page').disabled = false; + }, + error: function(request, status, error) { } + }); + }, + + initHandlebarHelpers: function(){ + Handlebars.registerHelper('display_rockonsSummary_table', function(){ + var html = ''; + for (s in this.share_map) { + html += ''; + html += 'Share'; + html += '' + this.share_map[s] + ''; + html += '' + s + ''; + html += ''; + } + for (p in this.port_map) { + html += ''; + html += 'Port'; + html += '' + this.port_map[p] + ''; + html += '' + p + ''; + html += ''; + } + for (c in this.cc_map) { + html += ''; + html += 'Custom'; + html += '' + this.cc_map[c] + ''; + html += '' + c + ''; + html += ''; + } + for (e in this.env_map) { + html += ''; + html += 'Env'; + html += '' + this.env_map[e] + ''; + html += '' + e + ''; + html += ''; + } + return new Handlebars.SafeString(html); + }); + } }); RockonInstallComplete = RockstorWizardPage.extend({ - initialize: function() { - this.template = window.JST.rockons_install_complete; - this.port_map = this.model.get('port_map'); - this.share_map = this.model.get('share_map'); - RockstorWizardPage.prototype.initialize.apply(this, arguments); - }, - - render: function() { - $(this.el).html(this.template({ - model: this.model, - port_map: this.port_map, - share_map: this.share_map - })); - return this; - } + initialize: function() { + this.template = window.JST.rockons_install_complete; + this.port_map = this.model.get('port_map'); + this.share_map = this.model.get('share_map'); + RockstorWizardPage.prototype.initialize.apply(this, arguments); + }, + + render: function() { + $(this.el).html(this.template({ + model: this.model, + port_map: this.port_map, + share_map: this.share_map + })); + return this; + } }); RockonInfoView = WizardView.extend({ - initialize: function() { - WizardView.prototype.initialize.apply(this, arguments); - this.pages = [RockonInfoSummary,]; - }, - - render: function() { - WizardView.prototype.render.apply(this, arguments); - return this; - }, - - modifyButtonText: function() { - this.$('#prev-page').hide(); - this.$('#next-page').hide(); - } + initialize: function() { + WizardView.prototype.initialize.apply(this, arguments); + this.pages = [RockonInfoSummary,]; + }, + + render: function() { + WizardView.prototype.render.apply(this, arguments); + return this; + }, + + modifyButtonText: function() { + this.$('#prev-page').hide(); + this.$('#next-page').hide(); + } }); RockonSettingsWizardView = WizardView.extend({ - initialize: function() { - WizardView.prototype.initialize.apply(this, arguments); - this.pages = [RockonSettingsSummary,]; - this.rockon = this.model.get('rockon'); - this.volumes = new RockOnVolumeCollection(null, {rid: this.rockon.id}); - this.ports = new RockOnPortCollection(null, {rid: this.rockon.id}); - this.custom_config = new RockOnCustomConfigCollection(null, {rid: this.rockon.id}); - this.shares = {}; - this.model.set('shares', this.shares); - }, - - fetchVolumes: function() { - var _this = this; - this.volumes.fetch({ - success: function () { - _this.model.set('volumes', _this.volumes); - _this.fetchPorts(); - } - }); - }, - - fetchPorts: function() { - var _this = this; - this.ports.fetch({ - success: function() { - _this.model.set('ports', _this.ports); - _this.fetchCustomConfig(); - } - }); - }, - - fetchCustomConfig: function() { - var _this = this; - this.custom_config.fetch({ - success: function() { - _this.model.set('custom_config', _this.custom_config); - _this.addPages(); - } - }); - }, - - render: function() { - this.fetchVolumes(); - return this; - }, - - addPages: function() { - if (this.rockon.get('volume_add_support')) { - this.pages.push.apply(this.pages, - [RockonAddShare, RockonSettingsSummary, - RockonSettingsComplete]); - } - WizardView.prototype.render.apply(this, arguments); - return this; - }, - - setCurrentPage: function() { - this.currentPage = new this.pages[this.currentPageNum]({ - model: this.model, - parent: this, - evAgg: this.evAgg - }); - }, - - modifyButtonText: function() { - if (this.currentPageNum == 0) { - this.$('#prev-page').hide(); - this.$('#next-page').html('Add Storage'); - if (!this.rockon.get('volume_add_support')) { - this.$('#next-page').hide(); - } - } else if (this.currentPageNum == (this.pages.length - 2)) { - this.$('#prev-page').html('Add Storage'); - this.$('#next-page').html('Next'); - } else if (this.currentPageNum == (this.pages.length - 1)) { - this.$('#prev-page').hide(); - this.$('#next-page').html('Submit'); - } else { - this.$('#prev-page').show(); - this.$('#next-page').html('Next'); - this.$('#ph-wizard-buttons').show(); - } - }, + initialize: function() { + WizardView.prototype.initialize.apply(this, arguments); + this.pages = [RockonSettingsSummary,]; + this.rockon = this.model.get('rockon'); + this.volumes = new RockOnVolumeCollection(null, {rid: this.rockon.id}); + this.ports = new RockOnPortCollection(null, {rid: this.rockon.id}); + this.custom_config = new RockOnCustomConfigCollection(null, {rid: this.rockon.id}); + this.environment = new RockOnEnvironmentCollection(null, {rid: this.rockon.id}); + this.shares = {}; + this.model.set('shares', this.shares); + }, + + fetchVolumes: function() { + var _this = this; + this.volumes.fetch({ + success: function () { + _this.model.set('volumes', _this.volumes); + _this.fetchPorts(); + } + }); + }, + + fetchPorts: function() { + var _this = this; + this.ports.fetch({ + success: function() { + _this.model.set('ports', _this.ports); + _this.fetchCustomConfig(); + } + }); + }, + + fetchCustomConfig: function() { + var _this = this; + this.custom_config.fetch({ + success: function() { + _this.model.set('custom_config', _this.custom_config); + _this.fetchEnvironment(); + } + }); + }, + + fetchEnvironment: function() { + var _this = this; + this.environment.fetch({ + success: function() { + _this.model.set('environment', _this.environment); + _this.addPages(); + } + }); + }, + + render: function() { + this.fetchVolumes(); + return this; + }, + + addPages: function() { + if (this.rockon.get('volume_add_support')) { + this.pages.push.apply(this.pages, + [RockonAddShare, RockonSettingsSummary, + RockonSettingsComplete]); + } + WizardView.prototype.render.apply(this, arguments); + return this; + }, + + setCurrentPage: function() { + this.currentPage = new this.pages[this.currentPageNum]({ + model: this.model, + parent: this, + evAgg: this.evAgg + }); + }, + + modifyButtonText: function() { + if (this.currentPageNum == 0) { + this.$('#prev-page').hide(); + this.$('#next-page').html('Add Storage'); + if (!this.rockon.get('volume_add_support')) { + this.$('#next-page').hide(); + } + } else if (this.currentPageNum == (this.pages.length - 2)) { + this.$('#prev-page').html('Add Storage'); + this.$('#next-page').html('Next'); + } else if (this.currentPageNum == (this.pages.length - 1)) { + this.$('#prev-page').hide(); + this.$('#next-page').html('Submit'); + } else { + this.$('#prev-page').show(); + this.$('#next-page').html('Next'); + this.$('#ph-wizard-buttons').show(); + } + }, - lastPage: function() { - return ((this.pages.length > 1) - && ((this.pages.length-1) == this.currentPageNum)); - }, + lastPage: function() { + return ((this.pages.length > 1) + && ((this.pages.length-1) == this.currentPageNum)); + }, - finish: function() { - this.parent.$('#install-rockon-overlay').overlay().close(); - this.parent.render(); - } + finish: function() { + this.parent.$('#install-rockon-overlay').overlay().close(); + this.parent.render(); + } }); RockonAddShare = RockstorWizardPage.extend({ - initialize: function() { - this.template = window.JST.rockons_add_shares; - this.sub_template = window.JST.rockons_add_shares_form; - this.shares = new ShareCollection(); - this.shares.setPageSize(100); - RockstorWizardPage.prototype.initialize.apply(this, arguments); - this.shares.on('reset', this.renderShares, this); - }, - - render: function() { - RockstorWizardPage.prototype.render.apply(this, arguments); - this.shares.fetch(); - return this; - }, - - renderShares: function() { - this.share_map = this.model.get('shares'); - this.volumes = this.model.get('volumes'); - this.used_shares = []; - var _this = this; - this.volumes.each(function(volume, index) { - _this.used_shares.push(volume.get('share_name')); - }); - for (var s in this.share_map) { - this.used_shares.push(s); - } - this.filtered_shares = this.shares.filter(function(share) { - if (_this.used_shares.indexOf(share.get('name')) == -1) { - return share; - } - }, this); - this.$('#ph-add-shares-form').html(this.sub_template({ - shares: this.filtered_shares - })); - this.share_form = this.$('#vol-select-form'); - this.validator = this.share_form.validate({ - rules: { "volume": "required", - "share": "required" }, - messages: { "volume": "Must be a valid unix path. Eg: /data/media", - "share": "Select an appropriate Share to map"} - }); - return this; - }, - - save: function() { - if (!this.share_form.valid()) { - this.validator.showErrors(); - return $.Deferred().reject(); - } - this.share_map = this.model.get('shares'); - this.share_map[this.$('#volume').val()] = this.$('#share').val(); - this.model.set('shares', this.share_map); - return $.Deferred().resolve(); + initialize: function() { + this.template = window.JST.rockons_add_shares; + this.sub_template = window.JST.rockons_add_shares_form; + this.shares = new ShareCollection(); + this.shares.setPageSize(100); + RockstorWizardPage.prototype.initialize.apply(this, arguments); + this.shares.on('reset', this.renderShares, this); + }, + + render: function() { + RockstorWizardPage.prototype.render.apply(this, arguments); + this.shares.fetch(); + return this; + }, + + renderShares: function() { + this.share_map = this.model.get('shares'); + this.volumes = this.model.get('volumes'); + this.used_shares = []; + var _this = this; + this.volumes.each(function(volume, index) { + _this.used_shares.push(volume.get('share_name')); + }); + for (var s in this.share_map) { + this.used_shares.push(s); } + this.filtered_shares = this.shares.filter(function(share) { + if (_this.used_shares.indexOf(share.get('name')) == -1) { + return share; + } + }, this); + this.$('#ph-add-shares-form').html(this.sub_template({ + shares: this.filtered_shares + })); + this.share_form = this.$('#vol-select-form'); + this.validator = this.share_form.validate({ + rules: { "volume": "required", + "share": "required" }, + messages: { "volume": "Must be a valid unix path. Eg: /data/media", + "share": "Select an appropriate Share to map"} + }); + return this; + }, + + save: function() { + if (!this.share_form.valid()) { + this.validator.showErrors(); + return $.Deferred().reject(); + } + this.share_map = this.model.get('shares'); + this.share_map[this.$('#volume').val()] = this.$('#share').val(); + this.model.set('shares', this.share_map); + return $.Deferred().resolve(); + } }); RockonInfoSummary = RockstorWizardPage.extend({ - initialize: function() { - this.template = window.JST.rockons_settings_summary; - this.sub_template = window.JST.rockons_more_info; - RockstorWizardPage.prototype.initialize.apply(this, arguments); - }, - - render: function() { - RockstorWizardPage.prototype.render.apply(this, arguments); - this.$('#ph-settings-summary-table').html(this.sub_template({ - rockonMoreInfo: this.model.get('more_info'), - - })); - return this; - } + initialize: function() { + this.template = window.JST.rockons_settings_summary; + this.sub_template = window.JST.rockons_more_info; + this.rockon = this.model.get('rockon'); + RockstorWizardPage.prototype.initialize.apply(this, arguments); + }, + + render: function() { + RockstorWizardPage.prototype.render.apply(this, arguments); + this.$('#ph-settings-summary-table').html(this.sub_template({ + rockonMoreInfo: this.rockon.get('more_info') + })); + return this; + } }); RockonSettingsSummary = RockstorWizardPage.extend({ - initialize: function() { - this.template = window.JST.rockons_settings_summary; - this.sub_template = window.JST.rockons_settings_summary_table; - this.rockon = this.model.get('rockon'); - RockstorWizardPage.prototype.initialize.apply(this, arguments); - this.initHandlebarHelpers(); - }, - - render: function() { - RockstorWizardPage.prototype.render.apply(this, arguments); - this.$('#ph-settings-summary-table').html(this.sub_template({ - model: this.model, - volumes: this.model.get('volumes'), - new_volumes: this.model.get('shares'), - ports: this.model.get('ports'), - cc: this.model.get('custom_config'), - rockon: this.model.get('rockon') - })); - return this; - }, - initHandlebarHelpers: function(){ - Handlebars.registerHelper('display_volumes', function(){ - var html = ''; - this.volumes.each(function(volume, index) { - html += ''; - html += 'Share'; - html += '' + volume.get('share_name') + ''; - html += '' + volume.get('dest_dir') + ''; - html += ''; - }); - return new Handlebars.SafeString(html); - }); - - Handlebars.registerHelper('display_newVolumes', function(){ - var html = ''; - for (share in this.new_volumes) { - html += ''; - html += 'Share'; - html += '' + this.new_volumes[share] + ''; - html += '' + share + ''; - html += ''; - } - return new Handlebars.SafeString(html); - }); - - Handlebars.registerHelper('display_ports', function(){ - var html = ''; - this.ports.each(function(port, index) { - html += ''; - html += 'Port'; - html += '' + port.get('hostp') + ''; - html += '' + port.get('containerp') + ''; - html += ''; - }); - return new Handlebars.SafeString(html); - }); - - Handlebars.registerHelper('display_cc', function(){ - var html = ''; - this.cc.each(function(cci, index) { - html += ''; - html += 'Custom'; - html += '' + cci.get('val') + '  '; - html += '' + cci.get('key') + ''; - html += ''; - }); - return new Handlebars.SafeString(html); - }); - - } + initialize: function() { + this.template = window.JST.rockons_settings_summary; + this.sub_template = window.JST.rockons_settings_summary_table; + this.rockon = this.model.get('rockon'); + RockstorWizardPage.prototype.initialize.apply(this, arguments); + this.initHandlebarHelpers(); + }, + + render: function() { + RockstorWizardPage.prototype.render.apply(this, arguments); + this.$('#ph-settings-summary-table').html(this.sub_template({ + model: this.model, + volumes: this.model.get('volumes'), + new_volumes: this.model.get('shares'), + ports: this.model.get('ports'), + cc: this.model.get('custom_config'), + env: this.model.get('environment'), + rockon: this.model.get('rockon') + })); + return this; + }, + initHandlebarHelpers: function(){ + Handlebars.registerHelper('display_volumes', function(){ + var html = ''; + this.volumes.each(function(volume, index) { + html += ''; + html += 'Share'; + html += '' + volume.get('share_name') + ''; + html += '' + volume.get('dest_dir') + ''; + html += ''; + }); + return new Handlebars.SafeString(html); + }); + + Handlebars.registerHelper('display_newVolumes', function(){ + var html = ''; + for (share in this.new_volumes) { + html += ''; + html += 'Share'; + html += '' + this.new_volumes[share] + ''; + html += '' + share + ''; + html += ''; + } + return new Handlebars.SafeString(html); + }); + + Handlebars.registerHelper('display_ports', function(){ + var html = ''; + this.ports.each(function(port, index) { + html += ''; + html += 'Port'; + html += '' + port.get('hostp') + ''; + html += '' + port.get('containerp') + ''; + html += ''; + }); + return new Handlebars.SafeString(html); + }); + + Handlebars.registerHelper('display_cc', function(){ + var html = ''; + this.cc.each(function(cci, index) { + html += ''; + html += 'Custom'; + html += '' + cci.get('val') + '  '; + html += '' + cci.get('key') + ''; + html += ''; + }); + //@todo: separate env and cc stuff. + this.env.each(function(envi, index) { + html += 'Env'; + html += '' + envi.get('val') + '  '; + html += '' + envi.get('key') + ''; + }); + return new Handlebars.SafeString(html); + }); + + } }); RockonSettingsComplete = RockstorWizardPage.extend({ - initialize: function() { - this.template = window.JST.rockons_update_complete; - this.rockon = this.model.get('rockon'); - this.shares = this.model.get('shares'); - RockstorWizardPage.prototype.initialize.apply(this, arguments); - }, - - render: function() { - $(this.el).html(this.template({ - model: this.model - })); - return this; - }, - - save: function() { - var _this = this; - if (document.getElementById('next-page').disabled) return false; - document.getElementById('next-page').disabled = true; - return $.ajax({ - url: '/api/rockons/' + this.rockon.id + '/update', - type: 'POST', - dataType: 'json', - contentType: 'application/json', - data: JSON.stringify({ - 'shares': this.shares - }), - success: function() {} - }); - } + initialize: function() { + this.template = window.JST.rockons_update_complete; + this.rockon = this.model.get('rockon'); + this.shares = this.model.get('shares'); + RockstorWizardPage.prototype.initialize.apply(this, arguments); + }, + + render: function() { + $(this.el).html(this.template({ + model: this.model + })); + return this; + }, + + save: function() { + var _this = this; + if (document.getElementById('next-page').disabled) return false; + document.getElementById('next-page').disabled = true; + return $.ajax({ + url: '/api/rockons/' + this.rockon.id + '/update', + type: 'POST', + dataType: 'json', + contentType: 'application/json', + data: JSON.stringify({ + 'shares': this.shares + }), + success: function() {} + }); + } }); diff --git a/src/rockstor/storageadmin/urls/rockons.py b/src/rockstor/storageadmin/urls/rockons.py index 44a3ecd91..0fcc34643 100644 --- a/src/rockstor/storageadmin/urls/rockons.py +++ b/src/rockstor/storageadmin/urls/rockons.py @@ -18,7 +18,8 @@ from django.conf.urls import patterns, url from storageadmin.views import (RockOnView, RockOnIdView, RockOnVolumeView, - RockOnPortView, RockOnCustomConfigView) + RockOnPortView, RockOnCustomConfigView, + RockOnEnvironmentView) urlpatterns = patterns( '', @@ -26,6 +27,7 @@ url(r'^/volumes/(?P\d+)$', RockOnVolumeView.as_view(), ), url(r'^/ports/(?P\d+)$', RockOnPortView.as_view(), ), url(r'^/customconfig/(?P\d+)$', RockOnCustomConfigView.as_view(), ), + url(r'^/environment/(?P\d+)$', RockOnEnvironmentView.as_view(), ), url(r'^/(?Pupdate)$', RockOnView.as_view(), ), url(r'^/(?P\d+)$', RockOnIdView.as_view(), ), url(r'^/(?P\d+)/(?Pinstall|uninstall|update|start|stop|state_update|status_update)$', diff --git a/src/rockstor/storageadmin/views/__init__.py b/src/rockstor/storageadmin/views/__init__.py index 88034ad37..89fed0751 100644 --- a/src/rockstor/storageadmin/views/__init__.py +++ b/src/rockstor/storageadmin/views/__init__.py @@ -47,6 +47,7 @@ from rockon_volume import RockOnVolumeView from rockon_port import RockOnPortView from rockon_custom_config import RockOnCustomConfigView +from rockon_environment import RockOnEnvironmentView from disk_smart import DiskSMARTDetailView from config_backup import (ConfigBackupListView, ConfigBackupDetailView, ConfigBackupUpload) diff --git a/src/rockstor/storageadmin/views/rockon.py b/src/rockstor/storageadmin/views/rockon.py index ecc7f271e..098d99c9c 100644 --- a/src/rockstor/storageadmin/views/rockon.py +++ b/src/rockstor/storageadmin/views/rockon.py @@ -21,7 +21,8 @@ from rest_framework.response import Response from django.db import transaction from storageadmin.models import (RockOn, DImage, DContainer, DPort, DVolume, - ContainerOption, DCustomConfig, DContainerLink) + ContainerOption, DCustomConfig, + DContainerLink, DContainerEnv) from storageadmin.serializers import RockOnSerializer from storageadmin.util import handle_exception import rest_framework_custom as rfc @@ -149,128 +150,139 @@ def _create_update_meta(self, name, r_d): if (not created): co.dimage = io co.launch_order = co_defaults['launch_order'] + if ('uid' in c_d): + co.uid = int(c_d['uid']) co.save() - ports = {} - if ('ports' in containers[c]): - ports = containers[c]['ports'] - for p in ports: - p_d = ports[p] - if ('protocol' not in p_d): - p_d['protocol'] = None - p = int(p) - po = None - if (DPort.objects.filter(containerp=p, container=co).exists()): - po = DPort.objects.get(containerp=p, container=co) - po.hostp_default = p_d['host_default'] - po.description = p_d['description'] - po.protocol = p_d['protocol'] - po.label = p_d['label'] - else: - #let's find next available default if default is already taken - def_hostp = p_d['host_default'] - while (True): - if (DPort.objects.filter(hostp=def_hostp).exists()): - def_hostp += 1 - else: - break - po = DPort(description=p_d['description'], - hostp=def_hostp, containerp=p, - hostp_default=def_hostp, - container=co, - protocol=p_d['protocol'], - label=p_d['label']) - if ('ui' in p_d): - po.uiport = p_d['ui'] - if (po.uiport): - ro.ui = True - ro.save() - po.save() + ports = containers[c].get('ports', {}) + for p in ports: + p_d = ports[p] + if ('protocol' not in p_d): + p_d['protocol'] = None + p = int(p) + po = None + if (DPort.objects.filter(containerp=p, container=co).exists()): + po = DPort.objects.get(containerp=p, container=co) + po.hostp_default = p_d['host_default'] + po.description = p_d['description'] + po.protocol = p_d['protocol'] + po.label = p_d['label'] + else: + #let's find next available default if default is already taken + def_hostp = p_d['host_default'] + while (True): + if (DPort.objects.filter(hostp=def_hostp).exists()): + def_hostp += 1 + else: + break + po = DPort(description=p_d['description'], + hostp=def_hostp, containerp=p, + hostp_default=def_hostp, + container=co, + protocol=p_d['protocol'], + label=p_d['label']) + if ('ui' in p_d): + po.uiport = p_d['ui'] + if (po.uiport): + ro.ui = True + ro.save() + po.save() ports = [int(p) for p in ports] for po in DPort.objects.filter(container=co): if (po.containerp not in ports): po.delete() - v_d = {} - if ('volumes' in c_d): - v_d = c_d['volumes'] - for v in v_d: - cv_d = v_d[v] - vo_defaults = {'description': cv_d['description'], - 'label': cv_d['label']} - vo, created = DVolume.objects.get_or_create(dest_dir=v, container=co, - defaults=vo_defaults) - if (not created): - vo.description = vo_defaults['description'] - vo.label = vo_defaults['label'] - if ('min_size' in cv_d): - vo.min_size = cv_d['min_size'] - vo.save() + v_d = c_d.get('volumes', {}) + for v in v_d: + cv_d = v_d[v] + vo_defaults = {'description': cv_d['description'], + 'label': cv_d['label']} + vo, created = DVolume.objects.get_or_create(dest_dir=v, container=co, + defaults=vo_defaults) + if (not created): + vo.description = vo_defaults['description'] + vo.label = vo_defaults['label'] + if ('min_size' in cv_d): + vo.min_size = cv_d['min_size'] + vo.save() for vo in DVolume.objects.filter(container=co): if (vo.dest_dir not in v_d): vo.delete() - if ('opts' in containers[c]): - options = containers[c]['opts'] - id_l = [] - for o in options: - #there are no unique constraints on this model, so we need this bandaid. - if (ContainerOption.objects.filter(container=co, name=o[0], val=o[1]).count() > 1): - ContainerOption.objects.filter(container=co, name=o[0], val=o[1]).delete() - oo, created = ContainerOption.objects.get_or_create(container=co, - name=o[0], - val=o[1]) - id_l.append(oo.id) - for oo in ContainerOption.objects.filter(container=co): - if (oo.id not in id_l): - oo.delete() + self._update_env(co, c_d) + options = containers[c].get('opts', []) + id_l = [] + for o in options: + #there are no unique constraints on this model, so we need this bandaid. + if (ContainerOption.objects.filter(container=co, name=o[0], val=o[1]).count() > 1): + ContainerOption.objects.filter(container=co, name=o[0], val=o[1]).delete() + oo, created = ContainerOption.objects.get_or_create(container=co, + name=o[0], + val=o[1]) + id_l.append(oo.id) + for oo in ContainerOption.objects.filter(container=co): + if (oo.id not in id_l): + oo.delete() - if ('container_links' in r_d): - l_d = r_d['container_links'] - for cname in l_d: - ll = l_d[cname] - lsources = [l['source_container'] for l in ll] - co = DContainer.objects.get(rockon=ro, name=cname) - for clo in co.destination_container.all(): - if (clo.name not in lsources): - clo.delete() - for cl_d in ll: - sco = DContainer.objects.get(rockon=ro, name=cl_d['source_container']) - clo, created = DContainerLink.objects.get_or_create(source=sco, - destination=co) - clo.name = cl_d['name'] - clo.save() + l_d = r_d.get('container_links', {}) + for cname in l_d: + ll = l_d[cname] + lsources = [l['source_container'] for l in ll] + co = DContainer.objects.get(rockon=ro, name=cname) + for clo in co.destination_container.all(): + if (clo.name not in lsources): + clo.delete() + for cl_d in ll: + sco = DContainer.objects.get(rockon=ro, name=cl_d['source_container']) + clo, created = DContainerLink.objects.get_or_create(source=sco, + destination=co) + clo.name = cl_d['name'] + clo.save() + self._update_cc(ro, r_d) - cc_d = {} - if ('custom_config' in r_d): - cc_d = r_d['custom_config'] - sorted_keys = [''] * len(cc_d.keys()) - for k in cc_d: - ccc_d = cc_d[k] - idx = ccc_d.get('index', 0) - if (idx == 0): - for i in range(len(sorted_keys)): - if (sorted_keys[i] == ''): - sorted_keys[i] = k - break - else: - sorted_keys[idx-1] = k - for k in sorted_keys: - ccc_d = cc_d[k] - cco, created = DCustomConfig.objects.get_or_create( - rockon=ro, key=k, - defaults={'description': ccc_d['description'], 'label': ccc_d['label']}) - if (not created): - cco.description = ccc_d['description'] - cco.label = ccc_d['label'] - cco.save() - def_val = ccc_d.get('default') - if (def_val is not None): - cco.val = def_val - cco.save() + + def _sorted_keys(self, cd): + sorted_keys = [''] * len(cd.keys()) + for k in cd: + ccd = cd[k] + idx = ccd.get('index', 0) + if (idx == 0): + for i in range(len(sorted_keys)): + if (sorted_keys[i] == ''): + sorted_keys[i] = k + break + else: + sorted_keys[idx-1] = k + return sorted_keys + + def _update_model(self, modelinst, ad): + for k,v in ad.iteritems(): + setattr(modelinst, k, v) + modelinst.save() + + def _update_cc(self, ro, r_d): + cc_d = r_d.get('custom_config', {}) + for k in self._sorted_keys(cc_d): + ccc_d = cc_d[k] + defaults = {'description': ccc_d['description'], + 'label': ccc_d['label'], } + cco, created = DCustomConfig.objects.get_or_create( + rockon=ro, key=k, defaults=defaults) + if (not created): self._update_model(cco, defaults) for cco in DCustomConfig.objects.filter(rockon=ro): - if (cco.key not in cc_d): - cco.delete() + if (cco.key not in cc_d): cco.delete() + + def _update_env(self, co, c_d): + cc_d = c_d.get('environment', {}) + for k in self._sorted_keys(cc_d): + ccc_d = cc_d[k] + defaults = {'description': ccc_d['description'], + 'label': ccc_d['label'], } + cco, created = DContainerEnv.objects.get_or_create( + container=co, key=k, defaults=defaults) + if (not created): self._update_model(cco, defaults) + for eo in DContainerEnv.objects.filter(container=co): + if (eo.key not in cc_d): eo.delete() def _get_available(self, request): msg = ('Network error while checking for updates. ' diff --git a/src/rockstor/storageadmin/views/rockon_environment.py b/src/rockstor/storageadmin/views/rockon_environment.py new file mode 100644 index 000000000..24048a376 --- /dev/null +++ b/src/rockstor/storageadmin/views/rockon_environment.py @@ -0,0 +1,36 @@ +""" +Copyright (c) 2012-2013 RockStor, Inc. +This file is part of RockStor. + +RockStor is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published +by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +RockStor is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +""" + +from storageadmin.models import (RockOn, DContainer, DContainerEnv) +from storageadmin.serializers import RockOnEnvironmentSerializer +import rest_framework_custom as rfc +from storageadmin.util import handle_exception + + +class RockOnEnvironmentView(rfc.GenericView): + serializer_class = RockOnEnvironmentSerializer + + def get_queryset(self, *args, **kwargs): + try: + rockon = RockOn.objects.get(id=self.kwargs['rid']) + except: + e_msg = ('Rock-on(%s) does not exist' % self.kwargs['rid']) + handle_exception(Exception(e_msg), self.request) + + containers = DContainer.objects.filter(rockon=rockon) + return DContainerEnv.objects.filter(container__in=containers).order_by('id') diff --git a/src/rockstor/storageadmin/views/rockon_helpers.py b/src/rockstor/storageadmin/views/rockon_helpers.py index ed44720fd..2dabcb822 100644 --- a/src/rockstor/storageadmin/views/rockon_helpers.py +++ b/src/rockstor/storageadmin/views/rockon_helpers.py @@ -29,7 +29,7 @@ from system.services import service_status from storageadmin.models import (RockOn, DContainer, DVolume, DPort, DCustomConfig, Share, Disk, DContainerLink, - ContainerOption) + ContainerOption, DContainerEnv) from fs.btrfs import mount_share from system.pkg_mgmt import install_pkg from rockon_utils import container_status @@ -183,15 +183,37 @@ def vol_ops(container): ops_list.extend(['-v', '%s:%s' % (share_mnt, v.dest_dir)]) return ops_list +def vol_owner_uid(container): + # If there are volumes, return the uid of the owner of the first volume. + vo = DVolume.objects.filter(container=container).first() + if (vo is None): return None + share_mnt = ('%s%s' % (settings.MNT_PT, vo.share.name)) + return os.stat(share_mnt).st_uid + +def envars(container): + var_list = [] + for e in DContainerEnv.objects.filter(container=container): + var_list.extend(['-e', '%s=%s' % (e.key, e.val)]) + return var_list + def generic_install(rockon): for c in DContainer.objects.filter(rockon=rockon).order_by('launch_order'): + rm_container(c.name) cmd = list(DCMD2) + ['--name', c.name,] cmd.extend(vol_ops(c)) + if (c.uid is not None): + uid = c.uid + if (c.uid is -1): + uid = vol_owner_uid(c) + #@todo: what if the uid does not exist? Create a user with username=container-name? + cmd.extend(['-u', str(uid)]) cmd.extend(port_ops(c)) cmd.extend(container_ops(c)) + cmd.extend(envars(c)) cmd.append(c.dimage.name) run_command(cmd) + def openvpn_install(rockon): #volume container vol_co = DContainer.objects.get(rockon=rockon, launch_order=1) @@ -214,23 +236,17 @@ def openvpn_install(rockon): run_command(server_cmd) -def transmission_install(rockon): - co = DContainer.objects.get(rockon=rockon, launch_order=1) - cmd = list(DCMD2) + ['--name', co.name] - for cco in DCustomConfig.objects.filter(rockon=rockon): - cmd.extend(['-e', '%s=%s' % (cco.key, cco.val)]) - cmd.extend(vol_ops(co)) - cmd.extend(port_ops(co)) - cmd.append(co.dimage.name) - run_command(cmd) - - def owncloud_install(rockon): for c in DContainer.objects.filter(rockon=rockon).order_by('launch_order'): + rm_container(c.name) cmd = list(DCMD2) + ['--name', c.name, ] db_user = DCustomConfig.objects.get(rockon=rockon, key='db_user').val db_pw = DCustomConfig.objects.get(rockon=rockon, key='db_pw').val if (c.dimage.name == 'postgres'): + #change permissions on the db volume to 700 + vo = DVolume.objects.get(container=c) + share_mnt = ('%s%s' % (settings.MNT_PT, vo.share.name)) + run_command(['/usr/bin/chmod', '700', share_mnt]) cmd.extend(['-e', 'POSTGRES_USER=%s' % db_user, '-e', 'POSTGRES_PASSWORD=%s' % db_pw]) cmd.extend(port_ops(c)) diff --git a/src/rockstor/storageadmin/views/rockon_id.py b/src/rockstor/storageadmin/views/rockon_id.py index e8b427715..336f482b0 100644 --- a/src/rockstor/storageadmin/views/rockon_id.py +++ b/src/rockstor/storageadmin/views/rockon_id.py @@ -21,7 +21,7 @@ from django.db import transaction from django.db.models import Q from storageadmin.models import (RockOn, DContainer, DVolume, Share, DPort, - DCustomConfig) + DCustomConfig, DContainerEnv) from storageadmin.serializers import RockOnSerializer import rest_framework_custom as rfc from storageadmin.util import handle_exception @@ -82,6 +82,7 @@ def post(self, request, rid, command): share_map = request.data.get('shares', {}) port_map = request.data.get('ports', {}) cc_map = request.data.get('cc', {}) + env_map = request.data.get('environment', {}) containers = DContainer.objects.filter(rockon=rockon) for co in containers: for s in share_map.keys(): @@ -118,6 +119,13 @@ def post(self, request, rid, command): cco = DCustomConfig.objects.get(rockon=rockon, key=c) cco.val = cc_map[c] cco.save() + for e in env_map.keys(): + if (not DContainerEnv.objects.filter(container=co, key=e).exists()): + e_msg = ('Invalid environment variabled(%s)' % e) + handle_exception(Exception(e_msg), request) + ceo = DContainerEnv.objects.get(container=co, key=e) + ceo.val = env_map[e] + ceo.save() install.async(rockon.id) rockon.state = 'pending_install' rockon.save()