Merge branch 'feature/api-cleanup'
diff --git a/apiary.apib b/apiary.apib
index cdee98c..25915e9 100644
--- a/apiary.apib
+++ b/apiary.apib
@@ -46,6 +46,47 @@
}
]
+### Create a deployment [POST]
+
++ Request (application/json)
+
+ {
+ "humanReadableName": "MyDeployment",
+ }
+
++ Response 200 (application/json)
+
+ {
+ "humanReadableName": "MyDeployment",
+ "id": 1,
+ "created": "2016-04-29T16:19:03.549901Z",
+ "updated": "2016-04-29T16:19:05.624151Z",
+ "enacted": null,
+ "policed": null,
+ "backend_register": "{}",
+ "backend_status": "0 - Provisioning in progress",
+ "deleted": false,
+ "write_protect": false,
+ "lazy_blocked": false,
+ "no_sync": true,
+ "name": "MyDeployment",
+ "accessControl": "allow all",
+ "images": [
+ "1"
+ ],
+ "sites": [
+ "1"
+ ],
+ "flavors": [
+ "1",
+ "2",
+ "3"
+ ],
+ "dashboardviews": [
+ "1"
+ ]
+ }
+
### View a Deployment Detail [GET]
+ Parameters
@@ -82,6 +123,12 @@
]
}
+### Delete a Deployment [DELETE]
+
++ Parameters
+ + id: 1 (number) - ID of the Deployment in the form of an integer
+
++ Response 204
# Group Flavors
@@ -119,6 +166,39 @@
}
]
+### Create a Flavor [POST]
+
++ Request (application/json)
+
+ {
+ "humanReadableName": "mq.test",
+ }
+
++ Response 200 (application/json)
+
+ {
+ "humanReadableName": "m1.large",
+ "id": 1,
+ "created": "2016-04-29T16:19:01.979548Z",
+ "updated": "2016-04-29T16:19:03.568238Z",
+ "enacted": null,
+ "policed": null,
+ "backend_register": "{}",
+ "backend_status": "0 - Provisioning in progress",
+ "deleted": false,
+ "write_protect": false,
+ "lazy_blocked": false,
+ "no_sync": true,
+ "name": "m1.large",
+ "description": null,
+ "flavor": "m1.large",
+ "order": 0,
+ "default": false,
+ "deployments": [
+ "1"
+ ]
+ }
+
### View a Flavors Detail [GET]
+ Parameters
@@ -148,13 +228,23 @@
"1"
]
}
+
+### Delete a Flavors Detail [DELETE]
+
++ Parameters
+ + id: 1 (number) - ID of the Flavors in the form of an integer
+
++ Response 204
# Group Instances
List of the XOS instances
-## Instances [/api/core/instances/{id}/]
+## Instances Collection [/api/core/instances/{?no_hyperlinks}]
+
+ + no_hyperlinks (number, optional) - Wheter to return relation with links or ids
+ + Default: `0`
### List all Instances [GET]
@@ -195,7 +285,107 @@
]
}
]
-
+
+### Create an Instance [POST]
+
++ Parameters
+ + no_hyperlinks: 1
+
++ Request (application/json)
+
+ {
+ "name": "test-instance",
+ "image": 1,
+ "slice": 1,
+ "deployment": 1,
+ "node": 1
+ }
+
++ Response 200 (application/json)
+
+ {
+ "id": 1,
+ "humanReadableName": "uninstantiated-1",
+ "created": "2016-04-26T00:36:22.465259Z",
+ "updated": "2016-04-26T00:36:22.465288Z",
+ "enacted": null,
+ "policed": null,
+ "backend_register": "{}",
+ "backend_status": "0 - Provisioning in progress",
+ "deleted": false,
+ "write_protect": false,
+ "lazy_blocked": false,
+ "no_sync": false,
+ "instance_id": null,
+ "instance_uuid": null,
+ "name": "test-instance",
+ "instance_name": null,
+ "ip": null,
+ "image": "1",
+ "creator": "1",
+ "slice": "1",
+ "deployment": "1",
+ "node": "1",
+ "numberCores": 0,
+ "flavor": "1",
+ "userData": null,
+ "isolation": "vm",
+ "volumes": "/etc/dnsmasq.d,/etc/ufw",
+ "parent": null,
+ "networks": [
+ "1"
+ ]
+ }
+
+## Instances Detail [/api/core/instances/{id}/]
+
+### Get instance details [GET]
+
++ Parameters
+ + id: 1 (number) - ID of the Instance in the form of an integer
+
++ Response 200 (application/json)
+
+ {
+ "id": 1,
+ "humanReadableName": "uninstantiated-1",
+ "created": "2016-04-26T00:36:22.465259Z",
+ "updated": "2016-04-26T00:36:22.465288Z",
+ "enacted": null,
+ "policed": null,
+ "backend_register": "{}",
+ "backend_status": "0 - Provisioning in progress",
+ "deleted": false,
+ "write_protect": false,
+ "lazy_blocked": false,
+ "no_sync": false,
+ "instance_id": null,
+ "instance_uuid": null,
+ "name": "mysite_vcpe",
+ "instance_name": null,
+ "ip": null,
+ "image": "1",
+ "creator": "1",
+ "slice": "1",
+ "deployment": "1",
+ "node": "1",
+ "numberCores": 0,
+ "flavor": "1",
+ "userData": null,
+ "isolation": "vm",
+ "volumes": "/etc/dnsmasq.d,/etc/ufw",
+ "parent": null,
+ "networks": [
+ "1"
+ ]
+ }
+
+### Delete instance [DELETE]
+
++ Parameters
+ + id: 1 (number) - ID of the Instance in the form of an integer
+
++ Response 204
# Group Nodes
diff --git a/xos/configurations/test-standalone/Makefile b/xos/configurations/test-standalone/Makefile
index 7de1598..64335d3 100644
--- a/xos/configurations/test-standalone/Makefile
+++ b/xos/configurations/test-standalone/Makefile
@@ -41,7 +41,7 @@
sudo docker cp ../../../apiary.apib teststandalone_xos_1:/opt/xos/tests/api/apiary.apib
sudo docker exec -i teststandalone_xos_1 bash -c "cd /opt/xos/tests/api; npm test"
-test-tosca:
+test-tosca: restore-initial-db-status
sudo docker-compose run xos bash -c "cd /opt/xos/tosca/tests; python ./alltests.py"
base-container:
diff --git a/xos/tests/api/helpers/before_test.py b/xos/tests/api/helpers/before_test.py
new file mode 100644
index 0000000..e53c323
--- /dev/null
+++ b/xos/tests/api/helpers/before_test.py
@@ -0,0 +1,270 @@
+import dredd_hooks as hooks
+import sys
+
+# HELPERS
+# NOTE move in separated module
+import os
+import sys
+sys.path.append("/opt/xos")
+os.environ.setdefault("DJANGO_SETTINGS_MODULE", "xos.settings")
+import django
+from core.models import *
+from services.cord.models import *
+from services.vtr.models import *
+import urllib2
+import json
+django.setup()
+
+
+def doLogin(username, password):
+ url = "http://127.0.0.1:8000/xoslib/login?username=%s&password=%s" % (username, password)
+ res = urllib2.urlopen(url).read()
+ parsed = json.loads(res)
+ return {'token': parsed['xoscsrftoken'], 'sessionid': parsed['xossessionid']}
+
+
+def cleanDB():
+ # deleting all subscribers
+ for s in CordSubscriberRoot.objects.all():
+ s.delete(purge=True)
+
+ # deleting all slices
+ for s in Slice.objects.all():
+ s.delete(purge=True)
+
+ # deleting all Services
+ for s in Service.objects.all():
+ s.delete(purge=True)
+
+ # deleting all Tenants
+ for s in Tenant.objects.all():
+ s.delete(purge=True)
+
+ # deleting all Networks
+ for s in Network.objects.all():
+ s.delete(purge=True)
+
+ # deleting all NetworkTemplates
+ for s in NetworkTemplate.objects.all():
+ s.delete(purge=True)
+
+ for s in NetworkSlice.objects.all():
+ s.delete(purge=True)
+
+ for s in AddressPool.objects.all():
+ s.delete(purge=True)
+
+ for s in Flavor.objects.all():
+ s.delete(purge=True)
+
+ for s in Image.objects.all():
+ s.delete(purge=True)
+
+ # print 'DB Cleaned'
+
+
+def createTestSubscriber():
+
+ cleanDB()
+ createFlavors()
+
+ # load user
+ user = User.objects.get(email="padmin@vicci.org")
+
+ # network template
+ private_template = NetworkTemplate()
+ private_template.name = 'Private Network'
+ private_template.save()
+
+ # creating the test subscriber
+ subscriber = CordSubscriberRoot(name='Test Subscriber 1', id=1)
+ subscriber.save()
+
+ # vRouter service
+ vrouter_service = VRouterService()
+ vrouter_service.name = 'service_vrouter'
+ vrouter_service.save()
+
+ # address pools
+ ap_vsg = AddressPool()
+ ap_vsg.service = vrouter_service
+ ap_vsg.name = 'addresses_vsg'
+ ap_vsg.addresses = '10.168.0.0'
+ ap_vsg.gateway_ip = '10.168.0.1'
+ ap_vsg.gateway_mac = '02:42:0a:a8:00:01'
+ ap_vsg.save()
+
+ # print 'vRouter created'
+
+ # Site
+ site = Site.objects.get(name='MySite')
+
+ # vSG service
+ vsg_service = VSGService()
+ vsg_service.name = 'service_vsg'
+
+ # vSG slice
+ vsg_slice = Slice(id=2)
+ vsg_slice.name = site.login_base + "_testVsg"
+ vsg_slice.service = vsg_service.id
+ vsg_slice.site = site
+ vsg_slice.caller = user
+
+ vsg_slice.save()
+
+ vsg_service.save()
+
+ # volt service
+ volt_service = VOLTService()
+ volt_service.name = 'service_volt'
+ volt_service.save()
+
+ # cvpe image
+ createImage('ubuntu-vcpe4')
+
+ # vcpe slice
+ vcpe_slice = Slice(id=3)
+ vcpe_slice.name = site.login_base + "_testVcpe"
+ vcpe_slice.service = Service.objects.get(kind='vCPE')
+ vcpe_slice.site = site
+ vcpe_slice.caller = user
+ vcpe_slice.save()
+
+ # print 'vcpe_slice created'
+
+ # create a lan network
+ lan_net = Network()
+ lan_net.name = 'lan_network'
+ lan_net.owner = vcpe_slice
+ lan_net.template = private_template
+ lan_net.save()
+
+ # print 'lan_network created'
+
+ # add relation between vcpe slice and lan network
+ vcpe_network = NetworkSlice()
+ vcpe_network.network = lan_net
+ vcpe_network.slice = vcpe_slice
+ vcpe_network.save()
+
+ # print 'vcpe network relation added'
+
+ # vbng service
+ vbng_service = VBNGService()
+ vbng_service.name = 'service_vbng'
+ vbng_service.save()
+
+ # print 'vbng_service creater'
+
+ # volt tenant
+ vt = VOLTTenant(subscriber=subscriber.id, id=1)
+ vt.s_tag = "222"
+ vt.c_tag = "432"
+ vt.provider_service_id = volt_service.id
+ vt.caller = user
+ vt.save()
+
+ # print "Subscriber Created"
+
+
+def deleteTruckrolls():
+ for s in VTRTenant.objects.all():
+ s.delete(purge=True)
+
+
+def setUpTruckroll():
+ service_vtr = VTRService()
+ service_vtr.name = 'service_vtr'
+ service_vtr.save()
+
+
+def createTruckroll():
+ setUpTruckroll()
+ tn = VTRTenant(id=1)
+ tn.save()
+
+
+def createFlavors():
+ small = Flavor(id=1)
+ small.name = "m1.small"
+ small.save()
+
+ medium = Flavor(id=2)
+ medium.name = "m1.medium"
+ medium.save()
+
+ large = Flavor(id=3)
+ large.name = "m1.large"
+ large.save()
+
+
+def createSlice():
+ site = Site.objects.get(name='MySite')
+ user = User.objects.get(email="padmin@vicci.org")
+
+ sl = Slice(id=1)
+ sl.name = site.login_base + "_testSlice"
+ sl.site = site
+ sl.caller = user
+ sl.save()
+ return sl
+
+
+def createDeployment():
+ deployment = Deployment(id=1)
+ deployment.name = 'MyTestDeployment'
+ deployment.save()
+ return deployment
+
+
+def createImage(name):
+ img = Image(id=1)
+ img.name = name
+ img.disk_format = 'QCOW2'
+ img.kind = 'vm'
+ img.save()
+ return img
+
+
+def createNode(deployment):
+ site = Site.objects.get(name='MySite')
+
+ site_deployment = SiteDeployment(id=1)
+ site_deployment.site = site
+ site_deployment.deployment = deployment
+ site_deployment.save()
+
+ node = Node(id=1)
+ node.name = 'test-node'
+ node.site = site
+ node.site_deployment = site_deployment
+ node.save()
+ return node
+
+
+def setupInstance():
+ deployment = createDeployment()
+ sl = createSlice()
+ node = createNode(deployment)
+ img = createImage('test-image')
+ print {'image': img.id, 'deployment': deployment.id, 'slice': sl.id}
+ return {'image': img, 'deployment': deployment, 'slice': sl}
+
+
+def createInstance():
+ requirements = setupInstance()
+ user = User.objects.get(email="padmin@vicci.org")
+
+ instance = Instance(id=1)
+ instance.name = 'test-instance'
+ instance.node = Node.objects.all()[0]
+ instance.image = requirements['image']
+ instance.slice = requirements['slice']
+ instance.deployment = requirements['deployment']
+ instance.caller = user
+ instance.save()
+
+setupInstance()
+# createTestSubscriber()
+# createInstance()
+# createNode()
diff --git a/xos/tests/api/hooks.py b/xos/tests/api/hooks.py
index 03b2ca1..1f4a0ad 100644
--- a/xos/tests/api/hooks.py
+++ b/xos/tests/api/hooks.py
@@ -57,6 +57,9 @@
for s in Flavor.objects.all():
s.delete(purge=True)
+ for s in Image.objects.all():
+ s.delete(purge=True)
+
# print 'DB Cleaned'
@@ -101,7 +104,7 @@
vsg_service.name = 'service_vsg'
# vSG slice
- vsg_slice = Slice()
+ vsg_slice = Slice(id=2)
vsg_slice.name = site.login_base + "_testVsg"
vsg_slice.service = vsg_service.id
vsg_slice.site = site
@@ -116,8 +119,11 @@
volt_service.name = 'service_volt'
volt_service.save()
+ # cvpe image
+ createImage('ubuntu-vcpe4')
+
# vcpe slice
- vcpe_slice = Slice()
+ vcpe_slice = Slice(id=3)
vcpe_slice.name = site.login_base + "_testVcpe"
vcpe_slice.service = Service.objects.get(kind='vCPE')
vcpe_slice.site = site
@@ -127,7 +133,7 @@
# print 'vcpe_slice created'
# create a lan network
- lan_net = Network()
+ lan_net = Network(id=1)
lan_net.name = 'lan_network'
lan_net.owner = vcpe_slice
lan_net.template = private_template
@@ -192,11 +198,71 @@
large.save()
+def createSlice():
+ site = Site.objects.get(name='MySite')
+ user = User.objects.get(email="padmin@vicci.org")
+
+ sl = Slice(id=1)
+ sl.name = site.login_base + "_testSlice"
+ sl.site = site
+ sl.caller = user
+ sl.save()
+ return sl
+
+
def createDeployment():
deployment = Deployment(id=1)
deployment.name = 'MyTestDeployment'
deployment.save()
- print 'Created deployment: ', deployment.id
+ return deployment
+
+
+def createImage(name):
+ img = Image(id=1)
+ img.name = name
+ img.disk_format = 'QCOW2'
+ img.kind = 'vm'
+ img.save()
+ return img
+
+
+def createNode(deployment):
+ site = Site.objects.get(name='MySite')
+
+ site_deployment = SiteDeployment(id=1)
+ site_deployment.site = site
+ site_deployment.deployment = deployment
+ site_deployment.save()
+
+ node = Node(id=1)
+ node.name = 'test-node'
+ node.site = site
+ node.site_deployment = site_deployment
+ node.save()
+ return node
+
+
+def setupInstance():
+ deployment = createDeployment()
+ sl = createSlice()
+ node = createNode(deployment)
+ img = createImage('test-image')
+ # print {'image': img.id, 'deployment': deployment.id, 'slice': sl.id}
+ return {'image': img, 'deployment': deployment, 'slice': sl}
+
+
+def createInstance():
+ requirements = setupInstance()
+ user = User.objects.get(email="padmin@vicci.org")
+
+ instance = Instance(id=1)
+ instance.name = 'test-instance'
+ instance.node = Node.objects.all()[0]
+ instance.image = requirements['image']
+ instance.slice = requirements['slice']
+ instance.deployment = requirements['deployment']
+ instance.caller = user
+ instance.save()
@hooks.before_all
@@ -213,9 +279,15 @@
transaction['request']['headers']['X-CSRFToken'] = auth['token']
transaction['request']['headers']['Cookie'] = "xossessionid=%s; xoscsrftoken=%s" % (auth['sessionid'], auth['token'])
createTestSubscriber()
+ setupInstance()
sys.stdout.flush()
+# @hooks.after_each
+# def my_after_each(transaction):
+# print "-------------------------------- Test end --------------------------------"
+
+
@hooks.before("Truckroll > Truckroll Collection > Create a Truckroll")
def test1(transaction):
setUpTruckroll()
@@ -245,10 +317,31 @@
@hooks.before("Deployments > Deployments > View a Deployment Detail")
-def deployments_collection(transaction):
+def get_deployments(transaction):
createDeployment()
+@hooks.before("Deployments > Deployments > Delete a Deployment")
+def delete_deployments(transaction):
+ createDeployment()
+
+
+@hooks.before("Instances > Instances Collection > Create an Instance")
+def create_instance(transaction):
+ setupInstance()
+ transaction['skip'] = True
+
+
+@hooks.before("Instances > Instances Detail > Get instance details")
+def get_instance(transaction):
+ createInstance()
+
+
+@hooks.before("Instances > Instances Detail > Delete instance")
+def delete_instance(transaction):
+ createInstance()
+
+
@hooks.before("Example > Example Services Collection > List all Example Services")
def exampleTest(transaction):
transaction['skip'] = True
diff --git a/xos/tests/api/source/core/deployment.md b/xos/tests/api/source/core/deployment.md
index d7599f3..764a73f 100644
--- a/xos/tests/api/source/core/deployment.md
+++ b/xos/tests/api/source/core/deployment.md
@@ -41,6 +41,47 @@
}
]
+### Create a deployment [POST]
+
++ Request (application/json)
+
+ {
+ "humanReadableName": "MyDeployment",
+ }
+
++ Response 200 (application/json)
+
+ {
+ "humanReadableName": "MyDeployment",
+ "id": 1,
+ "created": "2016-04-29T16:19:03.549901Z",
+ "updated": "2016-04-29T16:19:05.624151Z",
+ "enacted": null,
+ "policed": null,
+ "backend_register": "{}",
+ "backend_status": "0 - Provisioning in progress",
+ "deleted": false,
+ "write_protect": false,
+ "lazy_blocked": false,
+ "no_sync": true,
+ "name": "MyDeployment",
+ "accessControl": "allow all",
+ "images": [
+ "1"
+ ],
+ "sites": [
+ "1"
+ ],
+ "flavors": [
+ "1",
+ "2",
+ "3"
+ ],
+ "dashboardviews": [
+ "1"
+ ]
+ }
+
### View a Deployment Detail [GET]
+ Parameters
@@ -76,3 +117,10 @@
"3"
]
}
+
+### Delete a Deployment [DELETE]
+
++ Parameters
+ + id: 1 (number) - ID of the Deployment in the form of an integer
+
++ Response 204
\ No newline at end of file
diff --git a/xos/tests/api/source/core/flavors.md b/xos/tests/api/source/core/flavors.md
index cb63a57..aba5a6b 100644
--- a/xos/tests/api/source/core/flavors.md
+++ b/xos/tests/api/source/core/flavors.md
@@ -33,6 +33,39 @@
}
]
+### Create a Flavor [POST]
+
++ Request (application/json)
+
+ {
+ "humanReadableName": "mq.test",
+ }
+
++ Response 200 (application/json)
+
+ {
+ "humanReadableName": "m1.large",
+ "id": 1,
+ "created": "2016-04-29T16:19:01.979548Z",
+ "updated": "2016-04-29T16:19:03.568238Z",
+ "enacted": null,
+ "policed": null,
+ "backend_register": "{}",
+ "backend_status": "0 - Provisioning in progress",
+ "deleted": false,
+ "write_protect": false,
+ "lazy_blocked": false,
+ "no_sync": true,
+ "name": "m1.large",
+ "description": null,
+ "flavor": "m1.large",
+ "order": 0,
+ "default": false,
+ "deployments": [
+ "1"
+ ]
+ }
+
### View a Flavors Detail [GET]
+ Parameters
@@ -61,4 +94,11 @@
"deployments": [
"1"
]
- }
\ No newline at end of file
+ }
+
+### Delete a Flavors Detail [DELETE]
+
++ Parameters
+ + id: 1 (number) - ID of the Flavors in the form of an integer
+
++ Response 204
\ No newline at end of file
diff --git a/xos/tests/api/source/core/instances.md b/xos/tests/api/source/core/instances.md
index 4b95259..9caf93e 100644
--- a/xos/tests/api/source/core/instances.md
+++ b/xos/tests/api/source/core/instances.md
@@ -2,7 +2,10 @@
List of the XOS instances
-## Instances [/api/core/instances/{id}/]
+## Instances Collection [/api/core/instances/{?no_hyperlinks}]
+
+ + no_hyperlinks (number, optional) - Wheter to return relation with links or ids
+ + Default: `0`
### List all Instances [GET]
@@ -43,4 +46,104 @@
]
}
]
-
\ No newline at end of file
+
+### Create an Instance [POST]
+
++ Parameters
+ + no_hyperlinks: 1
+
++ Request (application/json)
+
+ {
+ "name": "test-instance",
+ "image": 1,
+ "slice": 1,
+ "deployment": 1,
+ "node": 1
+ }
+
++ Response 200 (application/json)
+
+ {
+ "id": 1,
+ "humanReadableName": "uninstantiated-1",
+ "created": "2016-04-26T00:36:22.465259Z",
+ "updated": "2016-04-26T00:36:22.465288Z",
+ "enacted": null,
+ "policed": null,
+ "backend_register": "{}",
+ "backend_status": "0 - Provisioning in progress",
+ "deleted": false,
+ "write_protect": false,
+ "lazy_blocked": false,
+ "no_sync": false,
+ "instance_id": null,
+ "instance_uuid": null,
+ "name": "test-instance",
+ "instance_name": null,
+ "ip": null,
+ "image": "1",
+ "creator": "1",
+ "slice": "1",
+ "deployment": "1",
+ "node": "1",
+ "numberCores": 0,
+ "flavor": "1",
+ "userData": null,
+ "isolation": "vm",
+ "volumes": "/etc/dnsmasq.d,/etc/ufw",
+ "parent": null,
+ "networks": [
+ "1"
+ ]
+ }
+
+## Instances Detail [/api/core/instances/{id}/]
+
+### Get instance details [GET]
+
++ Parameters
+ + id: 1 (number) - ID of the Instance in the form of an integer
+
++ Response 200 (application/json)
+
+ {
+ "id": 1,
+ "humanReadableName": "uninstantiated-1",
+ "created": "2016-04-26T00:36:22.465259Z",
+ "updated": "2016-04-26T00:36:22.465288Z",
+ "enacted": null,
+ "policed": null,
+ "backend_register": "{}",
+ "backend_status": "0 - Provisioning in progress",
+ "deleted": false,
+ "write_protect": false,
+ "lazy_blocked": false,
+ "no_sync": false,
+ "instance_id": null,
+ "instance_uuid": null,
+ "name": "mysite_vcpe",
+ "instance_name": null,
+ "ip": null,
+ "image": "1",
+ "creator": "1",
+ "slice": "1",
+ "deployment": "1",
+ "node": "1",
+ "numberCores": 0,
+ "flavor": "1",
+ "userData": null,
+ "isolation": "vm",
+ "volumes": "/etc/dnsmasq.d,/etc/ufw",
+ "parent": null,
+ "networks": [
+ "1"
+ ]
+ }
+
+### Delete instance [DELETE]
+
++ Parameters
+ + id: 1 (number) - ID of the Instance in the form of an integer
+
++ Response 204
\ No newline at end of file
diff --git a/xos/xos/settings.py b/xos/xos/settings.py
index 0343adc..dad7888 100644
--- a/xos/xos/settings.py
+++ b/xos/xos/settings.py
@@ -30,7 +30,7 @@
GEOIP_PATH = "/usr/share/GeoIP"
XOS_DIR = "/opt/xos"
-DEBUG = False
+DEBUG = True
TEMPLATE_DEBUG = DEBUG
ADMINS = (