Commit 9ab17d5f by Sulyok Gábor

Commit previous changes for Setty

parent 39a7ffc9
Pipeline #225 failed with stage
in 0 seconds
......@@ -17,13 +17,21 @@
from django.contrib import admin
from .models import (
Element,
Service,
ElementCategory,
ElementTemplate,
ElementConnection,
Service,
Machine,
NginxNode,
MySQLNode,
PostgreSQLNode
)
admin.site.register(Element)
admin.site.register(ElementCategory)
admin.site.register(ElementTemplate)
admin.site.register(ElementConnection)
admin.site.register(Service)
admin.site.register(Machine)
admin.site.register(NginxNode)
admin.site.register(MySQLNode)
admin.site.register(PostgreSQLNode)
from .models import *
from django.core.exceptions import PermissionDenied
from django.db.models import Q
from django.db.models.loading import get_model
from saltstackhelper import *
import os
class SettyController:
salthelper = SaltStackHelper()
@staticmethod
def saveService( serviceId, serviceName, serviceNodes, machines, elementConnections ):
service = None
try:
service = Service.objects.get(id=serviceId)
except Service.DoesNotExist:
return JsonResponse( {'error': 'Service not found'})
service.name = serviceName
service.save()
#first check machine names
#validMachineNames = self.salthelper.getAllMinionsUngrouped()
Machine.objects.filter(service=service).delete()
for machineData in machines:
# if machineData["hostname"] in validMachineNames:
machineSaved = Machine(service=service)
machineSaved.fromDataDictionary( machineData )
machineSaved.save()
ServiceNode.objects.filter(service=service).delete()
for node in serviceNodes:
elementTemplateId = node["displayId"].split("_")[0]
elementTemplate = ElementTemplate.objects.get(id=elementTemplateId)
newNode = get_model('setty', elementTemplate.prototype ).clone()
newNode.service = service
newNode.fromDataDictionary( node )
newNode.save()
for elementConnection in elementConnections:
sourceId = elementConnection['sourceId']
targetId = elementConnection['targetId']
sourceEndpoint = elementConnection['sourceEndpoint']
targetEndpoint = elementConnection['targetEndpoint']
connectionParameters = elementConnection['parameters']
targetObject = Element.objects.get(
display_id=targetId)
sourceObject = Element.objects.get(
display_id=sourceId)
connectionObject = ElementConnection(
target=targetObject,
source=sourceObject,
target_endpoint=targetEndpoint,
source_endpoint=sourceEndpoint,
parameters=connectionParameters
)
connectionObject.save()
return {"serviceName": serviceName}
@staticmethod
def loadService(serviceId):
service = None
try:
service = Service.objects.get(id=serviceId)
except Service.DoesNotExist:
return JsonResponse({'error': 'Service not found'})
machineList = Machine.objects.filter(service=service)
serviceNodes = []
elementConnections = []
machines = []
for machine in machineList:
machines.append(machine.getDataDictionary())
serviveNodeList = ServiceNode.objects.filter(service=service)
elementConnectionList = ElementConnection.objects.filter(
Q(target__in=serviveNodeList) | Q(source__in=serviveNodeList))
for servideNode in serviveNodeList:
serviceNodes.append( servideNode.cast().getDataDictionary() )
for elementConnection in elementConnectionList:
elementConnections.append( elementConnection.getDataDictionary() )
return {'serviceName': service.name,
'elementConnections': elementConnections,
'serviceNodes': serviceNodes,
'machines': machines}
@staticmethod
def getInformation(elementTemplateId, hostname):
if elementTemplateId:
try:
elementTemplate = ElementTemplate.objects.get(
id=elementTemplateId)
model = get_model('setty', elementTemplate.prototype)
return model.getInformation()
except ElementTemplate.DoesNotExist:
return
except LookupError:
return
elif hostname:
return Machine.getInformation()
elif hostname and elementTemplateId:
raise PermissionDenied # TODO: something more meaningful
else:
raise PermissionDenied # TODO: something more meaningful
@staticmethod
def getMachineAvailableList(service_id, used_hostnames):
all_minions = SettyController.salthelper.getAllMinionsGrouped()
result = []
#TODO: filter out used ones
for item in all_minions["up"]:
result.append( {'hostname': item,
'hardware-info': SettyController.salthelper.getMinionBasicHardwareInfo( item ),
'status': 'up'} )
for item in all_minions["down"]:
result.append( {'hostname': item, 'status': 'down' })
return { 'machinedata': result }
@staticmethod
def addMachine(hostname):
try:
Machine.objects.get(hostname=hostname)
return {'error': 'already added or doesnt exists'}
except:
pass
if SettyController.salthelper.checkMinionExists(hostname):
machine = Machine.clone()
machine.hostname = hostname
return machine.getDataDictionary()
else:
return {'error': 'already added or doesnt exists'}
@staticmethod
def addServiceNode(elementTemplateId):
if elementTemplateId:
try:
elementTemplate = ElementTemplate.objects.get(id=elementTemplateId)
model = get_model('setty', elementTemplate.prototype )
return model.clone().getDataDictionary()
except ElementTemplate.DoesNotExist:
return {'error': 'lofaszka' }
except:
return {'error': 'valami nagyon el lett baszva'}
else:
return {'error': 'templateid'}
@staticmethod
def deploy(serviceId):
service = Service.objects.get(id=serviceId)
machines = Machine.objects.filter(service=service)
elementConnections = ElementConnection.objects.filter(
Q(target__in=machines) | Q(source__in=machines) )
firstLevelServiceNodes = []
#phase one: set the machine ptr in serviceNodes which can be accessed by
# connections from machines
for machine in machines:
for connection in elementConnections:
serviceNode = None
if connection.target.cast() == machine:
serviceNode = connection.source.cast()
serviceNode.setMachineForDeploy( machine )
elif connection.source.cast() == machine:
serviceNode = connection.target.cast()
serviceNode.setMachineForDeploy( machine )
else:
raise PermissionDenied
firstLevelServiceNodes.append( serviceNode )
#phase two: let the nodes create configurations recursively
configuratedNodes = list()
for serviceNode in firstLevelServiceNodes:
generatedNodes = serviceNode.generateConfigurationRecursively()
if isinstance( generatedNodes, list ):
configuratedNodes = configuratedNodes + generatedNodes
else:
configuratedNodes.append( generatedNodes )
#phase three: sort the nodes by deployment priority(lower the prio, later in the deployement)
configuratedNodes.sort(reverse=True)
#deploy the nodes
for node in configuratedNodes:
SettyController.salthelper.deploy( node.machine.hostname, node.generatedConfig )
return {'status': 'deployed'}
#cleanup the temporary data
''' for node in configuratedNodes:
node.deployCleanUp()'''
\ No newline at end of file
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
import setty.storage
class Migration(migrations.Migration):
dependencies = [
('setty', '0012_auto_20160308_1432'),
]
operations = [
migrations.CreateModel(
name='ElementCategory',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('name', models.CharField(max_length=50)),
('parent_category', models.ForeignKey(to='setty.ElementCategory', null=True)),
],
),
migrations.CreateModel(
name='Machine',
fields=[
('element_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, to='setty.Element')),
('hostname', models.TextField()),
('alias', models.CharField(max_length=50)),
('config_file', models.FileField(default=None, storage=setty.storage.OverwriteStorage(), upload_to=b'setty/machine_configs/')),
('description', models.TextField(default=b'')),
('status', models.CharField(max_length=1, choices=[(1, b'Running'), (2, b'Unreachable')])),
],
options={
'abstract': False,
},
bases=('setty.element',),
),
migrations.CreateModel(
name='ServiceNode',
fields=[
('element_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, to='setty.Element')),
('name', models.CharField(max_length=50)),
('config_file', models.FileField(default=None, storage=setty.storage.OverwriteStorage(), upload_to=b'setty/node_configs/')),
('description', models.TextField(default=b'')),
('machine', models.ForeignKey(to='setty.Machine')),
],
bases=('setty.element',),
),
migrations.RemoveField(
model_name='element',
name='parameters',
),
migrations.RemoveField(
model_name='element',
name='service',
),
migrations.RemoveField(
model_name='elementtemplate',
name='parameters',
),
migrations.AlterField(
model_name='service',
name='status',
field=models.CharField(default=1, max_length=1, choices=[(1, b'Draft'), (2, b'Deployed')]),
),
migrations.AddField(
model_name='machine',
name='service',
field=models.ForeignKey(related_name='service_id', to='setty.Service'),
),
migrations.AddField(
model_name='elementtemplate',
name='category',
field=models.ForeignKey(to='setty.ElementCategory', null=True),
),
]
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('setty', '0013_saltstack_changes'),
]
operations = [
migrations.CreateModel(
name='NginxNode',
fields=[
('servicenode_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, to='setty.ServiceNode')),
('worker_connections', models.PositiveIntegerField()),
],
bases=('setty.servicenode',),
),
migrations.CreateModel(
name='WebServerNode',
fields=[
('servicenode_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, to='setty.ServiceNode')),
('useSSL', models.BooleanField(default=False)),
('listeningPort', models.PositiveIntegerField()),
],
bases=('setty.servicenode',),
),
migrations.RemoveField(
model_name='elementtemplate',
name='tags',
),
]
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('setty', '0014_auto_20160320_1724'),
]
operations = [
migrations.AlterField(
model_name='elementcategory',
name='parent_category',
field=models.ForeignKey(blank=True, to='setty.ElementCategory', null=True),
),
]
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
import setty.storage
class Migration(migrations.Migration):
dependencies = [
('setty', '0015_allow_blank_elementcategory_parent'),
]
operations = [
migrations.AddField(
model_name='elementtemplate',
name='prototype',
field=models.TextField(default=b'<SYNTAX ERROR>'),
),
migrations.AlterField(
model_name='elementtemplate',
name='compatibles',
field=models.ManyToManyField(related_name='compatibles_rel_+', to='setty.ElementTemplate', blank=True),
),
migrations.AlterField(
model_name='elementtemplate',
name='logo',
field=models.FileField(storage=setty.storage.OverwriteStorage(), upload_to=b'setty/', blank=True),
),
]
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
import setty.storage
class Migration(migrations.Migration):
dependencies = [
('setty', '0016_auto_20160320_1753'),
]
operations = [
migrations.RemoveField(
model_name='nginxnode',
name='servicenode_ptr',
),
migrations.AddField(
model_name='nginxnode',
name='webservernode_ptr',
field=models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, default=None, serialize=False, to='setty.WebServerNode'),
preserve_default=False,
),
migrations.AlterField(
model_name='elementtemplate',
name='logo',
field=models.FileField(storage=setty.storage.OverwriteStorage(), upload_to=b'setty/'),
),
]
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('setty', '0017_auto_20160320_1828'),
]
operations = [
migrations.RemoveField(
model_name='servicenode',
name='machine',
),
migrations.AddField(
model_name='servicenode',
name='service',
field=models.ForeignKey(default=None, to='setty.Service'),
),
]
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('setty', '0018_auto_20160420_1728'),
]
operations = [
migrations.AlterField(
model_name='servicenode',
name='service',
field=models.ForeignKey(related_name='node_service_id', default=None, to='setty.Service'),
),
]
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('setty', '0019_auto_20160420_2043'),
]
operations = [
migrations.AlterField(
model_name='servicenode',
name='service',
field=models.ForeignKey(default=None, to='setty.Service'),
),
]
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('contenttypes', '0002_remove_content_type_name'),
('setty', '0020_auto_20160420_2132'),
]
operations = [
migrations.AddField(
model_name='element',
name='real_type',
field=models.ForeignKey(default=None, editable=False, to='contenttypes.ContentType'),
),
]
......@@ -17,46 +17,101 @@
from django.db import models
from django.db.models import Model
from django.contrib.contenttypes.models import ContentType
from django.contrib.auth.models import User
from taggit.managers import TaggableManager
from django.utils.translation import ugettext_lazy as _
from storage import OverwriteStorage
import os
# TODO: derive from object or keep the tricky base function calling?
# TODO: exceptions
SALTSTACK_STATE_FOLDER = "/srv/salt"
def replaceParameter(config, parameterToReplace, newValue):
configEdited = config.replace(parameterToReplace, str(newValue))
return configEdited
class Service(models.Model):
SERVICE_STATUS_CHOICES = ((1, 'Draft'),
(2, 'Deployed'))
class Service(Model):
user = models.ForeignKey(User)
name = models.TextField(verbose_name="Name")
status = models.CharField(max_length=50)
status = models.CharField(
choices=SERVICE_STATUS_CHOICES, max_length=1, default=1)
def __unicode__(self):
return self.name
class ElementTemplate(Model):
class ElementCategory(models.Model):
name = models.CharField(max_length=50)
parent_category = models.ForeignKey(
'self', on_delete=models.CASCADE, null=True, blank=True)
def __unicode__(self):
return self.name
class ElementTemplate(models.Model):
name = models.CharField(max_length=50)
logo = models.FileField(upload_to='setty/', storage=OverwriteStorage())
description = models.TextField()
parameters = models.TextField()
compatibles = models.ManyToManyField('self')
tags = TaggableManager(blank=True, verbose_name=_("tags"))
compatibles = models.ManyToManyField('self', blank=True)
category = models.ForeignKey(
ElementCategory, on_delete=models.CASCADE, null=True)
prototype = models.TextField(default="<SYNTAX ERROR>")
def __unicode__(self):
return self.name
# http://stackoverflow.com/questions/929029/how-do-i-access-the-child-classes-of-an-object-in-django-without-knowing-the-name/929982#929982
# Super base class to prevent messing the code in the controller
# it saves the type info to DB, and when the objects are queried, the cast method returns the real class
# not the base
class Element(Model):
service = models.ForeignKey(Service, on_delete=models.CASCADE)
parameters = models.TextField()
class InheritanceCastModel(models.Model):
real_type = models.ForeignKey(ContentType, editable=False, default=None)
def save(self, *args, **kwargs):
if not self.id:
self.real_type = self._get_real_type()
super(InheritanceCastModel, self).save(*args, **kwargs)
def _get_real_type(self):
return ContentType.objects.get_for_model(type(self))
def cast(self):
return self.real_type.get_object_for_this_type(pk=self.pk)
class Meta:
abstract = True
class Element(InheritanceCastModel):
display_id = models.TextField()
position_left = models.FloatField()
position_top = models.FloatField()
anchor_number = models.PositiveSmallIntegerField()
def __unicode__(self):
return "%s (%s)" % (self.service.name, self.display_id)
def getDisplayData(self):
return {'displayId': self.display_id,
'positionLeft': self.position_left,
'positionTop': self.position_top,
'anchorNumber': self.anchor_number}
def setDisplayData(self, data):
self.display_id = data["displayId"]
self.position_left = data["positionLeft"]
self.position_top = data["positionTop"]
self.anchor_number = data["anchorNumber"]
class ElementConnection(Model):
class ElementConnection(models.Model):
target = models.ForeignKey(
Element,
related_name='target',
......@@ -70,4 +125,265 @@ class ElementConnection(Model):
parameters = models.TextField()
def __unicode__(self):
return "%s (%d)" % (self.target.service.name, self.id)
return "%d" % self.id
def getDataDictionary(self):
return {'targetEndpoint': self.target_endpoint,
'sourceEndpoint': self.source_endpoint,
'parameters': self.parameters}
class Machine(Element): # As a real machine
MACHINE_STATUS_CHOICES = (
(1, 'Running'),
(2, 'Unreachable'))
service = models.ForeignKey(
Service, on_delete=models.CASCADE, related_name="service_id")
hostname = models.TextField(null=False) # also serves as salt-minion id
alias = models.CharField(max_length=50)
#config_file = models.FileField(default=None,upload_to='setty/machine_configs/', storage=OverwriteStorage())
description = models.TextField(default="")
status = models.CharField(choices=MACHINE_STATUS_CHOICES, max_length=1)
def __unicode__(self):
return "%s" % self.hostname
@staticmethod
def getInformation():
return {'hostname': hostname.get_internal_type(),
'alias': alias.get_internal_type(),
'description': description.get_internal_type()}
def getDataDictionary(self):
element_data = self.getDisplayData()
self_data = {'hostname': self.hostname,
'alias': self.alias,
'description': self.description}
element_data.update(self_data)
return element_data
def fromDataDictionary(self, data):
self.setDisplayData(data)
self.hostname = data["hostname"]
self.alias = data["alias"]
self.description = data["description"]
@staticmethod
def clone():
return Machine()
class ServiceNode(Element):
service = models.ForeignKey(
Service, on_delete=models.CASCADE, default=None)
name = models.CharField(max_length=50)
config_file = models.FileField(
default=None, upload_to='setty/node_configs/', storage=OverwriteStorage())
description = models.TextField(default="")
machine = None # for deploying
generatedConfig = None
def __unicode__(self):
return "%s" % self.name
def getDataDictionary(self):
element_data = self.getDisplayData()
self_data = {'name': self.name,
'description': self.description}
element_data.update(self_data)
return element_data
def fromDataDictionary(self, data):
self.setDisplayData(data)
self.name = data['name']
self.description = data['description']
@staticmethod
def getInformation():
return {'name': ServiceNode._meta.get_field('name').get_internal_type(),
'description': ServiceNode._meta.get_field('description').get_internal_type()}
@staticmethod
def clone():
raise PermissionDenied
def __cmp__(self, other):
return self.getDeploymentPriority(self).__cmp__(other.getDeploymentPriority(other))
# functions for deployement
def setMachineForDeploy(self, machine):
self.machine = machine
def getDeploymentPriority(self):
return 0
def generateConfigurationRecursively(self):
raise PermissionDenied
class WebServerNode(ServiceNode):
useSSL = models.BooleanField(default=False)
listeningPort = models.PositiveIntegerField()
def getDataDictionary(self):
element_data = ServiceNode.getDataDictionary(self)
self_data = {'useSSL': self.useSSL,
'listeningPort': self.listeningPort}
element_data.update(self_data)
return element_data
def fromDataDictionary(self, data):
ServiceNode.fromDataDictionary(self, data)
self.useSSL = data['useSSL']
self.listeningPort = data['listeningPort']
@staticmethod
def getInformation():
superInformation = ServiceNode.getInformation()
ownInformation = {'useSSL': WebServerNode._meta.get_field('useSSL').get_internal_type(),
'listeningPort': WebServerNode._meta.get_field('listeningPort').get_internal_type()}
ownInformation.update(superInformation)
return ownInformation
@staticmethod
def getDeploymentPriority(self):
return 10
def generateConfiguration(self, config=""):
config = replaceParameter(config, r"%%USE_SSL%%", self.useSSL)
config = replaceParameter(config,
r"%%LISTENING_PORT%%", self.listeningPort)
return config
class NginxNode(WebServerNode):
worker_connections = models.PositiveIntegerField()
def getDataDictionary(self):
element_data = WebServerNode.getDataDictionary(self)
self_data = {'worker_connections': self.worker_connections}
element_data.update(self_data)
return element_data
def fromDataDictionary(self, data):
WebServerNode.fromDataDictionary(self, data)
self.worker_connections = data['worker_connections']
@staticmethod
def getInformation():
superInformation = WebServerNode.getInformation()
ownInformation = {'worker_connections': NginxNode._meta.get_field(
'worker_connections').get_internal_type()}
ownInformation.update(superInformation)
return ownInformation
@staticmethod
def clone():
return NginxNode()
def generateConfigurationRecursively(self):
config = str()
exampleFilePath = os.path.join( SALTSTACK_STATE_FOLDER, "nginx.example" )
with open(exampleFilePath, 'r') as configFile:
config = configFile.read()
config = WebServerNode.generateConfiguration(self, config)
config = replaceParameter(config,
r"%%WORKER_CONNECTIONS%%", self.worker_connections)
self.generatedConfig = "nginx_%s.sls" % self.machine.hostname
with open(os.path.join(SALTSTACK_STATE_FOLDER, self.generatedConfig), 'w') as generatedConfigFile:
generatedConfigFile.write(config)
configuredNodes = []
configuredNodes.append(self)
return configuredNodes
class DatabaseNode(ServiceNode):
adminUserName = models.CharField(max_length=50)
adminPassword = models.CharField(max_length=50)
listeningPort = models.PositiveIntegerField()
def getDataDictionary(self):
element_data = ServiceNode.getDataDictionary(self)
self_data = {'admin_username': self.adminUserName,
'admin_password': self.adminPassword, 'listeningPort': self.listeningPort}
element_data.update(self_data)
return element_data
def fromDataDictionary(self, data):
ServiceNode.fromDataDictionary(self, data)
self.adminUserName = data['admin_username']
self.adminPassword = data['admin_password']
self.listeningPort = data['listeningPort']
@staticmethod
def getInformation():
superInformation = ServiceNode.getInformation()
ownInformation = {'admin_username': DatabaseNode._meta.get_field('adminUserName').get_internal_type(),
'admin_password': DatabaseNode._meta.get_field('adminPassword').get_internal_type(),
'listeningPort': DatabaseNode._meta.get_field('listeningPort').get_internal_type()}
ownInformation.update(superInformation)
return ownInformation
@staticmethod
def getDeploymentPriority(self):
return 10
def generateConfiguration(self, config=""):
config = replaceParameter(config,
r"%%ADMIN_USERNAME%%", self.adminUserName)
config = replaceParameter(config,
r"%%ADMIN_PASSWORD%%", self.adminUserName)
config = replaceParameter(config,
r'%%LISTENING_PORT%%', self.listeningPort)
return config
class PostgreSQLNode(DatabaseNode):
@staticmethod
def clone():
return PostgreSQLNode()
def generateConfigurationRecursively(self):
config = str()
exampleFilePath = os.path.join( SALTSTACK_STATE_FOLDER, "postgres.example" )
with open( exampleFilePath, 'r') as configFile:
config = configFile.read()
config = DatabaseNode.generateConfiguration(self, config)
self.generatedConfig = "postgres_%s.sls" % self.machine.hostname
with open(os.path.join(SALTSTACK_STATE_FOLDER, self.generatedConfig), 'w') as generatedConfigFile:
generatedConfigFile.write(config)
return self
class MySQLNode(DatabaseNode):
@staticmethod
def clone():
return MySQLNode()
def generateConfigurationRecursively(self):
config = str()
exampleFilePath = os.path.join( SALTSTACK_STATE_FOLDER, "mysql.example" )
with open(exampleFilePath, 'r') as configFile:
config = configFile.read()
config = DatabaseNode.generateConfiguration(self, config)
self.generatedConfig = "mysql_%s.sls" % self.machine.hostname
with open(os.path.join(SALTSTACK_STATE_FOLDER, self.generatedConfig), 'w') as generatedConfigFile:
generatedConfigFile.write(config)
return self
import salt.loader
import salt.config
import salt.runner
import salt.client
SALTSTACK_STATE_FOLDER = "/srv/salt"
class SaltStackHelper:
def __init__(self):
self.master_opts = salt.config.client_config('/etc/salt/master')
self.salt_runner = salt.runner.RunnerClient(self.master_opts)
self.salt_localclient = salt.client.LocalClient()
self.salt_caller = salt.client.Caller()
def getAllMinionsGrouped(self):
query_result = self.salt_runner.cmd('manage.status', []);
return query_result
def getAllMinionsUngrouped(self):
query_result = self.salt_runner.cmd('manage.status', []);
return query_result["up"] + query_result["down"]
def getRunningMinions(self):
return self.salt_runner.cmd('manage.up', []);
def getUnavailableMinions(self):
return self.salt_runner.cmd('manage.down', []);
def getMinionBasicHardwareInfo(self, hostname):
query_res = self.salt_localclient.cmd( hostname,'grains.items' );
if query_res:
return {
'CpuModel': query_res[hostname]['cpu_model'],
'CpuArch': query_res[hostname]['cpuarch'],
'TotalMemory': query_res[hostname]['mem_total'],
'OSDescription': query_res[hostname]['lsb_distrib_description'] }
return query_res
def checkMinionExists(self, hostname):
query_res = self.salt_localclient.cmd( hostname,'network.get_hostname' );
return query_res != None
def deploy(self, hostname, configFilePath ):
print configFilePath
self.salt_localclient.cmd(hostname, 'state.apply', [configFilePath.split('.')[0]] )
\ No newline at end of file

15.9 KB | W: | H:

15.9 KB | W: | H:

circle/setty/static/setty/apache.jpg
circle/setty/static/setty/apache.jpg
circle/setty/static/setty/apache.jpg
circle/setty/static/setty/apache.jpg
  • 2-up
  • Swipe
  • Onion skin

18.4 KB | W: | H:

18.4 KB | W: | H:

circle/setty/static/setty/lighttpd.jpg
circle/setty/static/setty/lighttpd.jpg
circle/setty/static/setty/lighttpd.jpg
circle/setty/static/setty/lighttpd.jpg
  • 2-up
  • Swipe
  • Onion skin

6.02 KB | W: | H:

6.02 KB | W: | H:

circle/setty/static/setty/nginx.jpg
circle/setty/static/setty/nginx.jpg
circle/setty/static/setty/nginx.jpg
circle/setty/static/setty/nginx.jpg
  • 2-up
  • Swipe
  • Onion skin
/* Settimng up csrf token, touch event and zoom options. */
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie !== '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
if (cookie.substring(0, name.length + 1) == (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
function csrfSafeMethod(method) {
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
var csrftoken = getCookie('csrftoken');
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});
/* Setty implementation starts here. */
jsPlumb.ready(function() {
var jsPlumbInstance = jsPlumb.getInstance({
DragOptions: {
zIndex: 2000
},
EndpointHoverStyle: {
fillStyle: "green"
},
HoverPaintStyle: {
strokeStyle: "green"
},
Container: "dropContainer"
});
var jsPlumbEndpoint = {
endpoint: ["Dot", {
radius: 10
}],
paintStyle: {
fillStyle: "#9932cc"
},
isSource: true,
isTarget: true,
deleteEndpointsOnDetach: false,
zIndex: 20,
connectorStyle: {
strokeStyle: "#9932cc",
lineWidth: 8
},
connector: ["Bezier", {
curviness: 180
}],
maxConnections: 1,
dropOptions: {
tolerance: "fit"
}
};
var elementConnections = [];
var elementIndex = 0;
var dragContainerScroll = 0;
var workspaceWidth = $("#dropContainer").width();
var workspaceHeight = $("#dropContainer").height();
var stackIndexer = 0;
var stackSize = 0;
var objectStack = [];
var undoStack = [];
var redoStack = [];
var clickEvent = 0;
var nextStepConstraint = 0;
/* Functions. */
setServiceStatus = function(status) {
if (status == "unsaved") {
$("#serviceStatus").text(gettext("Unsaved"));
} else {
$("#serviceStatus").empty();
}
};
addInfo = function(title, info, object, type) {
mainDiv = $("<div>", {
class: "row",
html: $("<div>", {
class: "col-xs-12 text-center",
html: row = $("<h4>", {
html: title
})
})
}).add($("<div>", {
class: "row",
style: "margin-top: 16px",
html: $("<div>", {
class: "col-xs-12 text-center",
html: row = $("<textarea>", {
class: "form-control",
style: "text-align: justify;",
rows: "18",
id: "infoInput",
disabled: !type,
text: info
})
})
}));
controlDiv = $("<div>", {
class: "row",
style: "margin-top: 16px",
html: $("<div>", {
class: "col-xs-3 text-center",
html: $("<button>", {
class: "btn btn-success btn-block",
id: "addEndpoint",
html: gettext("Add endpoint")
})
}).add($("<div>", {
class: "col-xs-3 text-center",
html: $("<button>", {
class: "btn btn-danger btn-block",
id: "removeEndpoint",
html: gettext("Delete endpoint")
})
})).add($("<div>", {
class: "col-xs-6 text-center",
html: $("<button>", {
class: "btn btn-info btn-block",
id: "removeElementFromWorkspace",
html: gettext("Remove from workspace")
})
}))
});
addElementDiv = $("<div>", {
class: "row",
style: "margin-top: 16px",
html: $("<div>", {
class: "col-xs-12 text-center",
html: row = $("<button>", {
class: "btn btn-success",
id: "addElementToWorkspace",
html: gettext("Add to workspace")
})
})
});
$("#informationContainer").html(type?mainDiv.add(controlDiv):mainDiv.add(addElementDiv));
$("#changeInformationDialog").modal('show');
sharedObject = object;
};
updateConnections = function(connection, remove) {
if (!remove) {
elementConnections.push(connection);
} else {
index = -1;
for (var i = 0; i < elementConnections.length; i++) {
if (elementConnections[i] == connection) {
index = i;
break;
}
}
if (index != -1) {
elementConnections.splice(index, 1);
}
}
setServiceStatus("unsaved");
};
checkDuplicateConnection = function(connection) {
for (var i = 0; i < elementConnections.length; i++) {
if (((elementConnections[i].targetId ==
connection.targetId &&
elementConnections[i].sourceId ==
connection.sourceId) ||
(elementConnections[i].targetId ==
connection.sourceId &&
elementConnections[i].sourceId ==
connection.targetId)) &&
elementConnections[i] != connection) {
addMessage(gettext("Twofold connection is forbidden."), "danger");
return false;
}
}
return true;
};
checkCompatibility = function(sourceId, targetId) {
validTargets = $("#" + sourceId).attr("type").split(',');
if (jQuery.inArray(targetId.split('_')[1], validTargets) == -1) {
addMessage(gettext("Connecting incompatible elements is forbidden."), "danger");
return false;
}
return true;
};
checkSourceTargetEquality = function(connection) {
if (connection.targetId == connection.sourceId) {
addMessage(gettext("Connecting element to itself is forbidden."), "danger");
return false;
}
return true;
};
getAnchorCoordinate = function(rate) {
x = Math.cos(2.0 * Math.PI * rate) / 2;
y = Math.sin(2.0 * Math.PI * rate) / 2;
dx = 0;
dy = 0;
if (rate < 0.125) {
x = 0.5;
dx = 1;
} else if (rate > 0.125 && rate < 0.375) {
y = -0.5;
dy = -1;
} else if (rate > 0.375 && rate < 0.625) {
x = -0.5;
dx = -1;
} else if (rate > 0.625 && rate < 0.875) {
y = 0.5;
dy = 1;
} else if (rate > 0.875) {
x = -0.5;
dx = -1;
} else {
x = Math.sqrt(2) * Math.cos(2 * Math.PI *
rate) / 2;
y = Math.sqrt(2) * Math.sin(2 * Math.PI *
rate) / 2;
dx = Math.round(2 * x);
}
return [y + 0.5, -x + 0.5, dy, -dx];
};
isConnected = function(anchorId) {
returnValue = false;
$.each(elementConnections, function(index) {
if (elementConnections[index].endpoints[0].getUuid() == anchorId ||
elementConnections[index].endpoints[1].getUuid() == anchorId) {
returnValue = true;
return;
}
});
return returnValue;
};
elementIsConnected = function(element) {
anchors = element.attr("anchors");
id = element.attr("id");
for (i = 0; i < anchors; i++) {
if (isConnected(i + "_" + id)) {
return true;
}
}
return false;
};
getConnectionparamAndAnchor = function(anchorId) {
parameters = "";
otherAnchor = "";
$.each(elementConnections, function(index) {
if (elementConnections[index].endpoints[0].getUuid() == anchorId) {
parameters = elementConnections[index].parameters;
otherAnchor = elementConnections[index].endpoints[1].getUuid();
return;
}
if (elementConnections[index].endpoints[1].getUuid() == anchorId) {
parameters = elementConnections[index].parameters;
otherAnchor = elementConnections[index].endpoints[0].getUuid();
return;
}
});
return [otherAnchor, parameters];
};
addEndpoint = function(element) {
anchors = element.attr("anchors");
if (anchors == 8) return 1;
anchors++;
jsPlumbInstance.addEndpoint(document.getElementById(element.attr("id")), {
uuid: (anchors - 1) + "_" + element.attr("id")
},
jsPlumbEndpoint);
for (i = 0; i < anchors; i++) {
jsPlumbInstance.getEndpoint(i + "_" + element.attr("id")).setAnchor(getAnchorCoordinate(i / (anchors)));
}
element.attr("anchors", anchors);
jsPlumbInstance.repaintEverything();
return 0;
};
removeEndoint = function(element) {
anchors = element.attr("anchors");
if (anchors == 4) return 1;
i = --anchors;
while (isConnected(i + "_" + element.attr("id")) && i >= 0) i--;
if (i == -1) {
addMessage(gettext("Removing anchors is obstructed."), "danger");
return;
} else if (i == anchors) {
jsPlumbInstance.deleteEndpoint(jsPlumbInstance.getEndpoint(anchors + "_" + element.attr("id")));
} else {
newId = i + "_" + element.attr("id");
oldId = anchors + "_" + element.attr("id");
data = getConnectionparamAndAnchor(oldId);
data.splice(0, 0, newId);
jsPlumbInstance.deleteEndpoint(jsPlumbInstance.getEndpoint(oldId));
connectEndpoints(data);
}
for (i = 0; i < anchors; i++) jsPlumbInstance.getEndpoint(
i + "_" + element.attr("id")).setAnchor(getAnchorCoordinate(i / (anchors)));
element.attr("anchors", anchors);
jsPlumbInstance.repaintEverything();
return 0;
};
connectEndpoints = function(data) {
connectionObject =
jsPlumbInstance.connect({
uuids: [data[0], data[1]]
});
connectionObject.parameters = data[2];
setServiceStatus("unsaved");
};
disconnectEndpoints = function(data) {
for (var i = 0; i < elementConnections.length; i++) {
if (elementConnections[i].endpoints[0].getUuid() == data[0] &&
elementConnections[i].endpoints[1].getUuid() == data[1]) {
jsPlumbInstance.detach(elementConnections[i]);
return;
}
}
return;
};
addElement = function(idOrInstance, newId, newPositionY, endpoints, parameters, newPositionX) {
newInstance = "";
if (typeof idOrInstance != "string") {
newInstance = idOrInstance;
endpoints = newInstance.attr("anchors");
newInstance.attr("anchors", 0);
} else {
newInstance = $('#' + idOrInstance)
.clone()
.prop("id", newId)
.prop("title", "Right click to delete")
.removeClass()
.addClass("element")
.attr("anchors", 0)
.attr("parameters", parameters)
.css("top", newPositionY)
.css("left", newPositionX);
}
$("#dropContainer").append(newInstance);
for (i = 0; i <= endpoints; i++) {
addEndpoint(newInstance);
}
jsPlumbInstance.draggable(jsPlumb.getSelector(".element"), {
containment: $("#dropContainer")
});
setServiceStatus("unsaved");
jsPlumbInstance.repaintEverything();
return newInstance;
};
removeElement = function(object) {
jsPlumbInstance.detachAllConnections(object);
jsPlumbInstance.remove(object.attr("id"));
};
/* Registering events using JsPlumb. */
jsPlumbInstance.bind("connection", function(info) {
updateConnections(info.connection);
info.connection.parameters = "";
if (clickEvent === 0) {
undoStack.splice(stackIndexer, 0, disconnectEndpoints);
redoStack.splice(stackIndexer, 0, connectEndpoints);
connectionArray = [];
connectionArray.push(info.connection.endpoints[0].getUuid(),
info.connection.endpoints[1].getUuid(),
info.connection.parameters);
objectStack.splice(stackIndexer, 0, connectionArray);
stackIndexer++;
stackSize++;
}
});
jsPlumbInstance.bind("beforeDrop", function(info) {
return checkDuplicateConnection(info.connection) &&
checkSourceTargetEquality(info.connection) &&
checkCompatibility(info.connection.sourceId, info.connection.targetId);
});
jsPlumbInstance.bind("connectionDetached", function(info) {
updateConnections(info.connection, true);
if (clickEvent === 0) {
undoStack.splice(stackIndexer, 0, connectEndpoints);
redoStack.splice(stackIndexer, 0, disconnectEndpoints);
connectionArray = [];
connectionArray.push(info.connection.endpoints[0].getUuid(),
info.connection.endpoints[1].getUuid(),
info.connection.parameters);
objectStack.splice(stackIndexer, 0, connectionArray);
stackIndexer++;
stackSize++;
}
});
jsPlumbInstance.bind("connectionMoved", function(info) {
updateConnections(info.connection, true);
});
jsPlumbInstance.bind("contextmenu", function(info) {
jsPlumbInstance.detach(info);
});
jsPlumbInstance.draggable(jsPlumb.getSelector(".element"), {
containment: $("#dropContainer")
});
/* Registering events using JQuery. */
$('body').on('click', '.elementTemplate', function() {
addElement($(this).attr("id"),
(++elementIndex) + "_" + $(this).attr("id"),
(elementIndex % 21) * 30, 4, "",
(elementIndex % 21) * 30);
undoStack.splice(stackIndexer, 0, removeElement);
redoStack.splice(stackIndexer, 0, addElement);
objectStack.splice(stackIndexer, 0, newInstance);
stackSize++;
stackIndexer++;
});
$('body').on('dblclick', '.element', function() {
element = $(this);
element.addClass("elementSelected");
addInfo(element.attr("alt"),
element.attr("parameters"),
element, 1);
$(document).scrollTop(0);
});
$('body').on('contextmenu', '.element', function(event) {
setServiceStatus("unsaved");
removeElement($(this));
undoStack.splice(stackIndexer, 0, addElement);
redoStack.splice(stackIndexer, 0, removeElement);
objectStack.splice(stackIndexer, 0, $(this));
nextStepConstraint = 0;
stackSize++;
stackIndexer++;
});
$('body').on('keyup', '#infoInput', function() {
setServiceStatus("unsaved");
newParams = $("#infoInput").val();
sharedObject.attr("parameters", newParams);
});
$('body').on('click', '#addEndpoint', function() {
setServiceStatus("unsaved");
if(addEndpoint(sharedObject)) return;
undoStack.splice(stackIndexer, 0, removeEndoint);
redoStack.splice(stackIndexer, 0, addEndpoint);
objectStack.splice(stackIndexer, 0, sharedObject);
stackIndexer++;
stackSize++;
});
$('body').on('click', '#removeEndpoint', function() {
setServiceStatus("unsaved");
if(removeEndoint(sharedObject)) return;
undoStack.splice(stackIndexer, 0, addEndpoint);
redoStack.splice(stackIndexer, 0, removeEndoint);
objectStack.splice(stackIndexer, 0, sharedObject);
stackIndexer++;
stackSize++;
});
$('body').on('click', '#removeElementFromWorkspace', function() {
setServiceStatus("unsaved");
removeElement(sharedObject);
undoStack.splice(stackIndexer, 0, addElement);
redoStack.splice(stackIndexer, 0, removeElement);
objectStack.splice(stackIndexer, 0, sharedObject);
stackSize++;
stackIndexer++;
$("#changeInformationDialog").modal('hide');
});
$('body').on('click', '#removeConnection', function() {
jsPlumbInstance.detach(sharedObject);
});
$('body').on('click', '#addElementToWorkspace', function() {
newInstance = addElement(sharedObject.attr("id"),
(++elementIndex) + "_" + sharedObject.attr("id"),
(elementIndex % 21) * 30, 4, "",
(elementIndex % 21) * 30);
undoStack.splice(stackIndexer, 0, removeElement);
redoStack.splice(stackIndexer, 0, addElement);
objectStack.splice(stackIndexer, 0, newInstance);
stackSize++;
stackIndexer++;
});
$('body').on('click', '#clearService', function() {
//Todo
setServiceStatus("unsaved");
elementIndex = 0;
});
$('body').on('click', '#undoMovement', function() {
if (stackIndexer < 1) return;
stackIndexer--;
clickEvent = 1;
object = objectStack[stackIndexer];
undoStack[stackIndexer](object);
clickEvent = 0;
});
$('body').on('click', '#redoMovement', function() {
if (stackIndexer >= stackSize) return;
clickEvent = 1;
object = objectStack[stackIndexer];
redoStack[stackIndexer](object);
stackIndexer++;
clickEvent = 0;
});
$('body').on('click', '#addMachineDialog', function() {
// Here comes the ajax post of getting machines
});
$('body').on('click', '.elementTemplateInfo', function() {
id = $(this).attr("element");
addInfo($("#" + id).attr("alt"), $("#" + id).attr("desc"), $("#" + id), 0);
});
$('body').on('click', '#serviceName', function() {
$('#serviceName').hide();
$("#serviceNameEdit").css("display", "inline").val($(this).text()).select();
$("#serviceNameSave").css("display", "inline");
setServiceStatus("unsaved");
});
$('body').on('click', '#serviceNameSave', function() {
$('#serviceNameEdit').hide();
$(this).hide();
$("#serviceName").show().text($('#serviceNameEdit').val());
});
$('body').on('click', '#dragContainerScrollUp', function() {
scrollContainer(-1);
});
$('body').on('click', '#dragContainerScrollDown', function() {
scrollContainer(1);
});
$('body').on('hide.bs.modal', '#changeInformationDialog', function() {
$('.element').removeClass('elementSelected');
});
$('body').on('keyup', '#searchElementTemplate', function() {
$(".elementTemplate").each(function() {
$(this).parent().parent().hide();
if ($(this).attr("alt").toLowerCase().indexOf($("#searchElementTemplateInput").val().toLowerCase()) >= 0)
$(this).parent().parent().show();
});
});
$('body').on('mousewheel DOMMouseScroll onmousewheel', function(event) {
var e = window.event || event;
var delta = Math.max(-1, Math.min(1, (e.wheelDelta || -e.detail)));
$('body').addClass("noScroll");
dragContainerScroll -= delta;
if (dragContainerScroll == $(".elementTemplate").length - 2) dragContainerScroll--;
if (dragContainerScroll == -1) dragContainerScroll++;
$("#dragContainer").scrollTop(
dragContainerScroll * $("#elementTemplatePanel").height()
);
$('body').removeClass("noScroll");
});
$(document).on('keydown', function(e) {
var eventObject = window.event ? event : e;
// Undo (CTRL + Z)
if (eventObject.keyCode == 90 && eventObject.ctrlKey) {
eventObject.preventDefault();
$('#undoMovement').click();
}
// Redo (CTRL + Y)
if (eventObject.keyCode == 89 && eventObject.ctrlKey) {
eventObject.preventDefault();
$('#redoMovement').click();
}
// Add element (CTRL + A)
if (eventObject.keyCode == 65 && eventObject.ctrlKey) {
eventObject.preventDefault();
$('#showAddElementDialog').click();
}
// Clean (CTRL + C)
if (eventObject.keyCode == 67 && eventObject.ctrlKey) {
eventObject.preventDefault();
$('#clearService').click();
}
// Save (CTRL + S)
if (eventObject.keyCode == 83 && eventObject.ctrlKey) {
eventObject.preventDefault();
$('#saveService').click();
}
// Delete (CTRL + D)
if (eventObject.keyCode == 68 && eventObject.ctrlKey) {
eventObject.preventDefault();
$('#deleteService').click();
}
// Close dialog (ESC)
if (eventObject.keyCode == 27) {
eventObject.preventDefault();
$("#changeInformationDialog").modal('hide');
$("#addElementDialog").modal('hide');
}
});
$(window).on('resize', function() {
$(".element").each(function() {
rate = ($(this).position().left) / workspaceWidth;
left = rate * ($("#dropContainer").width());
$(this).css("left", left);
});
workspaceWidth = $("#dropContainer").width();
jsPlumbInstance.repaintEverything();
});
/* Registering events concerning persistence. */
$('body').on('click', '#saveService', function() {
serviceName = $("#serviceName").text();
connectionSet = [];
instanceSet = [];
$.each(elementConnections, function(index) {
connectionSet.push({
"sourceId": elementConnections[index].sourceId,
"sourceEndpoint": elementConnections[index].endpoints[0].getUuid(),
"targetId": elementConnections[index].targetId,
"targetEndpoint": elementConnections[index].endpoints[1].getUuid(),
"parameters": elementConnections[index].parameters
});
});
$.each($(".element"), function() {
instanceSet.push({
"displayId": $(this).prop("id"),
"positionLeft": $(this).position().left / workspaceWidth,
"positionTop": $(this).position().top / workspaceHeight,
"anchorNumber": $(this).attr("anchors"),
"parameters": $(this).attr("parameters")
});
});
$.post("", {
event: "saveService",
data: JSON.stringify({
"serviceName": serviceName,
"elementConnections": connectionSet,
"elements": instanceSet
})
}, function(result) {
addMessage(result.serviceName + gettext(" saved successfully."), "success");
setServiceStatus("saved");
});
});
$(document).ready(function() {
if (!$("#dropContainer").length) return; // Protection for not posting sites that differ from setty sites.
$.post("", {
event: "loadService"
}, function(result) {
$("#serviceName").text(result.serviceName);
$.each(result.elements, function(i, element) {
addElement(element.displayId.split('_')[1],
element.displayId,
(element.positionTop * workspaceHeight) + "px",
element.anchorNumber,
element.parameters,
(element.positionLeft * workspaceWidth) + "px");
if (elementIndex < element.displayId.split('_')[0])
elementIndex = element.displayId.split('_')[0];
elementIndex++;
});
clickEvent = 1;
$.each(result.elementConnections,
function(i, connection) {
connectEndpoints([connection.sourceEndpoint, connection.targetEndpoint, connection.parameters]);
});
clickEvent = 0;
setServiceStatus("saved");
});
});
});
/* Settimng up csrf token, touch event and zoom options. */
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie !== '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
if (cookie.substring(0, name.length + 1) == (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
function csrfSafeMethod(method) {
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
var csrftoken = getCookie('csrftoken');
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});
/* Setty implementation starts here. */
jsPlumb.ready(function() {
var jsPlumbInstance = jsPlumb.getInstance({
DragOptions: {
zIndex: 2000
},
EndpointHoverStyle: {
fillStyle: "green"
},
HoverPaintStyle: {
strokeStyle: "green"
},
Container: "dropContainer"
});
var jsPlumbEndpoint = {
endpoint: ["Dot", {
radius: 10
}],
paintStyle: {
fillStyle: "#9932cc"
},
isSource: true,
isTarget: true,
deleteEndpointsOnDetach: false,
zIndex: 20,
connectorStyle: {
strokeStyle: "#9932cc",
lineWidth: 8
},
connector: ["Bezier", {
curviness: 180
}],
maxConnections: 1,
dropOptions: {
tolerance: "fit"
}
};
var elementConnections = [];
var elementIndex = 0;
var dragContainerScroll = 0;
var workspaceWidth = $("#dropContainer").width();
var workspaceHeight = $("#dropContainer").height();
var stackIndexer = 0;
var stackSize = 0;
var objectStack = [];
var undoStack = [];
var redoStack = [];
var clickEvent = 0;
var nextStepConstraint = 0;
/* Functions. */
setServiceStatus = function(status) {
if (status == "unsaved") {
$("#serviceStatus").text("Unsaved");
}
else {
$("#serviceStatus").empty();
}
};
addInfo = function(title, info, type, object) {
id = object.attr("id").split("_")[1];
$.post("", {
event: "getInformation",
data: JSON.stringify({
"elementTemplateId": object.attr("id").split("_")[1],
"hostname": object.attr("hostname")})
}, function(result) {
alert(result);
});
/*
$("#informationContainer").empty();
switch(type){
case "connection":
div =
'<div class="row">' +
'<div class="col-xs-12 text-center">' +
'<h4>' + title + '</h4>' +
'</div>' +
'</div>&nbsp;' +
'<div class="row">' +
'<div class="col-xs-12">' +
'<textarea class="form-control" rows="28" id="infoInput" placeholder="Config data"></textarea>' +
'</div>' +
'</div>&nbsp;' +
'<div class="row">' +
'<div class="col-xs-12 text-center">' +
'<button id="removeConnection" class="btn btn-info">Remove connection</button>' +
'</div>' +
'</div>';
break;
case "element":
div =
'<div class="row">' +
'<div class="col-xs-12 text-center">' +
'<h4>' + title + '</h4>' +
'</div>' +
'</div>&nbsp;' +
'<div class="row">' +
'<div class="col-xs-12">' +
'<textarea class="form-control" rows="24" id="infoInput" placeholder="Config data"></textarea>' +
'</div>' +
'</div>&nbsp;' +
'<div class="row text-center">' +
'<label>Endpoints</label>' +
'</div>' +
'<div class="row">' +
'<div class="col-xs-6 text-center">' +
'<button id="addEndpoint" class="btn btn-success"><i class="fa fa-plus"></i></button>' +
'</div>' +
'<div class="col-xs-6 text-center">' +
'<button id="removeEndpoint" class="btn btn-danger"><i class="fa fa-minus"></i></button>' +
'</div>' +
'</div>&nbsp;' +
'<div class="row">' +
'<div class="col-xs-12 text-center">' +
'<button id="removeElementFromWorkspace" class="btn btn-info">Remove from workspace</button>' +
'</div>' +
'</div>';
break;
case "elementTemplate":
div =
'<div class="row">' +
'<div class="col-xs-12 text-center">' +
'<h4>' + title + '</h4>' +
'</div>' +
'</div>&nbsp;' +
'<div class="row">' +
'<div class="col-xs-12">' +
'<textarea class="form-control" rows="28" id="infoInput" placeholder="Config data"></textarea>' +
'</div>' +
'</div>&nbsp;' +
'<div class="row">' +
'<div class="col-xs-12 text-center">' +
'<button id="addElementToWorkspace" class="btn btn-success">Add to workspace</button>' +
'</div>' +
'</div>';
break;
}*/
// Here comes the ajax getInformation post.
// elementtemplateid vagy hostname
div = 0;
$("#informationContainer").append(div);
$("#infoInput").val(info);
$("#changeInformationDialog").modal('show');
sharedObject = object;
};
updateConnections = function(connection, remove) {
if (!remove) {
elementConnections.push(connection);
} else {
index = -1;
for (var i = 0; i < elementConnections.length; i++) {
if (elementConnections[i] == connection) {
index = i;
break;
}
}
if (index != -1) {
elementConnections.splice(index, 1);
}
}
setServiceStatus("unsaved");
};
checkDuplicateConnection = function(connection) {
for (var i = 0; i < elementConnections.length; i++) {
if (((elementConnections[i].targetId ==
connection.targetId &&
elementConnections[i].sourceId ==
connection.sourceId) ||
(elementConnections[i].targetId ==
connection.sourceId &&
elementConnections[i].sourceId ==
connection.targetId)) &&
elementConnections[i] != connection) {
addMessage(gettext("Twofold connection is forbidden."), "danger");
return false;
}
}
return true;
};
checkCompatibility = function(sourceId, targetId) {
validTargets = $("#" + sourceId).attr("type").split(',');
if (jQuery.inArray(targetId.split('_')[1], validTargets) == -1) {
addMessage(gettext("Connecting incompatible elements is forbidden."), "danger");
return false;
}
return true;
};
checkSourceTargetEquality = function(connection) {
if (connection.targetId == connection.sourceId) {
addMessage(gettext("Connecting element to itself is forbidden."), "danger");
return false;
}
return true;
};
getAnchorCoordinate = function(rate) {
x = Math.cos(2.0 * Math.PI * rate) / 2;
y = Math.sin(2.0 * Math.PI * rate) / 2;
dx = 0;
dy = 0;
if (rate < 0.125) {
x = 0.5;
dx = 1;
} else if (rate > 0.125 && rate < 0.375) {
y = -0.5;
dy = -1;
} else if (rate > 0.375 && rate < 0.625) {
x = -0.5;
dx = -1;
} else if (rate > 0.625 && rate < 0.875) {
y = 0.5;
dy = 1;
} else if (rate > 0.875) {
x = -0.5;
dx = -1;
} else {
x = Math.sqrt(2) * Math.cos(2 * Math.PI *
rate) / 2;
y = Math.sqrt(2) * Math.sin(2 * Math.PI *
rate) / 2;
dx = Math.round(2 * x);
}
return [y + 0.5, -x + 0.5, dy, -dx];
};
isConnected = function(anchorId) {
returnValue = false;
$.each(elementConnections, function(index) {
if (elementConnections[index].endpoints[0].getUuid() == anchorId ||
elementConnections[index].endpoints[1].getUuid() == anchorId) {
returnValue = true;
return;
}
});
return returnValue;
};
elementIsConnected = function(element) {
anchors = element.attr("anchors");
id = element.attr("id");
for(i=0;i<anchors;i++)
{
if(isConnected(i + "_" + id))
{
return true;
}
}
return false;
};
getConnectionparamAndAnchor = function(anchorId) {
parameters = "";
otherAnchor = "";
$.each(elementConnections, function(index) {
if (elementConnections[index].endpoints[0].getUuid() == anchorId) {
parameters = elementConnections[index].parameters;
otherAnchor = elementConnections[index].endpoints[1].getUuid();
return;
}
if (elementConnections[index].endpoints[1].getUuid() == anchorId) {
parameters = elementConnections[index].parameters;
otherAnchor = elementConnections[index].endpoints[0].getUuid();
return;
}
});
return [otherAnchor, parameters];
};
addEndpoint = function(element) {
anchors = element.attr("anchors");
if (anchors == 8) return;
anchors++;
jsPlumbInstance.addEndpoint(document.getElementById(element.attr("id")), {
uuid: (anchors - 1) + "_" + element.attr("id")
},
jsPlumbEndpoint);
for (i = 0; i < anchors; i++) {
jsPlumbInstance.getEndpoint(i + "_" + element.attr("id")).setAnchor(getAnchorCoordinate(i / (anchors)));
}
element.attr("anchors", anchors);
jsPlumbInstance.repaintEverything();
};
removeEndoint = function(element) {
anchors = element.attr("anchors");
if (anchors == 4) return;
i = --anchors;
while (isConnected(i + "_" + element.attr("id")) && i >= 0) i--;
if (i == -1) {
addMessage(gettext("Removing anchors is obstructed."), "danger");
return;
} else if (i == anchors) {
jsPlumbInstance.deleteEndpoint(jsPlumbInstance.getEndpoint(anchors + "_" + element.attr("id")));
} else {
newId = i + "_" + element.attr("id");
oldId = anchors + "_" + element.attr("id");
data = getConnectionparamAndAnchor(oldId);
data.splice(0, 0, newId);
jsPlumbInstance.deleteEndpoint(jsPlumbInstance.getEndpoint(oldId));
connectEndpoints(data);
}
for (i = 0; i < anchors; i++) jsPlumbInstance.getEndpoint(
i + "_" + element.attr("id")).setAnchor(getAnchorCoordinate(i / (anchors)));
element.attr("anchors", anchors);
jsPlumbInstance.repaintEverything();
};
connectEndpoints = function(data) {
connectionObject =
jsPlumbInstance.connect({
source: data[0],
target: data[1]
});
connectionObject.parameters = data[2];
setServiceStatus("unsaved");
};
disconnectEndpoints = function(data) {
for (var i = 0; i < elementConnections.length; i++) {
if (elementConnections[i].endpoints[0].getUuid() == data[0] &&
elementConnections[i].endpoints[1].getUuid() == data[1]) {
jsPlumbInstance.detach(elementConnections[i]);
return;
}
}
return;
};
addElement = function(idOrInstance, newId, newPositionY, endpoints, parameters, newPositionX) {
newInstance = "";
if (typeof idOrInstance != "string") {
newInstance = idOrInstance;
endpoints = newInstance.attr("anchomNumber");
newInstance.attr("anchors", 0);
} else {
newInstance = $('#' + idOrInstance)
.clone()
.prop("id", newId)
.prop("title", "Right click to delete")
.removeClass()
.addClass("element")
.attr("anchors", 0)
.attr("parameters", parameters)
.css("top", newPositionY)
.css("left", newPositionX);
}
$("#dropContainer").append(newInstance);
for (i = 0; i <= endpoints; i++) {
addEndpoint(newInstance);
}
jsPlumbInstance.draggable(jsPlumb.getSelector(".element"), {
containment: $("#dropContainer")
});
setServiceStatus("unsaved");
jsPlumbInstance.repaintEverything();
return newInstance;
};
addMachine = function(idOrInstance, newId, newPositionY, endpoints, parameters, newPositionX) {
newInstance = "";
newInstance = $('<div>')
.prop("id", newId)
.prop("title", "Right click to delete")
.removeClass()
.addClass("element")
.attr("anchors", 0)
.attr("parameters", parameters)
.css("top", newPositionY)
.css("left", newPositionX);
$("#dropContainer").append(newInstance);
for (i = 0; i <= endpoints; i++) {
addEndpoint(newInstance);
}
jsPlumbInstance.draggable(jsPlumb.getSelector(".element"), {
containment: $("#dropContainer")
});
setServiceStatus("unsaved");
jsPlumbInstance.repaintEverything();
return newInstance;
}
removeElement = function(object) {
jsPlumbInstance.detachAllConnections(object);
jsPlumbInstance.remove(object.attr("id"));
};
/* Registering events using JsPlumb. */
jsPlumbInstance.bind("connection", function(info) {
updateConnections(info.connection);
info.connection.parameters = "";
if (clickEvent === 0) {
undoStack.splice(stackIndexer, 0, disconnectEndpoints);
redoStack.splice(stackIndexer, 0, connectEndpoints);
connectionArray = [];
connectionArray.push(info.connection.endpoints[0].getUuid(),
info.connection.endpoints[1].getUuid(),
info.connection.parameters);
objectStack.splice(stackIndexer, 0, connectionArray);
stackIndexer++;
stackSize++;
}
});
jsPlumbInstance.bind("beforeDrop", function(info) {
return checkDuplicateConnection(info.connection) &&
checkSourceTargetEquality(info.connection) &&
checkCompatibility(info.connection.sourceId, info.connection.targetId);
});
jsPlumbInstance.bind("connectionDetached", function(info) {
updateConnections(info.connection, true);
if (clickEvent === 0) {
undoStack.splice(stackIndexer, 0, connectEndpoints);
redoStack.splice(stackIndexer, 0, disconnectEndpoints);
connectionArray = [];
connectionArray.push(info.connection.endpoints[0].getUuid(),
info.connection.endpoints[1].getUuid(),
info.connection.parameters);
objectStack.splice(stackIndexer, 0, connectionArray);
stackIndexer++;
stackSize++;
}
});
jsPlumbInstance.bind("connectionMoved", function(info) {
updateConnections(info.connection, true);
});
jsPlumbInstance.bind("contextmenu", function(info) {
jsPlumbInstance.detach(info);
});
jsPlumbInstance.bind("dblclick", function(info) {
info.setPaintStyle({strokeStyle:"red", lineWidth: 8});
addInfo($("#" + info.sourceId.split('_')[1]).attr("alt") + ' - ' + $("#" + info.targetId.split('_')[1]).attr("alt"),
info.parameters,
"connection",
info);
});
jsPlumbInstance.draggable(jsPlumb.getSelector(".element"), {
containment: $("#dropContainer")
});
/* Registering events using JQuery. */
$('body').on('click', '.elementTemplate', function() {
addElement($(this).attr("id"),
(++elementIndex) + "_" + $(this).attr("id"),
(elementIndex % 21) * 30, 4, "",
(elementIndex % 21) * 30);
undoStack.splice(stackIndexer, 0, removeElement);
redoStack.splice(stackIndexer, 0, addElement);
objectStack.splice(stackIndexer, 0, newInstance);
stackSize++;
stackIndexer++;
});
$('body').on('dblclick', '.element', function() {
element = $(this);
element.addClass("elementSelected");
addInfo(element.attr("alt"),
element.attr("parameters"),
"element", element);
$(document).scrollTop(0);
});
$('body').on('contextmenu', '.element', function(event) {
setServiceStatus("unsaved");
removeElement($(this));
undoStack.splice(stackIndexer, 0, addElement);
redoStack.splice(stackIndexer, 0, removeElement);
objectStack.splice(stackIndexer, 0, $(this));
nextStepConstraint = 0;
stackSize++;
stackIndexer++;
});
$('body').on('click', '#closeInfoPanel', function() {
$('#informationPanel').hide();
$('#dragPanel').show();
});
$('body').on('keyUp', '#infoInput', function() {
setServiceStatus("unsaved");
newParams = $("#infoInput").val();
if (type == "connection") object.parameters = newParams;
if (type == "element") object.attr("parameters", newParams);
});
$('body').on('click', '#addEndpoint', function() {
addEndpoint(sharedObject);
undoStack.splice(stackIndexer, 0, removeEndoint);
redoStack.splice(stackIndexer, 0, addEndpoint);
objectStack.splice(stackIndexer, 0, sharedObject);
stackIndexer++;
stackSize++;
});
$('body').on('click', '#removeEndpoint', function() {
removeEndoint(sharedObject);
undoStack.splice(stackIndexer, 0, addEndpoint);
redoStack.splice(stackIndexer, 0, removeEndoint);
objectStack.splice(stackIndexer, 0, sharedObject);
stackIndexer++;
stackSize++;
});
$('body').on('click', '#removeElementFromWorkspace', function() {
setServiceStatus("unsaved");
removeElement(sharedObject);
undoStack.splice(stackIndexer, 0, addElement);
redoStack.splice(stackIndexer, 0, removeElement);
objectStack.splice(stackIndexer, 0, sharedObject);
stackSize++;
stackIndexer++;
});
$('body').on('click', '#removeConnection', function() {
jsPlumbInstance.detach(sharedObject);
});
$('body').on('click', '#addElementToWorkspace', function() {
newInstance = addElement(sharedObject.attr("id"),
(++elementIndex) + "_" + sharedObject.attr("id"),
(elementIndex % 21) * 30, 4, "",
(elementIndex % 21) * 30);
undoStack.splice(stackIndexer, 0, removeElement);
redoStack.splice(stackIndexer, 0, addElement);
objectStack.splice(stackIndexer, 0, newInstance);
stackSize++;
stackIndexer++;
});
$('body').on('click', '#clearService', function() {
jsPlumbInstance.remove("element");
setServiceStatus("unsaved");
elementIndex = 0;
});
$('body').on('click', '#undoMovement', function() {
if (stackIndexer < 1) return;
stackIndexer--;
clickEvent = 1;
object = objectStack[stackIndexer];
undoStack[stackIndexer](object);
clickEvent = 0;
});
$('body').on('click', '#redoMovement', function() {
if (stackIndexer >= stackSize) return;
clickEvent = 1;
object = objectStack[stackIndexer];
redoStack[stackIndexer](object);
stackIndexer++;
clickEvent = 0;
});
$('body').on('click', '#addMachineDialog', function() {
// Here comes the ajax post of getMachineAvailableList
// posting usedhostnames
//
//
// after it, appending obtained content to addmachinedialogbody
});
$('body').on('click', '.elementTemplateInfo', function() {
id = $(this).attr("element");
addInfo($("#" + id).attr("alt"), $("#" + id).attr("desc"), "elementTemplate", $("#" + id));
});
$('body').on('click', '#serviceName', function() {
$('#serviceName').hide();
$("#serviceNameEdit").css("display", "inline").val($(this).text()).select();
$("#serviceNameSave").css("display", "inline");
setServiceStatus("unsaved");
});
$('body').on('click', '#serviceNameSave', function() {
$('#serviceNameEdit').hide();
$(this).hide();
$("#serviceName").show().text($('#serviceNameEdit').val());
});
$('body').on('click', '#dragContainerScrollUp', function() {
scrollContainer(-1);
});
$('body').on('click', '#dragContainerScrollDown', function() {
scrollContainer(1);
});
$('body').on('hide.bs.modal', '#changeInformationDialog', function () {
$('.element').removeClass('elementSelected');
jsPlumbInstance.select().setPaintStyle({strokeStyle:'#9932cc', lineWidth: 8});
});
$('body').on('keyup', '#searchElementTemplate', function() {
$(".elementTemplate").each(function() {
$(this).parent().parent().hide();
if ($(this).attr("alt").toLowerCase().indexOf($("#searchElementTemplateInput").val().toLowerCase()) >= 0)
$(this).parent().parent().show();
});
});
$('body').on('mousewheel DOMMouseScroll onmousewheel', function(event) {
var e = window.event || event;
var delta = Math.max(-1, Math.min(1, (e.wheelDelta || -e.detail)));
$('body').addClass("noScroll");
dragContainerScroll -= delta;
if (dragContainerScroll == $(".elementTemplate").length - 2) dragContainerScroll--;
if (dragContainerScroll == -1) dragContainerScroll++;
$("#dragContainer").scrollTop(
dragContainerScroll * $("#elementTemplatePanel").height()
);
$('body').removeClass("noScroll");
});
$(document).on('keydown', function(e) {
var eventObject = window.event ? event : e;
// Undo (CTRL + Z)
if (eventObject.keyCode == 90 && eventObject.ctrlKey)
{
eventObject.preventDefault();
$('#undoMovement').click();
}
// Redo (CTRL + Y)
if (eventObject.keyCode == 89 && eventObject.ctrlKey)
{
eventObject.preventDefault();
$('#redoMovement').click();
}
// Add element (CTRL + A)
if (eventObject.keyCode == 65 && eventObject.ctrlKey)
{
eventObject.preventDefault();
$('#showAddElementDialog').click();
}
// Clean (CTRL + C)
if (eventObject.keyCode == 67 && eventObject.ctrlKey)
{
eventObject.preventDefault();
$('#clearService').click();
}
// Save (CTRL + S)
if (eventObject.keyCode == 83 && eventObject.ctrlKey)
{
eventObject.preventDefault();
$('#saveService').click();
}
// Delete (CTRL + D)
if (eventObject.keyCode == 68 && eventObject.ctrlKey)
{
eventObject.preventDefault();
$('#deleteService').click();
}
});
$(window).on('resize', function() {
$(".element").each(function() {
rate = ($(this).position().left)/workspaceWidth;
left = rate*($("#dropContainer").width());
$(this).css("left", left);
});
workspaceWidth = $("#dropContainer").width();
jsPlumbInstance.repaintEverything();
});
/* Registering events concerning persistence. */
$('body').on('click', '#saveService', function() {
serviceName = $("#serviceName").text();
connectionSet = [];
instanceSet = [];
$.each(elementConnections, function(index) {
connectionSet.push({
"sourceId": elementConnections[index].sourceId,
"sourceEndpoint": elementConnections[index].endpoints[0].getUuid(),
"targetId": elementConnections[index].targetId,
"targetEndpoint": elementConnections[index].endpoints[1].getUuid(),
"parameters": elementConnections[index].parameters});
});
$.each($(".element"), function() {
instanceSet.push({
"displayId": $(this).prop("id"),
"positionLeft": $(this).position().left/workspaceWidth,
"positionTop": $(this).position().top/workspaceHeight,
"anchorNumber": $(this).attr("anchors"),
"parameters": $(this).attr("parameters")});
});
$.post("", {
event: "saveService",
data: JSON.stringify({
"serviceName": serviceName,
"elementConnections": connectionSet,
"elements": instanceSet,
"machines": []}) //TODO: Dani: add machines here
}, function(result) {
addMessage(result.serviceName + gettext(" saved successfully."),"success");
setServiceStatus("saved");
});
});
$(document).ready(function() {
if(!$("#dropContainer").length)
return;
$.post("", {
event: "loadService"
}, function(result) {
$("#serviceName").text(result.serviceName);
$.each(result.serviceNodes, function(i, element) {
addElement(element.displayId.split('_')[1],
element.displayId,
(element.positionTop*workspaceHeight) + "px",
element.anchorNumber,
element.parameters,
(element.positionLeft*workspaceWidth) + "px");
if (elementIndex < element.displayId.split('_')[0])
elementIndex = element.displayId.split('_')[0];
elementIndex++;
});
$.each(result.machines, function(i, element) {
addMachine(element.displayId.split('_')[1],
element.displayId,
(element.positionTop*workspaceHeight) + "px",
element.anchorNumber,
element.parameters,
(element.positionLeft*workspaceWidth) + "px");
if (elementIndex < element.displayId.split('_')[0])
elementIndex = element.displayId.split('_')[0];
elementIndex++;
});
clickEvent = 1;
$.each(result.elementConnections,
function(i, connection) {
connectEndpoints([connection.sourceEndpoint, connection.targetEndpoint, connection.parameters]);
});
clickEvent = 0;
setServiceStatus("saved");
});
});
});

9.06 KB | W: | H:

9.06 KB | W: | H:

circle/setty/static/setty/ubuntu.jpg
circle/setty/static/setty/ubuntu.jpg
circle/setty/static/setty/ubuntu.jpg
circle/setty/static/setty/ubuntu.jpg
  • 2-up
  • Swipe
  • Onion skin

19.9 KB | W: | H:

19.9 KB | W: | H:

circle/setty/static/setty/wordpress.jpg
circle/setty/static/setty/wordpress.jpg
circle/setty/static/setty/wordpress.jpg
circle/setty/static/setty/wordpress.jpg
  • 2-up
  • Swipe
  • Onion skin
# Copyright 2014 Budapest University of Technology and Economics (BME IK)
#
# This file is part of CIRCLE Cloud.
#
# CIRCLE 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 3 of the License, or (at your option)
# any later version.
#
# CIRCLE 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 CIRCLE. If not, see <http://www.gnu.org/licenses/>.
from django_tables2 import Table
from django_tables2.columns import TemplateColumn
from setty.models import Service
from django.utils.translation import ugettext as _
class ServiceListTable(Table):
name = TemplateColumn(
template_name="setty/tables/column-name.html",
attrs={'th': {'data-sort': "string"}}
)
owner = TemplateColumn(
template_name="setty/tables/column-owner.html",
verbose_name=_("Owner"),
attrs={'th': {'data-sort': "string"}}
)
running = TemplateColumn(
template_name="setty/tables/column-running.html",
verbose_name=_("Running"),
attrs={'th': {'data-sort': "string"}},
)
class Meta:
model = Service
attrs = {'class': ('table table-bordered table-striped table-hover'
' template-list-table')}
fields = ('name', 'owner', 'running', )
prefix = "service-"
# Copyright 2014 Budapest University of Technology and Economics (BME IK)
#
# This file is part of CIRCLE Cloud.
#
# CIRCLE 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 3 of the License, or (at your option)
# any later version.
#
# CIRCLE 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 CIRCLE. If not, see <http://www.gnu.org/licenses/>.
from django_tables2 import Table
from django_tables2.columns import TemplateColumn
from setty.models import Service
from django.utils.translation import ugettext as _
class ServiceListTable(Table):
name = TemplateColumn(
template_name="setty/tables/column-name.html",
attrs={'th': {'data-sort': "string"}}
)
owner = TemplateColumn(
template_name="setty/tables/column-owner.html",
verbose_name=_("Owner"),
attrs={'th': {'data-sort': "string"}}
)
running = TemplateColumn(
template_name="setty/tables/column-running.html",
verbose_name=_("Running"),
attrs={'th': {'data-sort': "string"}},
)
class Meta:
model = Service
attrs = {'class': ('table table-bordered table-striped table-hover'
' template-list-table')}
fields = ('name', 'owner', 'running', )
prefix = "service-"
......@@ -24,7 +24,8 @@ from django.shortcuts import redirect
from braces.views import LoginRequiredMixin
from django.views.generic import TemplateView, DeleteView
from django_tables2 import SingleTableView
from .models import Element, ElementTemplate, ElementConnection, Service
from saltstackhelper import *
from controller import *
from dashboard.views.util import FilterMixin
from django.utils.translation import ugettext as _
import json
......@@ -39,6 +40,7 @@ logger = logging.getLogger(__name__)
class DetailView(LoginRequiredMixin, TemplateView):
template_name = "setty/index.html"
salthelper = SaltStackHelper()
def get_context_data(self, **kwargs):
logger.debug('DetailView.get_context_data() called. User: %s',
......@@ -54,88 +56,37 @@ class DetailView(LoginRequiredMixin, TemplateView):
raise PermissionDenied
def post(self, request, *args, **kwargs):
logger.debug('DetailView.post() called. User: %s',
unicode(self.request.user))
service = Service.objects.get(id=kwargs['pk'])
if self.request.user == service.user or self.request.user.is_superuser:
if self.request.POST.get('event') == "saveService":
data = json.loads(self.request.POST.get('data'))
service = Service.objects.get(id=kwargs['pk'])
service.name = data['serviceName']
service.save()
Element.objects.filter(service=service).delete()
for element in data['elements']:
elementObject = Element(
service=service,
parameters=element['parameters'],
display_id=element['displayId'],
position_left=element['positionLeft'],
position_top=element['positionTop'],
anchor_number=element['anchorNumber']
)
elementObject.save()
for elementConnection in data['elementConnections']:
sourceId = elementConnection['sourceId']
targetId = elementConnection['targetId']
sourceEndpoint = elementConnection['sourceEndpoint']
targetEndpoint = elementConnection['targetEndpoint']
connectionParameters = elementConnection['parameters']
targetObject = Element.objects.get(
display_id=targetId,
service=service)
sourceObject = Element.objects.get(
display_id=sourceId,
service=service)
connectionObject = ElementConnection(
target=targetObject,
source=sourceObject,
target_endpoint=targetEndpoint,
source_endpoint=sourceEndpoint,
parameters=connectionParameters
)
connectionObject.save()
return JsonResponse({'serviceName': service.name})
elif self.request.POST.get('event') == "loadService":
service = Service.objects.get(id=kwargs['pk'])
elementList = Element.objects.filter(service=service)
elementConnectionList = ElementConnection.objects.filter(
Q(target__in=elementList) | Q(source__in=elementList))
elements = []
elementConnections = []
for item in elementList:
elements.append({
'parameters': item.parameters,
'displayId': item.display_id,
'positionLeft': item.position_left,
'positionTop': item.position_top,
'anchorNumber': item.anchor_number})
for item in elementConnectionList:
elementConnections.append({
'targetEndpoint': item.target_endpoint,
'sourceEndpoint': item.source_endpoint,
'parameters': item.parameters})
return JsonResponse(
{'elements': elements,
'elementConnections': elementConnections,
'serviceName': service.name})
else:
raise PermissionDenied
else:
if self.request.user != service.user or not self.request.user.is_superuser:
raise PermissionDenied
result = {}
eventName = self.request.POST.get('event')
serviceId = kwargs['pk']
if eventName == 'loadService':
result = SettyController.loadService(serviceId)
elif eventName == "deploy":
result = SettyController.deploy(serviceId)
data = json.loads(self.request.POST.get('data'))
if eventName == "saveService":
result = SettyController.saveService(serviceId, data['serviceName'], data[
'serviceNodes'], data['machines'], data['elementConnections'])
elif eventName == "getMachineAvailableList":
result = SettyController.getMachineAvailableList(
serviceId, data["usedHostnames"])
elif eventName == "addServiceNode":
result = SettyController.addServiceNode(
data["elementTemplateId"])
elif eventName == "addMachine":
result = SettyController.addMachine(data["hostname"])
elif eventName == "getInformation":
result = SettyController.getInformation(
data['elementTemplateId'], data['hostname'])
return JsonResponse(result)
class DeleteView(LoginRequiredMixin, DeleteView):
......@@ -180,11 +131,16 @@ class CreateView(LoginRequiredMixin, TemplateView):
if not service_name:
service_name = "Noname"
service = Service(
name=service_name,
status="stopped",
user=self.request.user
)
try:
serviceNameAvailable = Service.objects.get(name=service_name)
raise PermissionDenied
except Service.DoesNotExist:
pass
service = Service(name=service_name,
status=1,
user=self.request.user)
service.save()
return redirect('setty.views.service-detail', pk=service.pk)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment