Exemplo n.º 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 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)
Exemplo n.º 2
0
             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
Exemplo n.º 3
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()
                    DContainerNetwork.objects.filter(container=co).delete()
                    for lo in DContainerLink.objects.filter(destination=co):
                        dnet_remove(network=lo.name)
                    # Reset all ports to a published state (if any)
                    for po in DPort.objects.filter(container=co):
                        po.publish = True
                        po.save()
            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")
                ports_publish = request.data.get("edit_ports")
                cnets_map = request.data.get("cnets")
                update_mode = request.data.get("update_mode")
                live = False
                if request.data.get("update_mode") == "live":
                    live = True
                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()
                if (update_mode == "normal") and bool(ports_publish):
                    for p in ports_publish.keys():
                        po = DPort.objects.get(id=p)
                        pub = ports_publish[p]
                        po.publish = True
                        if pub == "unchecked":
                            po.publish = False
                        po.save()
                if bool(update_mode):
                    # Reset all existing rocknets
                    for co in DContainer.objects.filter(rockon=rockon):
                        for cno in DContainerNetwork.objects.filter(
                                container=co.id):
                            dnet_disconnect(co.name,
                                            cno.connection.docker_name)
                        DContainerNetwork.objects.filter(container=co).delete()
                    # Create new one(s)
                    if bool(cnets_map):
                        for c in cnets_map.keys():
                            # Create new entries for updated rocknets settings
                            for net in cnets_map[c]:
                                if not BridgeConnection.objects.filter(
                                        docker_name=net).exists():
                                    dnet_create(network=net)
                                    self._refresh_connections()
                                brco = BridgeConnection.objects.get(
                                    docker_name=net)
                                co = DContainer.objects.get(rockon=rockon,
                                                            name=c)
                                cno = DContainerNetwork(container=co,
                                                        connection=brco)
                                cno.save()
                rockon.state = "pending_update"
                rockon.save()
                update. async (rockon.id, live=live)
            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)
Exemplo n.º 4
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()