Adds support to deploy already created DU

This patch adds support to deploy a DU image
that is available in glance.

Change-Id: I8f3fddad005baaf054d8a41a2b14029dce6633ab
Partial-Bug:#1535462
This commit is contained in:
Devdatta Kulkarni 2016-01-21 19:36:17 -06:00
parent 002fd5faa1
commit ebda9cd07e
8 changed files with 125 additions and 15 deletions

View File

@ -51,6 +51,7 @@ class Workflow(wtypes.Base):
source = {wtypes.text: wtypes.text}
config = {wtypes.text: wtypes.text}
actions = [wtypes.text]
du_id = wtypes.text
status = wtypes.text
result = wtypes.text
scale_target = wtypes.text

View File

@ -12,6 +12,7 @@
# License for the specific language governing permissions and limitations
# under the License.
from oslo_config import cfg
import pecan
from pecan import rest
import wsmeext.pecan as wsme_pecan
@ -20,12 +21,15 @@ from solum.api.controllers.v1.datamodel import workflow
from solum.api.controllers.v1 import userlog as userlog_controller
from solum.api.handlers import app_handler
from solum.api.handlers import workflow_handler as wf_handler
from solum.common import clients
from solum.common import exception
from solum.common import request
from solum.openstack.common import log as logging
LOG = logging.getLogger(__name__)
cfg.CONF.import_opt('image_storage', 'solum.worker.config', group='worker')
class WorkflowController(rest.RestController):
"""Manages operations on a single workflow."""
@ -87,9 +91,16 @@ class WorkflowsController(rest.RestController):
data.source = app_model.source
wf_data = data.as_dict(workflow.Workflow)
du_id = None
if data.du_id:
du_id = data.du_id
self._verify_du_exists(pecan.request.security_context, du_id)
return workflow.Workflow.from_db_model(handler.create(wf_data,
commit_sha='',
status_url=''),
status_url='',
du_id=du_id),
pecan.request.host_url)
@exception.wrap_pecan_controller_exception
@ -102,3 +113,22 @@ class WorkflowsController(rest.RestController):
pecan.request.host_url)
for obj in handler.get_all(app_id=self.app_id)]
return all_wfs
def _verify_du_exists(self, ctxt, du_id):
du_image_backend = cfg.CONF.worker.image_storage
if du_image_backend.lower() == 'glance':
self._verify_du_image_exists_in_glance(ctxt, du_id)
elif du_image_backend.lower() == 'swift':
self._verify_du_image_exists_in_swift(ctxt, du_id)
else:
raise exception.BadRequest(message="DU image id not recognized.")
return
def _verify_du_image_exists_in_glance(self, ctxt, du_id):
osc = clients.OpenStackClients(ctxt)
osc.glance().images.get(du_id)
return
def _verify_du_image_exists_in_swift(self, du_id):
# TODO(devkulkarni): Check if specified du_id exists in swift
return

View File

@ -127,7 +127,8 @@ class AppHandler(handler.Handler):
'config': app.workflow_config,
'actions': wf
}
wfhand.create(wfdata, commit_sha=commit_sha, status_url=status_url)
wfhand.create(wfdata, commit_sha=commit_sha, status_url=status_url,
du_id=None)
def get_all(self):
"""Return all apps."""

View File

@ -89,7 +89,7 @@ class WorkflowHandler(handler.Handler):
db_obj = objects.registry.Workflow.get_by_uuid(self.context, id)
db_obj.destroy(self.context)
def create(self, data, commit_sha, status_url):
def create(self, data, commit_sha, status_url, du_id):
"""Create a new workflow."""
db_obj = objects.registry.Workflow()
db_obj.id = str(uuid.uuid4())
@ -120,7 +120,8 @@ class WorkflowHandler(handler.Handler):
workflow.Workflow.insert(self.context, db_obj)
self._execute_workflow_actions(db_obj, app_obj, assem,
commit_sha=app_obj.source['revision'])
commit_sha=app_obj.source['revision'],
du_id=du_id)
# TODO(devkulkarni): Update status of actions
@ -137,7 +138,8 @@ class WorkflowHandler(handler.Handler):
def _execute_workflow_actions(self, wf_obj, app_obj, assem,
verb='launch_workflow',
commit_sha='', status_url=None):
commit_sha='', status_url=None,
du_id=None):
image = objects.registry.Image()
image.name = app_obj.name
@ -182,7 +184,8 @@ class WorkflowHandler(handler.Handler):
assembly_id=assem.id,
workflow=assem.workflow,
test_cmd=test_cmd,
run_cmd=run_cmd)
run_cmd=run_cmd,
du_id=du_id)
class PlanAssemblyAdapter():

View File

@ -91,7 +91,8 @@ class TestWorkflowHandler(base.BaseTestCase):
handler = workflow_handler.WorkflowHandler(self.ctx)
res = handler.create(workflow_data, commit_sha='', status_url='')
res = handler.create(workflow_data, commit_sha='', status_url='',
du_id='')
self.assertEqual(wf_obj, res)
git_info = {
'source_url': app_obj.source['repository'],
@ -105,4 +106,4 @@ class TestWorkflowHandler(base.BaseTestCase):
git_info=git_info, test_cmd=test_cmd, ports=app_obj.ports,
base_image_id=fi.base_image_id,
source_format=fi.source_format,
image_format=fi.image_format, run_cmd=run_cmd)
image_format=fi.image_format, run_cmd=run_cmd, du_id='')

View File

@ -20,6 +20,7 @@ import uuid
import mock
from oslo_config import cfg
from solum.common import exception
from solum.openstack.common.gettextutils import _
from solum.tests import base
from solum.tests import fakes
@ -89,6 +90,58 @@ class HandlerTest(base.BaseTestCase):
super(HandlerTest, self).setUp()
self.ctx = utils.dummy_context()
@mock.patch('solum.common.clients.OpenStackClients')
def test_get_du_details_glance(self, mock_client):
handler = shell_handler.Handler()
du_id = 'dummy_du_id'
cfg.CONF.set_override('image_storage', 'glance',
group='worker')
fake_du = fakes.FakeImage()
fake_du.id = 2
fake_du.name = 'name'
mock_glance = mock_client.return_value.glance
mock_get = mock_glance.return_value.images.get
mock_get.return_value = fake_du
du_loc, du_name = handler.get_du_details(self.ctx, du_id)
self.assertTrue(mock_get.called)
self.assertTrue(du_loc, 2)
self.assertTrue(du_name, 'name')
@mock.patch('solum.common.clients.OpenStackClients')
def test_get_du_details_GLANCE(self, mock_client):
handler = shell_handler.Handler()
du_id = 'dummy_du_id'
cfg.CONF.set_override('image_storage', 'GLANCE',
group='worker')
fake_du = fakes.FakeImage()
fake_du.id = 2
fake_du.name = 'name'
mock_glance = mock_client.return_value.glance
mock_get = mock_glance.return_value.images.get
mock_get.return_value = fake_du
du_loc, du_name = handler.get_du_details(self.ctx, du_id)
self.assertTrue(mock_get.called)
self.assertTrue(du_loc, 2)
self.assertTrue(du_name, 'name')
@mock.patch('solum.common.clients.OpenStackClients')
def test_get_du_details_swift(self, mock_client):
handler = shell_handler.Handler()
du_id = 'dummy_du_id'
cfg.CONF.set_override('image_storage', 'swift',
group='worker')
try:
handler.get_du_details(self.ctx, du_id)
self.assertTrue(False)
except exception.NotImplemented:
self.assertTrue(True)
@mock.patch('solum.worker.handlers.shell.Handler._get_environment')
@mock.patch('solum.objects.registry')
@mock.patch('solum.conductor.api.API.update_assembly')
@ -223,7 +276,7 @@ class HandlerTest(base.BaseTestCase):
workflow=['unittest', 'build', 'deploy'], ports=[80],
name='new_app', base_image_id=self.base_image_id,
source_format='heroku', image_format='docker', assembly_id=44,
test_cmd=None, run_cmd=None)
test_cmd=None, run_cmd=None, du_id=None)
proj_dir = os.path.abspath(os.path.join(os.path.dirname(__file__),
'..', '..', '..', '..'))
@ -289,7 +342,7 @@ class HandlerTest(base.BaseTestCase):
workflow=['unitetst', 'build', 'deploy'], ports=[80],
name='new_app', base_image_id=self.base_image_id,
source_format='heroku', image_format='docker', assembly_id=44,
test_cmd=None, run_cmd=None)
test_cmd=None, run_cmd=None, du_id=None)
proj_dir = os.path.abspath(os.path.join(os.path.dirname(__file__),
'..', '..', '..', '..'))
@ -497,7 +550,7 @@ class HandlerTest(base.BaseTestCase):
workflow=['unittest', 'build', 'deploy'], ports=[80],
name='new_app', base_image_id=self.base_image_id,
source_format='heroku', image_format='docker', assembly_id=44,
test_cmd='faketests', run_cmd=None)
test_cmd='faketests', run_cmd=None, du_id=None)
proj_dir = os.path.abspath(os.path.join(os.path.dirname(__file__),
'..', '..', '..', '..'))
@ -553,7 +606,8 @@ class HandlerTest(base.BaseTestCase):
self.ctx, build_id=5, git_info=git_info, name='new_app',
base_image_id=self.base_image_id, source_format='chef',
image_format='docker', assembly_id=44, ports=[80],
test_cmd='faketests', run_cmd=None, workflow=['unittest', 'build'])
test_cmd='faketests', run_cmd=None, workflow=['unittest', 'build'],
du_id=None)
proj_dir = os.path.abspath(os.path.join(os.path.dirname(__file__),
'..', '..', '..', '..'))

View File

@ -28,12 +28,12 @@ class API(service.API):
def build_app(self, verb, build_id, git_info, ports, name, base_image_id,
source_format, image_format, assembly_id, workflow,
test_cmd=None, run_cmd=None):
test_cmd=None, run_cmd=None, du_id=None):
self._cast(verb, build_id=build_id, git_info=git_info, ports=ports,
name=name, base_image_id=base_image_id,
source_format=source_format, image_format=image_format,
assembly_id=assembly_id, workflow=workflow,
test_cmd=test_cmd, run_cmd=run_cmd)
test_cmd=test_cmd, run_cmd=run_cmd, du_id=du_id)
def build_lp(self, image_id, git_info, name, source_format, image_format,
artifact_type):

View File

@ -163,6 +163,23 @@ class Handler(object):
def echo(self, ctxt, message):
LOG.debug("%s" % message)
@exception.wrap_keystone_exception
def get_du_details(self, ctxt, du_id):
du_loc = None
du_name = None
du_image_backend = cfg.CONF.worker.image_storage
if du_image_backend.lower() == 'glance':
img = clients.OpenStackClients(ctxt).glance().images.get(du_id)
du_loc = img.id
du_name = img.name
elif du_image_backend.lower() == 'swift':
raise exception.NotImplemented()
else:
LOG.error("Invalid image storage option.")
raise exception.ResourceNotFound()
return du_loc, du_name
@exception.wrap_keystone_exception
def _get_environment(self, ctxt, source_uri, assembly_id=None,
test_cmd=None, run_cmd=None, lp_access=None):
@ -328,7 +345,8 @@ class Handler(object):
def launch_workflow(self, ctxt, build_id, git_info, ports, name,
base_image_id, source_format, image_format,
assembly_id, workflow, test_cmd, run_cmd):
assembly_id, workflow, test_cmd, run_cmd, du_id):
if 'unittest' in workflow:
if self._do_unittest(ctxt, build_id, git_info, name, base_image_id,
source_format, image_format, assembly_id,
@ -343,6 +361,8 @@ class Handler(object):
image_format, assembly_id, run_cmd)
if 'deploy' in workflow:
if du_id:
du_image_loc, du_image_name = self.get_du_details(ctxt, du_id)
if du_image_loc and du_image_name:
self._do_deploy(ctxt, assembly_id, ports, du_image_loc,
du_image_name)