Example #1
0
    def post(self, request, rid, command):
        with self._handle_exception(request):

            if (not docker_status()):
                e_msg = ('Docker service is not running. Start it and try '
                         'again.')
                handle_exception(Exception(e_msg), request)

            try:
                rockon = RockOn.objects.get(id=rid)
            except:
                e_msg = ('Rock-on(%d) does not exist' % rid)
                handle_exception(Exception(e_msg), request)

            try:
                dname = 'ztask-daemon'
                e_msg = ('ztask daemon is not running and could not be started')
                o, e, rc = superctl(dname, 'status')
                if (rc == 1):
                    superctl(dname, 'restart')
                    time.sleep(5)
            except Exception, e:
                logger.exception(e)
                handle_exception(Exception(e_msg), request)
            finally:
Example #2
0
 def get_queryset(self, *args, **kwargs):
     if (docker_status()):
         pending_rids = {}
         failed_rids = {}
         for t in Task.objects.filter(
                 function_name__regex='rockon_helpers'):
             rid = pickle.loads(t.args)[0]
             if (t.retry_count == 0 and t.failed is not None):
                 failed_rids[rid] = t
             else:
                 pending_rids[rid] = t
         #Remove old failed attempts
         #@todo: we should prune all failed tasks of the past, not here though.
         for rid in pending_rids.keys():
             if (rid in failed_rids):
                 pt = pending_rids[rid]
                 ft = failed_rids[rid]
                 if (failed_rids[rid].created > pending_rids[rid].created):
                     #this should never be the case. pending tasks either
                     #succeed and get deleted or they are marked failed.
                     msg = ('Found a failed Task(%s) in the future of a '
                            'pending Task(%s).' % (ft.uuid, pt.uuid))
                     handle_exception(Exception(msg), self.request)
                 failed_rids[rid].delete()
                 logger.debug('deleted failed task')
                 del failed_rids[rid]
         for ro in RockOn.objects.all():
             if (ro.state == 'installed'):
                 # update current running status of installed rockons.
                 if (ro.id not in pending_rids):
                     ro.status = rockon_status(ro.name)
             elif (re.search('pending', ro.state) is not None):
                 if (ro.id in failed_rids):
                     #we update the status on behalf of the task runner
                     func_name = t.function_name.split('.')[-1]
                     ro.state = '%s_failed' % func_name
                 elif (ro.id not in pending_rids):
                     logger.error(
                         'Rockon(%s) is in pending state but there '
                         'is no pending or failed task for it. ' % ro.name)
                     ro.state = '%s_failed' % ro.state.split('_')[1]
                 else:
                     logger.debug('Rockon(%s) is in pending state' %
                                  ro.name)
             elif (ro.state == 'uninstall_failed'):
                 ro.state = 'installed'
             ro.save()
     return RockOn.objects.filter().order_by('name')
Example #3
0
 def get_queryset(self, *args, **kwargs):
     if docker_status():
         pending_rids = {}
         failed_rids = {}
         for t in Task.objects.filter(
                 function_name__regex="rockon_helpers"):  # noqa E501
             rid = pickle.loads(t.args)[0]
             if t.retry_count == 0 and t.failed is not None:
                 failed_rids[rid] = t
             else:
                 pending_rids[rid] = t
         # Remove old failed attempts @todo: we should prune all failed
         # tasks of the past, not here though.
         for rid in pending_rids.keys():
             if rid in failed_rids:
                 pt = pending_rids[rid]
                 ft = failed_rids[rid]
                 if failed_rids[rid].created > pending_rids[rid].created:
                     # this should never be the case. pending tasks either
                     # succeed and get deleted or they are marked failed.
                     msg = ("Found a failed Task ({}) in the future of a "
                            "pending Task ({}).").format(ft.uuid, pt.uuid)
                     handle_exception(Exception(msg), self.request)
                 failed_rids[rid].delete()
                 del failed_rids[rid]
         for ro in RockOn.objects.all():
             if ro.state == "installed":
                 # update current running status of installed rockons.
                 if ro.id not in pending_rids:
                     ro.status = rockon_status(ro.name)
             elif re.search("pending", ro.state) is not None:
                 if ro.id in failed_rids:
                     # we update the status on behalf of the task runner
                     func_name = t.function_name.split(".")[-1]
                     ro.state = "%s_failed" % func_name
                 elif ro.id not in pending_rids:
                     logger.error(("Rockon ({}) is in pending state but "
                                   "there is no pending or failed task "
                                   "for it.").format(ro.name))
                     ro.state = "%s_failed" % ro.state.split("_")[1]
                 else:
                     logger.debug(
                         ("Rockon ({}) is in pending state.").format(
                             ro.name))
             elif ro.state == "uninstall_failed":
                 ro.state = "installed"
             ro.save()
     return RockOn.objects.filter().order_by("name")
Example #4
0
 def get_queryset(self, *args, **kwargs):
     if (docker_status()):
         pending_rids = {}
         failed_rids = {}
         for t in Task.objects.filter(function_name__regex='rockon_helpers'):
             rid = pickle.loads(t.args)[0]
             if (t.retry_count == 0 and t.failed is not None):
                 failed_rids[rid] = t
             else:
                 pending_rids[rid] = t
         #Remove old failed attempts
         #@todo: we should prune all failed tasks of the past, not here though.
         for rid in pending_rids.keys():
             if (rid in failed_rids):
                 pt = pending_rids[rid]
                 ft = failed_rids[rid]
                 if (failed_rids[rid].created > pending_rids[rid].created):
                     #this should never be the case. pending tasks either
                     #succeed and get deleted or they are marked failed.
                     msg = ('Found a failed Task(%s) in the future of a '
                            'pending Task(%s).' % (ft.uuid, pt.uuid))
                     handle_exception(Exception(msg), self.request)
                 failed_rids[rid].delete()
                 logger.debug('deleted failed task')
                 del failed_rids[rid]
         for ro in RockOn.objects.all():
             if (ro.state == 'installed'):
                 # update current running status of installed rockons.
                 if (ro.id not in pending_rids):
                     ro.status = rockon_status(ro.name)
             elif (re.search('pending', ro.state) is not None):
                 if (ro.id in failed_rids):
                     #we update the status on behalf of the task runner
                     func_name = t.function_name.split('.')[-1]
                     ro.state = '%s_failed' % func_name
                 elif (ro.id not in pending_rids):
                     logger.error('Rockon(%s) is in pending state but there '
                                  'is no pending or failed task for it. '
                                  % ro.name)
                     ro.state = '%s_failed' % ro.state.split('_')[1]
                 else:
                     logger.debug('Rockon(%s) is in pending state' % ro.name)
             elif (ro.state == 'uninstall_failed'):
                 ro.state = 'installed'
             ro.save()
     return RockOn.objects.filter().order_by('name')
Example #5
0
 def get_queryset(self, *args, **kwargs):
     if docker_status():
         pending_rids = {}
         failed_rids = {}
         for t in Task.objects.filter(function_name__regex="rockon_helpers"):
             rid = pickle.loads(t.args)[0]
             if t.retry_count == 0 and t.failed is not None:
                 failed_rids[rid] = t
             else:
                 pending_rids[rid] = t
         # Remove old failed attempts
         # @todo: we should prune all failed tasks of the past, not here though.
         for rid in pending_rids.keys():
             if rid in failed_rids:
                 pt = pending_rids[rid]
                 ft = failed_rids[rid]
                 if failed_rids[rid].created > pending_rids[rid].created:
                     # this should never be the case. pending tasks either
                     # succeed and get deleted or they are marked failed.
                     msg = "Found a failed Task(%s) in the future of a " "pending Task(%s)." % (ft.uuid, pt.uuid)
                     handle_exception(Exception(msg), self.request)
                 failed_rids[rid].delete()
                 logger.debug("deleted failed task")
                 del failed_rids[rid]
         for ro in RockOn.objects.all():
             if ro.state == "installed":
                 # update current running status of installed rockons.
                 if ro.id not in pending_rids:
                     ro.status = rockon_status(ro.name)
             elif re.search("pending", ro.state) is not None:
                 if ro.id in failed_rids:
                     # we update the status on behalf of the task runner
                     func_name = t.function_name.split(".")[-1]
                     ro.state = "%s_failed" % func_name
                 elif ro.id not in pending_rids:
                     logger.error(
                         "Rockon(%s) is in pending state but there "
                         "is no pending or failed task for it. " % ro.name
                     )
                     ro.state = "%s_failed" % ro.state.split("_")[1]
                 else:
                     logger.debug("Rockon(%s) is in pending state" % ro.name)
             elif ro.state == "uninstall_failed":
                 ro.state = "installed"
             ro.save()
     return RockOn.objects.filter().order_by("name")
Example #6
0
 def get_queryset(self, *args, **kwargs):
     if (docker_status()):
         pending_rids = []
         for t in Task.objects.all():
             pending_rids.append(pickle.loads(t.args)[0])
         for ro in RockOn.objects.all():
             if (ro.state == 'installed'):
                 # update current running status of installed rockons.
                 ro.status = rockon_status(ro.name)
             elif (re.search('pending', ro.state) is not None and
                   ro.id not in pending_rids):
                 # reset rockons to their previosu state if they are stuck
                 # in a pending transition.
                 if (re.search('uninstall', ro.state) is not None):
                     ro.state = 'installed'
                 else:
                     ro.state = 'available'
             ro.save()
     return RockOn.objects.filter().order_by('-id')
Example #7
0
    def post(self, request, rid, command):
        with self._handle_exception(request):

            if (not docker_status()):
                e_msg = ('Docker service is not running. Start it and try '
                         'again.')
                handle_exception(Exception(e_msg), request)

            try:
                rockon = RockOn.objects.get(id=rid)
            except:
                e_msg = ('Rock-on(%d) does not exist' % rid)
                handle_exception(Exception(e_msg), request)

            try:
                dname = 'ztask-daemon'
                e_msg = ('ztask daemon is not running and could not be '
                         'started')
                o, e, rc = superctl(dname, 'status')
                if (rc == 1):
                    superctl(dname, 'restart')
                    time.sleep(5)
            except Exception as e:
                logger.exception(e)
                handle_exception(Exception(e_msg), request)
            finally:
                if (rc == 1):
                    o, e, rc = superctl(dname, 'status')
                    if (rc == 1):
                        handle_exception(Exception(e_msg), request)

            if (command == 'install'):
                self._pending_check(request)
                share_map = request.data.get('shares', {})
                port_map = request.data.get('ports', {})
                cc_map = request.data.get('cc', {})
                env_map = request.data.get('environment', {})
                containers = DContainer.objects.filter(rockon=rockon)
                for co in containers:
                    for sname in share_map.keys():
                        dest_dir = share_map[sname]
                        if (not Share.objects.filter(name=sname).exists()):
                            e_msg = ('Invalid Share(%s).' % sname)
                            handle_exception(Exception(e_msg), request)
                        if (DVolume.objects.filter(
                                container=co, dest_dir=dest_dir).exists()):
                            so = Share.objects.get(name=sname)
                            vo = DVolume.objects.get(container=co,
                                                     dest_dir=dest_dir)
                            vo.share = so
                            vo.save()
                    # {'host_port' : 'container_port', ... }
                    for p in port_map.keys():
                        if (DPort.objects.filter(hostp=p).exists()):
                            dup_po = DPort.objects.get(hostp=p)
                            if (dup_po.container.rockon.id != rockon.id):
                                if (dup_po.container.rockon.state
                                        in ('installed', 'pending_install')):
                                    # cannot claim from a rock-on that's
                                    # installed.
                                    conf_ro = dup_po.container.rockon.name
                                    e_msg = (
                                        'Port(%s) belongs to another '
                                        'Rock-n(%s). Choose a different '
                                        'port. If you must choose the same '
                                        'port, uninstall %s first and try '
                                        'again.' % (p, conf_ro, conf_ro))
                                    handle_exception(Exception(e_msg), request)
                                # change the host port to next available.
                                dup_po.hostp = self._next_available_default_hostp(
                                    dup_po.hostp)  # noqa E501
                                dup_po.save()
                        for co2 in DContainer.objects.filter(rockon=rockon):
                            if (DPort.objects.filter(
                                    container=co2,
                                    containerp=port_map[p]).exists()):
                                # found the container that needs this port.
                                po = DPort.objects.get(container=co2,
                                                       containerp=port_map[p])
                                po.hostp = p
                                po.save()
                                break
                    for c in cc_map.keys():
                        if (not DCustomConfig.objects.filter(rockon=rockon,
                                                             key=c).exists()):
                            e_msg = ('Invalid custom config key(%s)' % c)
                            handle_exception(Exception(e_msg), request)
                        cco = DCustomConfig.objects.get(rockon=rockon, key=c)
                        cco.val = cc_map[c]
                        cco.save()
                    for e in env_map.keys():
                        if (not DContainerEnv.objects.filter(container=co,
                                                             key=e).exists()):
                            e_msg = ('Invalid environment variabled(%s)' % e)
                            handle_exception(Exception(e_msg), request)
                        ceo = DContainerEnv.objects.get(container=co, key=e)
                        ceo.val = env_map[e]
                        ceo.save()
                install. async (rockon.id)
                rockon.state = 'pending_install'
                rockon.save()
            elif (command == 'uninstall'):
                self._pending_check(request)
                if (rockon.state != 'installed'):
                    e_msg = ('Rock-on(%s) is not currently installed. Cannot '
                             'uninstall it' % rockon.name)
                    handle_exception(Exception(e_msg), request)
                if (rockon.status == 'started'
                        or rockon.status == 'pending_start'):
                    e_msg = ('Rock-on(%s) must be stopped before it can '
                             'be uninstalled. Stop it and try again' %
                             rockon.name)
                    handle_exception(Exception(e_msg), request)
                uninstall. async (rockon.id)
                rockon.state = 'pending_uninstall'
                rockon.save()
                for co in DContainer.objects.filter(rockon=rockon):
                    DVolume.objects.filter(container=co, uservol=True).delete()
            elif (command == 'update'):
                self._pending_check(request)
                if (rockon.state != 'installed'):
                    e_msg = ('Rock-on(%s) is not currently installed. Cannot '
                             'update it' % rockon.name)
                    handle_exception(Exception(e_msg), request)
                if (rockon.status == 'started'
                        or rockon.status == 'pending_start'):
                    e_msg = ('Rock-on(%s) must be stopped before it can '
                             'be updated. Stop it and try again' % rockon.name)
                    handle_exception(Exception(e_msg), request)
                share_map = request.data.get('shares')
                for co in DContainer.objects.filter(rockon=rockon):
                    for s in share_map.keys():
                        sname = share_map[s]
                        if (not Share.objects.filter(name=sname).exists()):
                            e_msg = ('Invalid Share(%s).' % sname)
                            handle_exception(Exception(e_msg), request)
                        so = Share.objects.get(name=sname)
                        if (DVolume.objects.filter(container=co,
                                                   share=so).exists()):
                            e_msg = ('Share(%s) is already assigned to '
                                     'this Rock-on' % sname)
                            handle_exception(Exception(e_msg), request)
                        if (DVolume.objects.filter(container=co,
                                                   dest_dir=s).exists()):
                            e_msg = ('Directory(%s) is already mapped for '
                                     'this Rock-on' % s)
                            handle_exception(Exception(e_msg), request)
                        if (not s.startswith('/')):
                            e_msg = ('Invalid Directory(%s). Must provide an '
                                     'absolute path. Eg: /data/media' % s)
                            handle_exception(Exception(e_msg), request)
                        do = DVolume(container=co,
                                     share=so,
                                     uservol=True,
                                     dest_dir=s)
                        do.save()
                rockon.state = 'pending_update'
                rockon.save()
                update. async (rockon.id)
            elif (command == 'stop'):
                stop. async (rockon.id)
                rockon.status = 'pending_stop'
                rockon.save()
            elif (command == 'start'):
                start. async (rockon.id)
                rockon.status = 'pending_start'
                rockon.save()
            elif (command == 'state_update'):
                state = request.data.get('new_state')
                rockon.state = state
                rockon.save()
            elif (command == 'status_update'):
                status = request.data.get('new_status')
                rockon.status = status
                rockon.save()
            return Response(RockOnSerializer(rockon).data)
Example #8
0
    def post(self, request, command=None):
        with self._handle_exception(request):
            if (not docker_status()):
                e_msg = ('Rock-on service is not running. Start it and try '
                         'again')
                handle_exception(Exception(e_msg), request)

            if (command == 'update'):
                rockons = self._get_available(request)
                for r in rockons:
                    name = r
                    r_d = rockons[r]
                    ro_defaults = {'description': r_d['description'],
                                   'website': r_d['website'],
                                   'version': '1.0',
                                   'state': 'available',
                                   'status': 'stopped'}
                    ro, created = RockOn.objects.get_or_create(name=name,
                                                               defaults=ro_defaults)
                    if (not created):
                        ro.description = ro_defaults['description']
                        ro.website = ro_defaults['website']
                        ro.version = ro_defaults['version']
                    if ('ui' in r_d):
                        ui_d = r_d['ui']
                        ro.link = ui_d['slug']
                        if ('https' in ui_d):
                            ro.https = ui_d['https']
                    if ('icon' in r_d):
                        ro.icon = r_d['icon']
                    if ('volume_add_support' in r_d):
                        ro.volume_add_support = r_d['volume_add_support']
                    if ('more_info' in r_d):
                        ro.more_info = r_d['more_info']
                    ro.save()
                    containers = r_d['containers']
                    for c in containers:
                        c_d = containers[c]
                        io, created = DImage.objects.get_or_create(name=c_d['image'],
                                                                   defaults={'tag': 'latest',
                                                                             'repo': 'na'})
                        co_defaults = {'rockon': ro,
                                       'dimage': io,
                                       'launch_order': c_d['launch_order'],}
                        co, created = DContainer.objects.get_or_create(name=c,
                                                                       defaults=co_defaults)
                        if (co.rockon.name != ro.name):
                            e_msg = ('Container(%s) belongs to another '
                                     'Rock-On(%s). Update rolled back.' %
                                     (c, co.rockon.name))
                            handle_exception(Exception(e_msg), request)
                        if (not created):
                            co.dimage = io
                            co.launch_order = co_defaults['launch_order']
                        co.save()

                        ports = {}
                        if ('ports' in containers[c]):
                            ports = containers[c]['ports']
                            for p in ports:
                                p_d = ports[p]
                                if ('protocol' not in p_d):
                                    p_d['protocol'] = None
                                p = int(p)
                                po = None
                                if (DPort.objects.filter(containerp=p, container=co).exists()):
                                    po = DPort.objects.get(containerp=p, container=co)
                                    po.hostp_default = p_d['host_default']
                                    po.description = p_d['description']
                                    po.protocol = p_d['protocol']
                                    po.label = p_d['label']
                                else:
                                    #let's find next available default if default is already taken
                                    def_hostp = p_d['host_default']
                                    while (True):
                                        if (DPort.objects.filter(hostp=def_hostp).exists()):
                                            def_hostp += 1
                                        else:
                                            break
                                    po = DPort(description=p_d['description'],
                                               hostp=def_hostp, containerp=p,
                                               hostp_default=def_hostp,
                                               container=co,
                                               protocol=p_d['protocol'],
                                               label=p_d['label'])
                                if ('ui' in p_d):
                                    po.uiport = p_d['ui']
                                if (po.uiport):
                                    ro.ui = True
                                    ro.save()
                                po.save()
                        ports = [int(p) for p in ports]
                        for po in DPort.objects.filter(container=co):
                            if (po.containerp not in ports):
                                po.delete()

                        v_d = {}
                        if ('volumes' in c_d):
                            v_d = c_d['volumes']
                            for v in v_d:
                                cv_d = v_d[v]
                                vo_defaults = {'description': cv_d['description'],
                                               'label': cv_d['label']}
                                vo, created = DVolume.objects.get_or_create(dest_dir=v, container=co,
                                                                            defaults=vo_defaults)
                                if (not created):
                                    vo.description = vo_defaults['description']
                                    vo.label = vo_defaults['label']
                                if ('min_size' in cv_d):
                                    vo.min_size = cv_d['min_size']
                                vo.save()
                        for vo in DVolume.objects.filter(container=co):
                            if (vo.dest_dir not in v_d):
                                vo.delete()

                        if ('opts' in containers[c]):
                            options = containers[c]['opts']
                            id_l = []
                            for o in options:
                                #there are no unique constraints on this model, so we need this bandaid.
                                if (ContainerOption.objects.filter(container=co, name=o[0], val=o[1]).count() > 1):
                                    ContainerOption.objects.filter(container=co, name=o[0], val=o[1]).delete()
                                oo, created = ContainerOption.objects.get_or_create(container=co,
                                                                                    name=o[0],
                                                                                    val=o[1])
                                id_l.append(oo.id)
                            for oo in ContainerOption.objects.filter(container=co):
                                if (oo.id not in id_l):
                                    oo.delete()

                    if ('container_links' in r_d):
                        l_d = r_d['container_links']
                        for cname in l_d:
                            ll = l_d[cname]
                            lsources = [l['source_container'] for l in ll]
                            co = DContainer.objects.get(rockon=ro, name=cname)
                            for clo in co.destination_container.all():
                                if (clo.name not in lsources):
                                    clo.delete()
                            for cl_d in ll:
                                sco = DContainer.objects.get(rockon=ro, name=cl_d['source_container'])
                                clo, created = DContainerLink.objects.get_or_create(source=sco,
                                                                                    destination=co)
                                clo.name = cl_d['name']
                                clo.save()

                    cc_d = {}
                    if ('custom_config' in r_d):
                        cc_d = r_d['custom_config']
                        for k in cc_d:
                            ccc_d = cc_d[k]
                            cco, created = DCustomConfig.objects.get_or_create(
                                rockon=ro, key=k,
                                defaults={'description': ccc_d['description'], 'label': ccc_d['label']})
                            if (not created):
                                cco.description = ccc_d['description']
                                cco.label = ccc_d['label']
                                cco.save()
                    for cco in DCustomConfig.objects.filter(rockon=ro):
                        if (cco.key not in cc_d):
                            cco.delete()
            return Response()
Example #9
0
    def post(self, request, rid, command):
        with self._handle_exception(request):

            if not docker_status():
                e_msg = "Docker service is not running. Start it and try again."
                handle_exception(Exception(e_msg), request)

            try:
                rockon = RockOn.objects.get(id=rid)
            except:
                e_msg = "Rock-on ({}) does not exist.".format(rid)
                handle_exception(Exception(e_msg), request)

            try:
                dname = "ztask-daemon"
                e_msg = "ztask daemon is not running and could not be started."
                o, e, rc = superctl(dname, "status")
                if rc == 1:
                    superctl(dname, "restart")
                    time.sleep(5)
            except Exception as e:
                logger.exception(e)
                handle_exception(Exception(e_msg), request)
            finally:
                if rc == 1:
                    o, e, rc = superctl(dname, "status")
                    if rc == 1:
                        handle_exception(Exception(e_msg), request)

            if command == "install":
                self._pending_check(request)
                share_map = request.data.get("shares", {})
                port_map = request.data.get("ports", {})
                dev_map = request.data.get("devices", {})
                cc_map = request.data.get("cc", {})
                env_map = request.data.get("environment", {})
                containers = DContainer.objects.filter(rockon=rockon)
                for co in containers:
                    for sname in share_map.keys():
                        dest_dir = share_map[sname]
                        if not Share.objects.filter(name=sname).exists():
                            e_msg = "Invalid share ({}).".format(sname)
                            handle_exception(Exception(e_msg), request)
                        if DVolume.objects.filter(
                            container=co, dest_dir=dest_dir
                        ).exists():
                            so = Share.objects.get(name=sname)
                            vo = DVolume.objects.get(container=co, dest_dir=dest_dir)
                            vo.share = so
                            vo.save()
                    # {'host_port' : 'container_port', ... }
                    for p in port_map.keys():
                        if DPort.objects.filter(hostp=p).exists():
                            dup_po = DPort.objects.get(hostp=p)
                            if dup_po.container.rockon.id != rockon.id:
                                if dup_po.container.rockon.state in (
                                    "installed",
                                    "pending_install",
                                ):
                                    # cannot claim from a rock-on that's
                                    # installed.
                                    conf_ro = dup_po.container.rockon.name
                                    e_msg = (
                                        "Port ({}) belongs to another "
                                        "rock-on ({}). Choose a different "
                                        "port. If you must choose the same "
                                        "port, uninstall ({}) first and try "
                                        "again."
                                    ).format(p, conf_ro, conf_ro)
                                    handle_exception(Exception(e_msg), request)
                                # change the host port to next available.
                                dup_po.hostp = self._next_available_default_hostp(
                                    dup_po.hostp
                                )  # noqa E501
                                dup_po.save()
                        for co2 in DContainer.objects.filter(rockon=rockon):
                            if DPort.objects.filter(
                                container=co2, containerp=port_map[p]
                            ).exists():
                                # found the container that needs this port.
                                po = DPort.objects.get(
                                    container=co2, containerp=port_map[p]
                                )
                                po.hostp = p
                                po.save()
                                break
                    for d in dev_map.keys():
                        if not DContainerDevice.objects.filter(
                            container=co, dev=d
                        ).exists():
                            e_msg = ("Invalid device variable ({}).").format(d)
                            handle_exception(Exception(e_msg), request)
                        cdo = DContainerDevice.objects.get(container=co, dev=d)
                        cdo.val = dev_map[d]
                        cdo.save()
                    for c in cc_map.keys():
                        if not DCustomConfig.objects.filter(
                            rockon=rockon, key=c
                        ).exists():
                            e_msg = "Invalid custom config key ({}).".format(c)
                            handle_exception(Exception(e_msg), request)
                        cco = DCustomConfig.objects.get(rockon=rockon, key=c)
                        cco.val = cc_map[c]
                        cco.save()
                    for e in env_map.keys():
                        if not DContainerEnv.objects.filter(
                            container=co, key=e
                        ).exists():
                            e_msg = ("Invalid environment variable ({}).").format(e)
                            handle_exception(Exception(e_msg), request)
                        ceo = DContainerEnv.objects.get(container=co, key=e)
                        ceo.val = env_map[e]
                        ceo.save()
                install.async(rockon.id)
                rockon.state = "pending_install"
                rockon.save()
            elif command == "uninstall":
                self._pending_check(request)
                if rockon.state != "installed":
                    e_msg = (
                        "Rock-on ({}) is not currently installed. Cannot "
                        "uninstall it."
                    ).format(rockon.name)
                    handle_exception(Exception(e_msg), request)
                if rockon.status == "started" or rockon.status == "pending_start":
                    e_msg = (
                        "Rock-on ({}) must be stopped before it can "
                        "be uninstalled. Stop it and "
                        "try again."
                    ).format(rockon.name)
                    handle_exception(Exception(e_msg), request)
                uninstall.async(rockon.id)
                rockon.state = "pending_uninstall"
                rockon.save()
                for co in DContainer.objects.filter(rockon=rockon):
                    DVolume.objects.filter(container=co, uservol=True).delete()
                    DContainerLabel.objects.filter(container=co).delete()
            elif command == "update":
                self._pending_check(request)
                if rockon.state != "installed":
                    e_msg = (
                        "Rock-on ({}) is not currently installed. Cannot update it."
                    ).format(rockon.name)
                    handle_exception(Exception(e_msg), request)
                if rockon.status == "started" or rockon.status == "pending_start":
                    e_msg = (
                        "Rock-on ({}) must be stopped before it can "
                        "be updated. Stop it and "
                        "try again."
                    ).format(rockon.name)
                    handle_exception(Exception(e_msg), request)
                share_map = request.data.get("shares")
                label_map = request.data.get("labels")
                if bool(share_map):
                    for co in DContainer.objects.filter(rockon=rockon):
                        for s in share_map.keys():
                            sname = share_map[s]
                            if not Share.objects.filter(name=sname).exists():
                                e_msg = "Invalid share ({}).".format(sname)
                                handle_exception(Exception(e_msg), request)
                            so = Share.objects.get(name=sname)
                            if DVolume.objects.filter(container=co, share=so).exists():
                                e_msg = (
                                    "Share ({}) is already assigned to this rock-on."
                                ).format(sname)
                                handle_exception(Exception(e_msg), request)
                            if DVolume.objects.filter(
                                container=co, dest_dir=s
                            ).exists():
                                e_msg = (
                                    "Directory ({}) is already mapped for "
                                    "this rock-on."
                                ).format(s)
                                handle_exception(Exception(e_msg), request)
                            if not s.startswith("/"):
                                e_msg = (
                                    "Invalid directory ({}). Must provide an "
                                    "absolute path. Eg: "
                                    "(/data/media)."
                                ).format(s)
                                handle_exception(Exception(e_msg), request)
                            do = DVolume(
                                container=co, share=so, uservol=True, dest_dir=s
                            )
                            do.save()
                if bool(label_map):
                    for co in DContainer.objects.filter(rockon=rockon):
                        for c in label_map.keys():
                            cname = label_map[c]
                            coname = co.name
                            if cname != coname:
                                continue
                            lo = DContainerLabel(container=co, key=cname, val=c)
                            lo.save()
                rockon.state = "pending_update"
                rockon.save()
                update.async(rockon.id)
            elif command == "stop":
                stop.async(rockon.id)
                rockon.status = "pending_stop"
                rockon.save()
            elif command == "start":
                start.async(rockon.id)
                rockon.status = "pending_start"
                rockon.save()
            elif command == "state_update":
                state = request.data.get("new_state")
                rockon.state = state
                rockon.save()
            elif command == "status_update":
                status = request.data.get("new_status")
                rockon.status = status
                rockon.save()
            return Response(RockOnSerializer(rockon).data)
Example #10
0
    def post(self, request, command=None):
        with self._handle_exception(request):
            if (not docker_status()):
                e_msg = ('Rock-on service is not running. Start it and try '
                         'again')
                handle_exception(Exception(e_msg), request)

            if (command == 'update'):
                rockons = self._get_available(request)
                for r in rockons.keys():
                    name = r
                    ro = None
                    if (RockOn.objects.filter(name=name).exists()):
                        ro = RockOn.objects.get(name=name)
                        if (ro.state != 'available'):
                            #don't update metadata if it's installed or in some pending state.
                            continue
                        ro.description = rockons[r]['description']
                    else:
                        ro = RockOn(name=name,
                                    description=rockons[r]['description'],
                                    version='1.0', state='available',
                                    status='stopped')
                    ro.save()
                    containers = rockons[r]['containers']
                    for c in containers.keys():
                        io = None
                        iname = containers[c]['image']
                        if (DImage.objects.filter(name=iname).exists()):
                            io = DImage.objects.get(name=iname)
                        else:
                            io = DImage(name=iname, tag='latest', repo='foo')
                        io.save()

                        co = None
                        if (DContainer.objects.filter(name=c).exists()):
                            co = DContainer.objects.get(name=c)
                            co.dimage = io
                            co.rockon = ro
                        else:
                            co = DContainer(rockon=ro, dimage=io, name=c)
                        co.save()

                        if ('ports' in containers[c]):
                            ports = containers[c]['ports']
                            for p in ports.keys():
                                po = None
                                if (DPort.objects.filter(hostp=p).exists()):
                                    po = DPort.objects.get(hostp=p)
                                    po.container = co
                                elif (DPort.objects.filter(containerp=p, container=co).exists()):
                                    po = DPort.objects.get(containerp=p, container=co)
                                    po.hostp = p
                                else:
                                    po = DPort(hostp=p, containerp=p,
                                               container=co)
                                if (ports[p] == 'ui'):
                                    po.uiport = True
                                else:
                                    po.protocol = ports[p]
                                po.save()

                        if ('volumes' in containers[c]):
                            volumes = containers[c]['volumes']
                            for v in volumes:
                                if (not DVolume.objects.filter(
                                        dest_dir=v, container=co).exists()):
                                    vo = DVolume(container=co, dest_dir=v)
                                    vo.save()
                            for vo in DVolume.objects.filter(container=co):
                                if (vo.dest_dir not in volumes):
                                    vo.delete()

                        if ('opts' in containers[c]):
                            options = containers[c]['opts']
                            for o in options.keys():
                                if (not ContainerOption.objects.filter(
                                        container=co, name=options[o]).exists()):
                                    oo = ContainerOption(container=co, name=o,
                                                         val=options[o])
                                    oo.save()

                    if ('custom_config' in rockons[r]):
                        cc_d = rockons[r]['custom_config']
                        for k in cc_d:
                            cco, created = DCustomConfig.objects.get_or_create(
                                rockon=ro, key=k,
                                defaults={'description': cc_d[k]})
                            if (not created):
                                cco.description = cc_d[k]
                            if (not created and k == 'iprange' and ro.name == 'Plex'):
                                from storageadmin.models import NetworkInterface
                                try:
                                    ni = NetworkInterface.objects.filter(itype='management')[0]
                                    cco.val = ('%s/255.255.255.0' % ni.ipaddr)
                                except:
                                    pass
                            cco.save()
                    if ('app_link' in rockons[r]):
                        app_link = rockons[r]['app_link']
                        if (ro.state != 'installed'):
                            ro.link = app_link
                    if ('website' in rockons[r]):
                        ro.website = rockons[r]['website']
                    ro.save()
            return Response()
Example #11
0
    def post(self, request, command=None):
        with self._handle_exception(request):
            if (not docker_status()):
                e_msg = ('Rock-on service is not running. Start it and try '
                         'again')
                handle_exception(Exception(e_msg), request)

            if (command == 'update'):
                rockons = self._get_available(request)
                for r in rockons:
                    name = r
                    r_d = rockons[r]
                    ro_defaults = {
                        'description': r_d['description'],
                        'website': r_d['website'],
                        'version': '1.0',
                        'state': 'available',
                        'status': 'stopped'
                    }
                    ro, created = RockOn.objects.get_or_create(
                        name=name, defaults=ro_defaults)
                    if (not created):
                        ro.description = ro_defaults['description']
                        ro.website = ro_defaults['website']
                        ro.version = ro_defaults['version']
                    if ('ui' in r_d):
                        ui_d = r_d['ui']
                        ro.link = ui_d['slug']
                        if ('https' in ui_d):
                            ro.https = ui_d['https']
                    if ('icon' in r_d):
                        ro.icon = r_d['icon']
                    if ('volume_add_support' in r_d):
                        ro.volume_add_support = r_d['volume_add_support']
                    if ('more_info' in r_d):
                        ro.more_info = r_d['more_info']
                    ro.save()
                    containers = r_d['containers']
                    for c in containers:
                        c_d = containers[c]
                        io, created = DImage.objects.get_or_create(
                            name=c_d['image'],
                            defaults={
                                'tag': 'latest',
                                'repo': 'na'
                            })
                        co_defaults = {
                            'rockon': ro,
                            'dimage': io,
                            'launch_order': c_d['launch_order'],
                        }
                        co, created = DContainer.objects.get_or_create(
                            name=c, defaults=co_defaults)
                        if (co.rockon.name != ro.name):
                            e_msg = ('Container(%s) belongs to another '
                                     'Rock-On(%s). Update rolled back.' %
                                     (c, co.rockon.name))
                            handle_exception(Exception(e_msg), request)
                        if (not created):
                            co.dimage = io
                            co.launch_order = co_defaults['launch_order']
                        co.save()

                        ports = {}
                        if ('ports' in containers[c]):
                            ports = containers[c]['ports']
                            for p in ports:
                                p_d = ports[p]
                                if ('protocol' not in p_d):
                                    p_d['protocol'] = None
                                p = int(p)
                                po = None
                                if (DPort.objects.filter(
                                        containerp=p, container=co).exists()):
                                    po = DPort.objects.get(containerp=p,
                                                           container=co)
                                    po.hostp_default = p_d['host_default']
                                    po.description = p_d['description']
                                    po.protocol = p_d['protocol']
                                    po.label = p_d['label']
                                else:
                                    #let's find next available default if default is already taken
                                    def_hostp = p_d['host_default']
                                    while (True):
                                        if (DPort.objects.filter(
                                                hostp=def_hostp).exists()):
                                            def_hostp += 1
                                        else:
                                            break
                                    po = DPort(description=p_d['description'],
                                               hostp=def_hostp,
                                               containerp=p,
                                               hostp_default=def_hostp,
                                               container=co,
                                               protocol=p_d['protocol'],
                                               label=p_d['label'])
                                if ('ui' in p_d):
                                    po.uiport = p_d['ui']
                                if (po.uiport):
                                    ro.ui = True
                                    ro.save()
                                po.save()
                        ports = [int(p) for p in ports]
                        for po in DPort.objects.filter(container=co):
                            if (po.containerp not in ports):
                                po.delete()

                        v_d = {}
                        if ('volumes' in c_d):
                            v_d = c_d['volumes']
                            for v in v_d:
                                cv_d = v_d[v]
                                vo_defaults = {
                                    'description': cv_d['description'],
                                    'label': cv_d['label']
                                }
                                vo, created = DVolume.objects.get_or_create(
                                    dest_dir=v,
                                    container=co,
                                    defaults=vo_defaults)
                                if (not created):
                                    vo.description = vo_defaults['description']
                                    vo.label = vo_defaults['label']
                                if ('min_size' in cv_d):
                                    vo.min_size = cv_d['min_size']
                                vo.save()
                        for vo in DVolume.objects.filter(container=co):
                            if (vo.dest_dir not in v_d):
                                vo.delete()

                        if ('opts' in containers[c]):
                            options = containers[c]['opts']
                            id_l = []
                            for o in options:
                                #there are no unique constraints on this model, so we need this bandaid.
                                if (ContainerOption.objects.filter(
                                        container=co, name=o[0],
                                        val=o[1]).count() > 1):
                                    ContainerOption.objects.filter(
                                        container=co, name=o[0],
                                        val=o[1]).delete()
                                oo, created = ContainerOption.objects.get_or_create(
                                    container=co, name=o[0], val=o[1])
                                id_l.append(oo.id)
                            for oo in ContainerOption.objects.filter(
                                    container=co):
                                if (oo.id not in id_l):
                                    oo.delete()

                    if ('container_links' in r_d):
                        l_d = r_d['container_links']
                        for cname in l_d:
                            ll = l_d[cname]
                            lsources = [l['source_container'] for l in ll]
                            co = DContainer.objects.get(rockon=ro, name=cname)
                            for clo in co.destination_container.all():
                                if (clo.name not in lsources):
                                    clo.delete()
                            for cl_d in ll:
                                sco = DContainer.objects.get(
                                    rockon=ro, name=cl_d['source_container'])
                                clo, created = DContainerLink.objects.get_or_create(
                                    source=sco, destination=co)
                                clo.name = cl_d['name']
                                clo.save()

                    cc_d = {}
                    if ('custom_config' in r_d):
                        cc_d = r_d['custom_config']
                        for k in cc_d:
                            ccc_d = cc_d[k]
                            cco, created = DCustomConfig.objects.get_or_create(
                                rockon=ro,
                                key=k,
                                defaults={
                                    'description': ccc_d['description'],
                                    'label': ccc_d['label']
                                })
                            if (not created):
                                cco.description = ccc_d['description']
                                cco.label = ccc_d['label']
                                cco.save()
                    for cco in DCustomConfig.objects.filter(rockon=ro):
                        if (cco.key not in cc_d):
                            cco.delete()
            return Response()
Example #12
0
    def post(self, request, rid, command):
        with self._handle_exception(request):

            if (not docker_status()):
                e_msg = ('Docker service is not running. Start it and try '
                         'again.')
                handle_exception(Exception(e_msg), request)

            try:
                rockon = RockOn.objects.get(id=rid)
            except:
                e_msg = ('Rock-on(%d) does not exist' % rid)
                handle_exception(Exception(e_msg), request)

            try:
                dname = 'ztask-daemon'
                e_msg = ('ztask daemon is not running and could not be '
                         'started')
                o, e, rc = superctl(dname, 'status')
                if (rc == 1):
                    superctl(dname, 'restart')
                    time.sleep(5)
            except Exception as e:
                logger.exception(e)
                handle_exception(Exception(e_msg), request)
            finally:
                if (rc == 1):
                    o, e, rc = superctl(dname, 'status')
                    if (rc == 1):
                        handle_exception(Exception(e_msg), request)

            if (command == 'install'):
                self._pending_check(request)
                share_map = request.data.get('shares', {})
                port_map = request.data.get('ports', {})
                cc_map = request.data.get('cc', {})
                env_map = request.data.get('environment', {})
                containers = DContainer.objects.filter(rockon=rockon)
                for co in containers:
                    for sname in share_map.keys():
                        dest_dir = share_map[sname]
                        if (not Share.objects.filter(name=sname).exists()):
                            e_msg = ('Invalid Share(%s).' % sname)
                            handle_exception(Exception(e_msg), request)
                        if (DVolume.objects.filter(
                                container=co, dest_dir=dest_dir).exists()):
                            so = Share.objects.get(name=sname)
                            vo = DVolume.objects.get(container=co,
                                                     dest_dir=dest_dir)
                            vo.share = so
                            vo.save()
                    # {'host_port' : 'container_port', ... }
                    for p in port_map.keys():
                        if (DPort.objects.filter(hostp=p).exists()):
                            dup_po = DPort.objects.get(hostp=p)
                            if (dup_po.container.rockon.id != rockon.id):
                                if (dup_po.container.rockon.state in
                                        ('installed', 'pending_install')):
                                    # cannot claim from a rock-on that's
                                    # installed.
                                    conf_ro = dup_po.container.rockon.name
                                    e_msg = (
                                        'Port(%s) belongs to another '
                                        'Rock-n(%s). Choose a different '
                                        'port. If you must choose the same '
                                        'port, uninstall %s first and try '
                                        'again.' % (p, conf_ro, conf_ro))
                                    handle_exception(Exception(e_msg), request)
                                # change the host port to next available.
                                dup_po.hostp = self._next_available_default_hostp(dup_po.hostp)  # noqa E501
                                dup_po.save()
                        for co2 in DContainer.objects.filter(rockon=rockon):
                            if (DPort.objects.filter(
                                    container=co2,
                                    containerp=port_map[p]).exists()):
                                # found the container that needs this port.
                                po = DPort.objects.get(container=co2,
                                                       containerp=port_map[p])
                                po.hostp = p
                                po.save()
                                break
                    for c in cc_map.keys():
                        if (not DCustomConfig.objects.filter(
                                rockon=rockon, key=c).exists()):
                            e_msg = ('Invalid custom config key(%s)' % c)
                            handle_exception(Exception(e_msg), request)
                        cco = DCustomConfig.objects.get(rockon=rockon, key=c)
                        cco.val = cc_map[c]
                        cco.save()
                    for e in env_map.keys():
                        if (not DContainerEnv.objects.filter(
                                container=co, key=e).exists()):
                            e_msg = ('Invalid environment variabled(%s)' % e)
                            handle_exception(Exception(e_msg), request)
                        ceo = DContainerEnv.objects.get(container=co, key=e)
                        ceo.val = env_map[e]
                        ceo.save()
                install.async(rockon.id)
                rockon.state = 'pending_install'
                rockon.save()
            elif (command == 'uninstall'):
                self._pending_check(request)
                if (rockon.state != 'installed'):
                    e_msg = ('Rock-on(%s) is not currently installed. Cannot '
                             'uninstall it' % rockon.name)
                    handle_exception(Exception(e_msg), request)
                if (rockon.status == 'started' or
                        rockon.status == 'pending_start'):
                    e_msg = ('Rock-on(%s) must be stopped before it can '
                             'be uninstalled. Stop it and try again' %
                             rockon.name)
                    handle_exception(Exception(e_msg), request)
                uninstall.async(rockon.id)
                rockon.state = 'pending_uninstall'
                rockon.save()
                for co in DContainer.objects.filter(rockon=rockon):
                    DVolume.objects.filter(container=co, uservol=True).delete()
            elif (command == 'update'):
                self._pending_check(request)
                if (rockon.state != 'installed'):
                    e_msg = ('Rock-on(%s) is not currently installed. Cannot '
                             'update it' % rockon.name)
                    handle_exception(Exception(e_msg), request)
                if (rockon.status == 'started' or
                        rockon.status == 'pending_start'):
                    e_msg = ('Rock-on(%s) must be stopped before it can '
                             'be updated. Stop it and try again' %
                             rockon.name)
                    handle_exception(Exception(e_msg), request)
                share_map = request.data.get('shares')
                for co in DContainer.objects.filter(rockon=rockon):
                    for s in share_map.keys():
                        sname = share_map[s]
                        if (not Share.objects.filter(name=sname).exists()):
                            e_msg = ('Invalid Share(%s).' % sname)
                            handle_exception(Exception(e_msg), request)
                        so = Share.objects.get(name=sname)
                        if (DVolume.objects.filter(
                                container=co, share=so).exists()):
                            e_msg = ('Share(%s) is already assigned to '
                                     'this Rock-on' % sname)
                            handle_exception(Exception(e_msg), request)
                        if (DVolume.objects.filter(
                                container=co, dest_dir=s).exists()):
                            e_msg = ('Directory(%s) is already mapped for '
                                     'this Rock-on' % s)
                            handle_exception(Exception(e_msg), request)
                        if (not s.startswith('/')):
                            e_msg = ('Invalid Directory(%s). Must provide an '
                                     'absolute path. Eg: /data/media' % s)
                            handle_exception(Exception(e_msg), request)
                        do = DVolume(container=co, share=so, uservol=True,
                                     dest_dir=s)
                        do.save()
                rockon.state = 'pending_update'
                rockon.save()
                update.async(rockon.id)
            elif (command == 'stop'):
                stop.async(rockon.id)
                rockon.status = 'pending_stop'
                rockon.save()
            elif (command == 'start'):
                start.async(rockon.id)
                rockon.status = 'pending_start'
                rockon.save()
            elif (command == 'state_update'):
                state = request.data.get('new_state')
                rockon.state = state
                rockon.save()
            elif (command == 'status_update'):
                status = request.data.get('new_status')
                rockon.status = status
                rockon.save()
            return Response(RockOnSerializer(rockon).data)