staffeln api.
diff --git a/staffeln/api/app.py b/staffeln/api/app.py
index 90f35df..e75a5c7 100755
--- a/staffeln/api/app.py
+++ b/staffeln/api/app.py
@@ -1,21 +1,60 @@
from flask import Flask
+from flask import Response
from flask import jsonify
from flask import request
+from staffeln import objects
+from staffeln.common import context
+from staffeln.common import auth
+from oslo_log import log
+from openstack import exceptions as exc
+ctx = context.make_context()
app = Flask(__name__)
+LOG = log.getLogger(__name__)
-@app.route('/')
-def hello_world():
- return 'This is my first API call!'
+conn = auth.create_connection()
-@app.route('/post', methods=["POST"])
-def testpost():
- input_json = request.get_json(force=True)
- dictToReturn = {'text': input_json['text']}
- return jsonify(dictToReturn)
+@app.route("/v1/backup", methods=["GET"])
+def backup_id():
+ if "backup_id" not in request.args:
+ # Return error if the backup_id argument is not provided.
+ return "Error: No backup_id field provided. Please specify backup_id."
+
+ backup_id = request.args["backup_id"]
+ # Retrive the backup object from backup_data table with matching backup_id.
+ backup_info = objects.Volume.get_backup_by_backup_id(ctx, backup_id)
+ # backup_info is None when there is no entry of the backup id in backup_table.
+ if backup_info is None:
+ LOG.info("No record of backup in storage. Checking cloud for backup")
+ try:
+ backup = conn.block_storage.get_backup(backup_id)
+ except exc.ResourceNotFound:
+ return Response(
+ "Backup Resource not found for the provided backup id.",
+ status=404,
+ mimetype="text/plain",
+ )
+ except:
+ return Response("Internal Server Error.", status=500, mimetype="text/plain")
+ metadata = backup.metadata
+ if metadata is not None:
+ if metadata["__automated_backup"] is True:
+ return Response("Deny", status=401, mimetype="text/plain")
+
+ return Response(
+ "True",
+ status=200,
+ mimetype="text/plain",
+ )
+ metadata = backup_info.backup_metadata
+ if metadata["__automated_backup"] is True:
+ return Response("Deny", status=401, mimetype="text/plain")
+ else:
+ return Response("True", status=200, mimetype="text/plain")
+
def run(host, port, ssl_context):
app.run(host=host, port=port, ssl_context=ssl_context)
diff --git a/staffeln/db/sqlalchemy/api.py b/staffeln/db/sqlalchemy/api.py
index 83bb484..d16766f 100644
--- a/staffeln/db/sqlalchemy/api.py
+++ b/staffeln/db/sqlalchemy/api.py
@@ -181,7 +181,7 @@
query = query.filter(getattr(model, fieldname) == value)
try:
- obj = query.one()
+ obj = query.one_or_none()
except exc.NoResultFound:
LOG.error("ResourceNotFound")
@@ -280,7 +280,7 @@
)
def update_queue(self, id, values):
- print(self._update(models.Queue_data, id, values))
+
try:
return self._update(models.Queue_data, id, values)
except:
@@ -306,3 +306,21 @@
return self._soft_delete(models.Queue_data, id)
except:
LOG.error("Queue Not found.")
+
+ def get_backup_by_backup_id(self, context, backup_id):
+ """Get the column from the backup_data with matching backup_id"""
+
+ try:
+ return self._get_backup(context, fieldname="backup_id", value=backup_id)
+ except:
+ LOG.error("Backup not found with backup_id %s." % backup_id)
+
+ def _get_backup(self, context, fieldname, value):
+ """Get the column from the volume_data table"""
+
+ try:
+ return self._get(
+ context, model=models.Backup_data, fieldname=fieldname, value=value
+ )
+ except:
+ LOG.error("Backup resource not found.")
diff --git a/staffeln/db/sqlalchemy/models.py b/staffeln/db/sqlalchemy/models.py
index 715d747..7ec8a4e 100644
--- a/staffeln/db/sqlalchemy/models.py
+++ b/staffeln/db/sqlalchemy/models.py
@@ -4,18 +4,12 @@
from oslo_db.sqlalchemy import models
from oslo_serialization import jsonutils
-from sqlalchemy import Boolean
from sqlalchemy import Column
from sqlalchemy import DateTime
from sqlalchemy.ext.declarative import declarative_base
-from sqlalchemy import Float
-from sqlalchemy import ForeignKey
from sqlalchemy import Integer
-from sqlalchemy import LargeBinary
-from sqlalchemy import orm
-from sqlalchemy import Numeric
from sqlalchemy import String
-from sqlalchemy import Text
+from sqlalchemy import JSON
from sqlalchemy.types import TypeDecorator, TEXT
from sqlalchemy import UniqueConstraint
import urllib.parse as urlparse
@@ -65,6 +59,7 @@
volume_id = Column(String(100))
instance_id = Column(String(100))
backup_completed = Column(Integer())
+ backup_metadata = Column(JSON(), nullable=True)
class Queue_data(Base):
diff --git a/staffeln/objects/volume.py b/staffeln/objects/volume.py
index 3933bdf..62ed2b4 100644
--- a/staffeln/objects/volume.py
+++ b/staffeln/objects/volume.py
@@ -17,6 +17,7 @@
"instance_id": sfeild.StringField(),
"volume_id": sfeild.UUIDField(),
"backup_completed": sfeild.IntegerField(),
+ "backup_metadata": sfeild.JsonField(),
}
@base.remotable_classmethod
@@ -33,7 +34,6 @@
def create(self):
"""Create a :class:`Backup_data` record in the DB"""
values = self.obj_get_changes()
- print(values)
db_backup = self.dbapi.create_backup(values)
self._from_db_object(self, db_backup)
@@ -59,3 +59,22 @@
"""
current = self.get_by_uuid(backup_id=self.backup_id)
self.obj_refresh(current)
+
+ @base.remotable_classmethod
+ def get_backup_by_backup_id(cls, context, backup_id):
+ """Find a backup based on backup_id
+ :param context: Security context. NOTE: This should only
+ be used internally by the indirection_api.
+ Unfortunately, RPC requires context as the first
+ argument, even though we don't use it.
+ A context should be set when instantiating the
+ object, e.g.: Queue(context)
+ :param backup_id: the backup id of volume in volume data.
+ :returns: a :class:`Backup` object.
+ """
+ db_backup = cls.dbapi.get_backup_by_backup_id(context, backup_id)
+ if db_backup is None:
+ return db_backup
+ else:
+ backup = cls._from_db_object(cls(context), db_backup)
+ return backup