summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore3
-rw-r--r--mongodb/docker-compose.yml30
-rw-r--r--mongodb/mongo-init-opendc-db.sh173
-rwxr-xr-xmongodb/prefab.py110
-rwxr-xr-xmongodb/prefabs.py124
5 files changed, 399 insertions, 41 deletions
diff --git a/.gitignore b/.gitignore
index ea273d96..8d2a8cda 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,6 +6,7 @@ keys.json
# pyenv version files
.python-version
+mongodb/opendc_testing/*
# macOS-specific files
-.DS_Store
+.DS_Store \ No newline at end of file
diff --git a/mongodb/docker-compose.yml b/mongodb/docker-compose.yml
new file mode 100644
index 00000000..0253cd7d
--- /dev/null
+++ b/mongodb/docker-compose.yml
@@ -0,0 +1,30 @@
+version: "3"
+services:
+ mongo:
+ build:
+ context: ./
+ restart: on-failure
+ environment:
+ MONGO_INITDB_ROOT_USERNAME: root
+ MONGO_INITDB_ROOT_PASSWORD: rootpassword
+ MONGO_INITDB_DATABASE: admin
+ OPENDC_DB: opendc
+ OPENDC_DB_USERNAME: opendc
+ OPENDC_DB_PASSWORD: opendcpassword
+ ports:
+ - 27017:27017
+ #volumes:
+ # - mongo-volume:/data/db
+
+ mongo-express:
+ image: mongo-express
+ restart: on-failure
+ ports:
+ - 8082:8081
+ environment:
+ ME_CONFIG_MONGODB_ADMINUSERNAME: root
+ ME_CONFIG_MONGODB_ADMINPASSWORD: rootpassword
+
+volumes:
+ mongo-volume:
+ external: false \ No newline at end of file
diff --git a/mongodb/mongo-init-opendc-db.sh b/mongodb/mongo-init-opendc-db.sh
index ed33e955..965698e7 100644
--- a/mongodb/mongo-init-opendc-db.sh
+++ b/mongodb/mongo-init-opendc-db.sh
@@ -12,43 +12,136 @@ MONGO_ROOT_CMD="mongo $OPENDC_DB --host localhost --port 27017 -u $MONGO_INITDB_
#echo 'Creating opendc db schema...'
MONGO_CMD="mongo $OPENDC_DB -u $OPENDC_DB_USERNAME -p $OPENDC_DB_PASSWORD --authenticationDatabase $OPENDC_DB"
-$MONGO_CMD --eval 'db.createCollection("environments", {
- validator: {
- $jsonSchema: {
- bsonType: "object",
- required: ["name"],
- properties: {
- name: {
- bsonType: "string",
- description: "The name of the environment i.e. Production, or Compute Cluster"
- },
- datacenters: {
- bsonType: "object",
- required: ["name, location, length, width, height"],
- properties: {
- name: {
- bsonType: "string",
- description: "The name of the datacenter i.e. eu-west-1, or Science Building"
- },
- location: {
- bsonType: "string",
- description: "The location of the datacenter i.e. Frankfurt, or De Boelelaan 1105"
- },
- length: {
- bsonType: "double",
- description: "The physical length of the datacenter, in centimetres"
- },
- width: {
- bsonType: "double",
- description: "The physical width of the datacenter, in centimetres"
- },
- height: {
- bsonType: "double",
- description: "The physical height of the datacenter, in centimetres"
- }
- }
- }
- }
- }
- }
-});' \ No newline at end of file
+$MONGO_CMD --eval 'db.createCollection("prefabs");'
+
+$MONGO_CMD --eval 'db.prefabs.insertOne(
+ {
+ "type": "rack",
+ "name": "test_rack3",
+ "size": 42,
+ "depth": 42,
+ "author": "Jacob Burley",
+ "visibility": "public",
+ "children": [
+ {
+ "type": "switch",
+ "ports": 48,
+ "power_draw": 150,
+ "psus": 1,
+ "size": 1
+ },
+ {
+ "type": "chassis",
+ "size": 4,
+ "children": [
+ {
+ "type": "mainboard",
+ "sockets": 1,
+ "dimm_slots": 4,
+ "nics": 1,
+ "pcie_slots": 2,
+ "children": [
+ {
+ "type": "CPU",
+ "coreCount": 4,
+ "SMT": true,
+ "base_clk": 3.5,
+ "boost_clk": 3.9,
+ "brand": "Intel",
+ "SKU": "i7-3770K",
+ "socket": "LGA1155",
+ "TDP": 77
+ },
+ {
+ "type": "DDR3",
+ "capacity": 4096,
+ "memfreq": 1333,
+ "ecc": false
+ },
+ {
+ "type": "DDR3",
+ "capacity": 4096,
+ "memfreq": 1333,
+ "ecc": false
+ },
+ {
+ "type": "DDR3",
+ "capacity": 4096,
+ "memfreq": 1333,
+ "ecc": false
+ },
+ {
+ "type": "DDR3",
+ "capacity": 4096,
+ "memfreq": 1333,
+ "ecc": false
+ },
+ {
+ "type": "GPU",
+ "VRAM": 8192,
+ "coreCount": 2304,
+ "brand": "AMD",
+ "technologies": "OpenCL",
+ "pcie_gen": "3x16",
+ "tdp": 169,
+ "slots": 2
+ }
+ ]
+ },
+ {
+ "type": "PSU",
+ "wattage": 550,
+ "ac": true
+ },
+ {
+ "type": "disk",
+ "size": 2000,
+ "interface": "SATA",
+ "media": "flash",
+ "form_factor": 2.5
+ }
+ ]
+ }
+ ]
+ });'
+
+# $MONGO_CMD --eval 'db.createCollection("prefabs", {
+# validator: {
+# $jsonSchema: {
+# bsonType: "object",
+# required: ["name"],
+# properties: {
+# name: {
+# bsonType: "string",
+# description: "The name of the environment i.e. Production, or Compute Cluster"
+# },
+# datacenters: {
+# bsonType: "object",
+# required: ["name, location, length, width, height"],
+# properties: {
+# name: {
+# bsonType: "string",
+# description: "The name of the datacenter i.e. eu-west-1, or Science Building"
+# },
+# location: {
+# bsonType: "string",
+# description: "The location of the datacenter i.e. Frankfurt, or De Boelelaan 1105"
+# },
+# length: {
+# bsonType: "double",
+# description: "The physical length of the datacenter, in centimetres"
+# },
+# width: {
+# bsonType: "double",
+# description: "The physical width of the datacenter, in centimetres"
+# },
+# height: {
+# bsonType: "double",
+# description: "The physical height of the datacenter, in centimetres"
+# }
+# }
+# }
+# }
+# }
+# }
+# });' \ No newline at end of file
diff --git a/mongodb/prefab.py b/mongodb/prefab.py
new file mode 100755
index 00000000..1ce355fd
--- /dev/null
+++ b/mongodb/prefab.py
@@ -0,0 +1,110 @@
+#!/Users/jacobburley/thesis-src/opendc/mongodb/opendc_testing/bin/python3
+#Change shebang to /usr/bin/python3 before using with docker
+# encoding: utf-8
+"""
+prefab
+
+CLI frontend for viewing, modifying and creating prefabs in OpenDC.
+
+"""
+import sys
+import prefabs
+
+def usage():
+ print("Usage: prefab add <prefab>: imports a prefab from YML or JSON")
+ print(" list: lists all (public) prefabs")
+ print(" export <prefab> [json|yaml]: exports the specified prefab to the specified filetype (with JSON used by default)")
+
+def interactive(): #interactive CLI mode: recommended
+ print("OpenDC Prefab CLI")
+ running = True
+ while(exit):
+ print(">", end=" ")
+ try:
+ command = input()
+ command = command.split()
+ except EOFError as e:
+ print("exit")
+ print("bye!")
+ exit()
+ except KeyboardInterrupt as KI:
+ print("\nbye!")
+ exit()
+ if(len(command) >= 1):
+ if(command[0] == "exit"):
+ print("bye!")
+ exit()
+ elif(command[0] == "list"): # decrypt
+ prefabs.list()
+ elif(command[0] == "help"): # decrypt
+ usage()
+ elif(command[0] == "add"):
+ if(len(command) == 3):
+ prefabs.add(command[1], command[2])
+ else:
+ prefabs.add(command[1], None)
+ elif(command[0] == "clone"):
+ if(len(command) == 3):
+ prefabs.clone(command[1], command[2])
+ else:
+ prefabs.clone(command[1], None)
+ elif(command[0] == "export"):
+ #print(sys.argv[2])
+ prefabs.export(command[1], "json")
+ elif(command[0] == "remove"):
+ print("WARNING: Doing so will permanently remove the specified prefab. \nThis action CANNOT be undone. Please type the name of the prefab to confirm deletion.")
+ confirm = input()
+ if confirm == command[1]:
+ prefabs.remove(command[1])
+ print(f'Prefab {command[1]} has been removed.')
+ else:
+ print("Confirmation failed. The prefab has not been removed.")
+ else:
+ print("prefabs: try 'help' for more information\n")
+ else:
+ print("prefabs: try 'help' for more information\n")
+
+
+def main():
+ if(len(sys.argv) >= 2):
+ if(sys.argv[1] == "list"): # decrypt
+ prefabs.list()
+ exit()
+ #elif(sys.argv[1] == "-e"): # encrypt
+ # encrypt(sys.argv[2], sys.argv[3], sys.argv[4])
+ #elif(sys.argv[1] == "-v"): # verify
+ # verify(sys.argv[2], sys.argv[3], sys.argv[4])
+ elif(sys.argv[1] == "help"): # decrypt
+ usage()
+ exit()
+ elif(sys.argv[1] == "add"):
+ if(sys.argv[3]):
+ prefabs.add(sys.argv[2], sys.argv[3])
+ else:
+ prefabs.add(sys.argv[2])
+ exit()
+ elif(sys.argv[1] == "export"):
+ #print(sys.argv[2])
+ prefabs.export(sys.argv[2], "json")
+ exit()
+ elif(sys.argv[1] == "remove"):
+ print("WARNING: Doing so will permanently remove the specified prefab. \nThis action CANNOT be undone. Please type the name of the prefab to confirm deletion.")
+ confirm = input()
+ if confirm == sys.argv[2]:
+ prefabs.remove(sys.argv[2])
+ print(f'Prefab {sys.argv[2]} has been removed.')
+ else:
+ print("Confirmation failed. The prefab has not been removed.")
+ exit()
+ else:
+ print("prefabs: try 'prefabs help' for more information\n")
+ elif(len(sys.argv) == 1):
+ interactive()
+
+ else:
+ # print "Incorrect number of arguments!\n"
+ print("prefabs: try 'prefabs help' for more information\n")
+
+
+if __name__ == "__main__":
+ main() \ No newline at end of file
diff --git a/mongodb/prefabs.py b/mongodb/prefabs.py
new file mode 100755
index 00000000..f6f46cbc
--- /dev/null
+++ b/mongodb/prefabs.py
@@ -0,0 +1,124 @@
+#!/Users/jacobburley/thesis-src/opendc/mongodb/opendc_testing/bin/python3
+#Change shebang to /usr/bin/python3 before using with docker
+# encoding: utf-8
+"""
+prefabs
+
+Python Library for interacting with mongoDB prefabs collection.
+
+"""
+import urllib.parse
+import pprint
+import sys
+import os
+import json
+import re
+import ujson
+#import pyyaml
+
+from pymongo import MongoClient
+from bson.json_util import loads, dumps, RELAXED_JSON_OPTIONS, CANONICAL_JSON_OPTIONS
+
+#mongodb_opendc_db = os.environ['OPENDC_DB']
+#mongodb_opendc_user = os.environ['OPENDC_DB_USERNAME']
+#mongodb_opendc_password = os.environ['OPENDC_DB_PASSWORD']
+
+#if mongodb_opendc_db == None or mongodb_opendc_user == None or mongodb_opendc_password == None:
+# print("One or more environment variables are not set correctly. \nYou may experience issues connecting to the mongodb database.")
+
+user = urllib.parse.quote_plus('opendc') #TODO: replace this with environment variable
+password = urllib.parse.quote_plus('opendcpassword') #TODO: same as above
+database = urllib.parse.quote_plus('opendc')
+
+client = MongoClient('mongodb://%s:%s@localhost/default_db?authSource=%s' % (user, password, database))
+opendcdb = client.opendc
+prefabs_collection = opendcdb.prefabs
+
+
+def add(prefab_file, name):
+ if(re.match(r"\w+(\\\ \w*)*\.json", prefab_file)):
+ try:
+ with open(prefab_file, "r") as json_file:
+ json_prefab = json.load(json_file)
+ #print(json_prefab)
+ if name != None:
+ json_prefab["name"] = name
+ try:
+ prefab_id = prefabs_collection.insert(json_prefab)
+ except ConnectionFailure:
+ print("ERROR: Could not connect to the mongoDB database.")
+ except DuplicateKeyError:
+ print("ERROR: A prefab with the same unique ID already exists in the database. \nPlease remove the '_id' before trying again.\nYour prefab has not been imported.")
+ except:
+ print("ERROR: A general error has occurred. Your prefab has not been imported.")
+ if prefab_id != None:
+ if name != None:
+ print(f'Prefab "{name}" has been imported successfully.')
+ else:
+ print(f'Prefab "{prefab_file}" has been imported successfully.')
+ except FileNotFoundError:
+ print(f"ERROR: {prefab_file} could not be found in the specified path. No prefabs have been imported.")
+ elif(re.match(r"\w+(\\\ \w*)*\.yml", prefab_file)):
+ print("expecting a yaml file here")
+ #yaml
+ else:
+ print("The filetype provided is an unsupported filetype.")
+ #unsupported filetype
+
+def clone(prefab_name, new_name):
+ bson = prefabs_collection.find_one({'name': prefab_name})
+ json_string = dumps(bson) #convert BSON representation to JSON
+ chosen_prefab = json.loads(json_string) #load as a JSON object
+
+ chosen_prefab.pop("_id") # clean out our _id field from the export: mongo will generate a new one if this is imported back in
+
+ if new_name != None:
+ chosen_prefab["name"] = new_name
+ try:
+ prefab_id = prefabs_collection.insert_one(chosen_prefab)
+ except ConnectionFailure:
+ print("ERROR: Could not connect to the mongoDB database.")
+ except:
+ print("ERROR: A general error has occurred. Your selected prefab has not been cloned.")
+ if prefab_id != None:
+ if new_name != None:
+ print(f'Prefab "{prefab_name}" has been cloned successfully as {new_name}.')
+ else:
+ print(f'Prefab "{prefab_name}" has been cloned successfully.')
+
+def export(prefab_name, type):
+ bson = prefabs_collection.find_one({'name': prefab_name})
+ json_string = dumps(bson) #convert BSON representation to JSON
+ chosen_prefab = json.loads(json_string) #load as a JSON object
+
+ chosen_prefab.pop("_id") # clean out our _id field from the export: mongo will generate a new one if this is imported back in
+
+ with open(f'{prefab_name}.json', 'w', encoding='utf8') as f:
+ json.dump(chosen_prefab, f, ensure_ascii=False, indent=4)
+ print(f'Prefab {prefab_name} written to {os.getcwd()}/{prefab_name}.json.')
+ #pprint.pprint(json_string)
+ #pprint.pprint(json.loads(str(json_string)))
+
+def list():
+ #TODO: why does it output in single quotations?
+ cursor = prefabs_collection.find()
+ prefabs = []
+ for record in cursor:
+ #pprint.pprint(record)
+ #print(record)
+ json_string = dumps(record, json_options=RELAXED_JSON_OPTIONS) ##pymongo retrieves BSON objects, which need to be converted to json for pythons json module
+ prefabs.append(json.loads(json_string))
+
+ #print(f'There are {str(len(prefabs))} prefabs in the database. They are:')
+ print("Name Author")
+ for prefab in prefabs:
+ if(prefab['visibility'] == "private"):
+ continue
+ print(f"{prefab['name']} {prefab['author']}")
+ #pprint.pprint(prefab)
+
+
+def remove(prefab_name):
+ prefabs_collection.delete_one({'name': prefab_name})
+
+