Ejemplo n.º 1
0
    def _create_update_meta(self, name, r_d):
        #Update our application state with any changes from hosted app
        #profiles(app.json files). Some attributes cannot be updated
        #if the Rock-on is currently installed. These will be logged and
        #ignored.
        ro_defaults = {
            'description': r_d['description'],
            'website': r_d['website'],
            'version': r_d['version'],
            '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']
        cur_containers = [
            co.name for co in DContainer.objects.filter(rockon=ro)
        ]
        if (len(set(containers.keys()) ^ set(cur_containers)) != 0):
            if (ro.state != 'available'):
                e_msg = ('Cannot add/remove container definitions for %s as '
                         'it is not in available state. Uninstall the '
                         'Rock-on first and try again.' % ro.name)
                handle_exception(Exception(e_msg), self.request)
            #rock-on is in available state. we can safely wipe metadata
            #and start fresh.
            DContainer.objects.filter(rockon=ro).delete()

        for c in containers:
            c_d = containers[c]
            co = None
            if (DContainer.objects.filter(name=c).exists()):
                co = DContainer.objects.get(name=c)
                if (co.rockon.id != ro.id):
                    e_msg = ('Duplicate container(%s) definition detected. '
                             'It belongs to another Rock-on(%s). Uninstall '
                             'one of them and try again.' %
                             (co.name, co.rockon.name))
                    handle_exception(Exception(e_msg), self.request)

                if (co.dimage.name != c_d['image']):
                    if (ro.state != 'available'):
                        e_msg = ('Cannot change image of the container(%s) '
                                 'as it belongs to an installed Rock-on(%s). '
                                 'Uninstall it first and try again.' %
                                 (co.name, ro.name))
                        handle_exception(Exception(e_msg), self.request)
                    co.dimage.delete()
            if (co is None):
                co = DContainer(name=c, rockon=ro)
            defaults = {
                'tag': c_d.get('tag', 'latest'),
                'repo': 'na',
            }
            io, created = DImage.objects.get_or_create(name=c_d['image'],
                                                       defaults=defaults)
            co.dimage = io
            co.launch_order = c_d['launch_order']
            if ('uid' in c_d):
                co.uid = int(c_d['uid'])
            co.save()

            ports = containers[c].get('ports', {})
            cur_ports = [
                po.containerp for po in DPort.objects.filter(container=co)
            ]
            if (len(set(map(int, ports.keys())) ^ set(cur_ports)) != 0):
                if (ro.state != 'available'):
                    e_msg = ('Cannot add/remove port definitions of the '
                             'container(%s) as it belongs to an installed '
                             'Rock-on(%s). Uninstall it first and try again.' %
                             (co.name, ro.name))
                    handle_exception(Exception(e_msg), self.request)
                DPort.objects.filter(container=co).delete()

            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)
                    if (po.hostp_default != p_d['host_default']):
                        po.hostp_default = self._next_available_default_hostp(
                            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 = self._next_available_default_hostp(
                        p_d['host_default'])
                    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()

            v_d = c_d.get('volumes', {})
            cur_vols = [
                vo.dest_dir for vo in DVolume.objects.filter(container=co)
            ]
            if (len(set(v_d.keys()) ^ set(cur_vols)) != 0):
                if (ro.state != 'available'):
                    e_msg = ('Cannot add/remove volume definitions of the '
                             'container(%s) as it belongs to an installed '
                             'Rock-on(%s). Uninstall it first and try again.' %
                             (co.name, ro.name))
                    handle_exception(Exception(e_msg), self.request)
                DVolume.objects.filter(container=co).delete()

            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()

            self._update_env(co, c_d)
            options = containers[c].get('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()

        l_d = r_d.get('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()
        self._update_cc(ro, r_d)
Ejemplo n.º 2
0
    def _create_update_meta(self, name, r_d):
        #Update our application state with any changes from hosted app
        #profiles(app.json files). Some attributes cannot be updated
        #if the Rock-on is currently installed. These will be logged and
        #ignored.
        ro_defaults = {'description': r_d['description'],
                       'website': r_d['website'],
                       'version': r_d['version'],
                       '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']
        cur_containers = [co.name for co in
                          DContainer.objects.filter(rockon=ro)]
        if (len(set(containers.keys()) ^ set(cur_containers)) != 0):
            if (ro.state != 'available'):
                e_msg = ('Cannot add/remove container definitions for %s as '
                         'it is not in available state. Uninstall the '
                         'Rock-on first and try again.' % ro.name)
                handle_exception(Exception(e_msg), self.request)
            #rock-on is in available state. we can safely wipe metadata
            #and start fresh.
            DContainer.objects.filter(rockon=ro).delete()

        for c in containers:
            c_d = containers[c]
            co = None
            if (DContainer.objects.filter(name=c).exists()):
                co = DContainer.objects.get(name=c)
                if (co.rockon.id != ro.id):
                    e_msg = ('Duplicate container(%s) definition detected. '
                             'It belongs to another Rock-on(%s). Uninstall '
                             'one of them and try again.' % (co.name, co.rockon.name))
                    handle_exception(Exception(e_msg), self.request)

                if (co.dimage.name != c_d['image']):
                    if (ro.state != 'available'):
                        e_msg = ('Cannot change image of the container(%s) '
                                 'as it belongs to an installed Rock-on(%s). '
                                 'Uninstall it first and try again.' %
                                 (co.name, ro.name))
                        handle_exception(Exception(e_msg), self.request)
                    co.dimage.delete()
            if (co is None):
                co = DContainer(name=c, rockon=ro)
            defaults = {'tag': c_d.get('tag', 'latest'),
                        'repo': 'na',}
            io, created = DImage.objects.get_or_create(name=c_d['image'],
                                                       defaults=defaults)
            co.dimage = io
            co.launch_order = c_d['launch_order']
            if ('uid' in c_d):
                co.uid = int(c_d['uid'])
            co.save()

            ports = containers[c].get('ports', {})
            cur_ports = [po.containerp for po in
                         DPort.objects.filter(container=co)]
            if (len(set(map(int, ports.keys())) ^ set(cur_ports)) != 0):
                if (ro.state != 'available'):
                    e_msg = ('Cannot add/remove port definitions of the '
                             'container(%s) as it belongs to an installed '
                             'Rock-on(%s). Uninstall it first and try again.' %
                             (co.name, ro.name))
                    handle_exception(Exception(e_msg), self.request)
                DPort.objects.filter(container=co).delete()

            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)
                    if (po.hostp_default != p_d['host_default']):
                        po.hostp_default = self._next_available_default_hostp(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 = self._next_available_default_hostp(p_d['host_default'])
                    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()

            v_d = c_d.get('volumes', {})
            cur_vols = [vo.dest_dir for vo in
                        DVolume.objects.filter(container=co)]
            if (len(set(v_d.keys()) ^ set(cur_vols)) != 0):
                if (ro.state != 'available'):
                    e_msg = ('Cannot add/remove volume definitions of the '
                             'container(%s) as it belongs to an installed '
                             'Rock-on(%s). Uninstall it first and try again.' %
                             (co.name, ro.name))
                    handle_exception(Exception(e_msg), self.request)
                DVolume.objects.filter(container=co).delete()

            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()

            self._update_env(co, c_d)
            options = containers[c].get('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()

        l_d = r_d.get('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()
        self._update_cc(ro, r_d)
Ejemplo n.º 3
0
    def _create_update_meta(self, name, r_d):
        # Update our application state with any changes from hosted app
        # profiles(app.json files). Some attributes cannot be updated if the
        # Rock-on is currently installed. These will be logged and ignored.
        ro_defaults = {
            "description": r_d["description"],
            "website": r_d["website"],
            "version": r_d["version"],
            "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"]
        cur_containers = [
            co.name for co in DContainer.objects.filter(rockon=ro)
        ]
        if len(set(containers.keys()) ^ set(cur_containers)) != 0:
            if ro.state not in ("available", "install_failed"):
                e_msg = ("Cannot add/remove container definitions for {} as "
                         "it is not in available state. Uninstall the "
                         "Rock-on first and try again.").format(ro.name)
                handle_exception(Exception(e_msg), self.request)
            # rock-on is in available state. we can safely wipe metadata
            # and start fresh.
            DContainer.objects.filter(rockon=ro).delete()

        for c in containers:
            c_d = containers[c]
            co = None
            if DContainer.objects.filter(name=c).exists():
                co = DContainer.objects.get(name=c)
                if co.rockon.id != ro.id:
                    e_msg = ("Duplicate container ({}) definition detected. "
                             "It belongs to another Rock-on ({}). Uninstall "
                             "one of them and "
                             "try again.").format(co.name, co.rockon.name)
                    handle_exception(Exception(e_msg), self.request)

                if co.dimage.name != c_d["image"]:
                    if ro.state not in ("available", "install_failed"):
                        e_msg = ("Cannot change image of the container ({}) "
                                 "as it belongs to an installed Rock-on ({}). "
                                 "Uninstall it first and "
                                 "try again.").format(co.name, ro.name)
                        handle_exception(Exception(e_msg), self.request)
                    co.dimage.delete()
            if co is None:
                co = DContainer(name=c, rockon=ro)
            defaults = {
                "repo": "na",
            }
            io, created = DImage.objects.get_or_create(name=c_d["image"],
                                                       tag=c_d.get(
                                                           "tag", "latest"),
                                                       defaults=defaults)
            co.dimage = io
            co.launch_order = c_d["launch_order"]
            if "uid" in c_d:
                co.uid = int(c_d["uid"])
            co.save()

            ports = containers[c].get("ports", {})
            cur_ports = [
                po.containerp for po in DPort.objects.filter(container=co)
            ]
            if len(set(map(int, ports.keys())) ^ set(cur_ports)) != 0:
                if ro.state not in ("available", "install_failed"):
                    e_msg = ("Cannot add/remove port definitions of the "
                             "container ({}) as it belongs to an installed "
                             "Rock-on ({}). Uninstall it first and "
                             "try again.").format(co.name, ro.name)
                    handle_exception(Exception(e_msg), self.request)
                DPort.objects.filter(container=co).delete()

            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)
                    if po.hostp_default != p_d["host_default"]:
                        po.hostp_default = self._next_available_default_hostp(
                            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 = self._next_available_default_hostp(
                        p_d["host_default"])  # noqa E501
                    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()

            v_d = c_d.get("volumes", {})
            cur_vols = [
                vo.dest_dir for vo in DVolume.objects.filter(container=co)
            ]
            # cur_vols can have entries not in the config for Shares mapped
            # post install.  If we have more volumes defined in the rock-on
            # definition than we have previously seen for this rockon, ie
            # volumes added in newer definition, then remove our existing
            # volumes record.
            if len(set(v_d.keys()) - set(cur_vols)) != 0:
                # but only if the current state is 'available' (to install) or
                # 'install failed', otherwise raise warning about changing an
                # installed rock-ons.
                if ro.state not in ("available", "install_failed"):
                    e_msg = ("Cannot add/remove volume definitions of the "
                             "container ({}) as it belongs to an installed "
                             "Rock-on ({}). Uninstall it first and "
                             "try again.").format(co.name, ro.name)
                    handle_exception(Exception(e_msg), self.request)
                # Delete all volume entries for this container so that they
                # might be created a fresh.
                DVolume.objects.filter(container=co).delete()
            # If the existing rock-on db entry indicates this container is not
            # installed ie state available or install_failed then check if we
            # need to remove any now deprecated volume entries.
            # Ie updated config that has removed a previously seen volume.
            if ro.state in ("available", "install_failed"):
                if len(set(cur_vols) - set(v_d.keys())) > 0:
                    # we have some current volumes in db that are no longer in
                    # our updated rock-on definition so remove all volumes for
                    # this rock-on so they might be updated whole sale.
                    # Delete all volume entries for this container so that they
                    # might be created a fresh.
                    DVolume.objects.filter(container=co).delete()

            # Cycle through all volumes in the rock-on json definition and
            # update or create the appropriate db volumes entry.
            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 this db entry previously existed then update its
                # description and label to that found in our rock-on json
                # This ensures changes made in repo json to the description and
                # label's get updated in the local db.
                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()

            self._update_env(co, c_d)
            self._update_device(co, c_d)
            options = containers[c].get("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()

            cmd_args = containers[c].get("cmd_arguments", [])
            id_l = []
            for ca in cmd_args:
                # there are no unique constraints on this model, so we need
                # this bandaid.
                if (DContainerArgs.objects.filter(
                        container=co, name=ca[0], val=ca[1]).count() > 1):
                    DContainerArgs.objects.filter(container=co,
                                                  name=ca[0],
                                                  val=ca[1]).delete()
                cao, created = DContainerArgs.objects.get_or_create(
                    container=co, name=ca[0], val=ca[1])
                id_l.append(cao.id)
            for cao in DContainerArgs.objects.filter(container=co):
                if cao.id not in id_l:
                    cao.delete()

        l_d = r_d.get("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()
        self._update_cc(ro, r_d)
Ejemplo n.º 4
0
    def _create_update_meta(self, name, r_d):
        # Update our application state with any changes from hosted app
        # profiles(app.json files). Some attributes cannot be updated if the
        # Rock-on is currently installed. These will be logged and ignored.
        ro_defaults = {'description': r_d['description'],
                       'website': r_d['website'],
                       'version': r_d['version'],
                       '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']
        cur_containers = [co.name for co in
                          DContainer.objects.filter(rockon=ro)]
        if (len(set(containers.keys()) ^ set(cur_containers)) != 0):
            if (ro.state not in ('available', 'install_failed')):
                e_msg = ('Cannot add/remove container definitions for {} as '
                         'it is not in available state. Uninstall the '
                         'Rock-on first and try again.').format(ro.name)
                handle_exception(Exception(e_msg), self.request)
            # rock-on is in available state. we can safely wipe metadata
            # and start fresh.
            DContainer.objects.filter(rockon=ro).delete()

        for c in containers:
            c_d = containers[c]
            co = None
            if (DContainer.objects.filter(name=c).exists()):
                co = DContainer.objects.get(name=c)
                if (co.rockon.id != ro.id):
                    e_msg = ('Duplicate container ({}) definition detected. '
                             'It belongs to another Rock-on ({}). Uninstall '
                             'one of them and '
                             'try again.').format(co.name, co.rockon.name)
                    handle_exception(Exception(e_msg), self.request)

                if (co.dimage.name != c_d['image']):
                    if (ro.state not in ('available', 'install_failed')):
                        e_msg = ('Cannot change image of the container ({}) '
                                 'as it belongs to an installed Rock-on ({}). '
                                 'Uninstall it first and '
                                 'try again.').format(co.name, ro.name)
                        handle_exception(Exception(e_msg), self.request)
                    co.dimage.delete()
            if (co is None):
                co = DContainer(name=c, rockon=ro)
            defaults = {'tag': c_d.get('tag', 'latest'),
                        'repo': 'na', }
            io, created = DImage.objects.get_or_create(name=c_d['image'],
                                                       defaults=defaults)
            co.dimage = io
            co.launch_order = c_d['launch_order']
            if ('uid' in c_d):
                co.uid = int(c_d['uid'])
            co.save()

            ports = containers[c].get('ports', {})
            cur_ports = [po.containerp for po in
                         DPort.objects.filter(container=co)]
            if (len(set(map(int, ports.keys())) ^ set(cur_ports)) != 0):
                if (ro.state not in ('available', 'install_failed')):
                    e_msg = ('Cannot add/remove port definitions of the '
                             'container ({}) as it belongs to an installed '
                             'Rock-on ({}). Uninstall it first and '
                             'try again.').format(co.name, ro.name)
                    handle_exception(Exception(e_msg), self.request)
                DPort.objects.filter(container=co).delete()

            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)
                    if (po.hostp_default != p_d['host_default']):
                        po.hostp_default = self._next_available_default_hostp(
                            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 = self._next_available_default_hostp(p_d['host_default'])  # noqa E501
                    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()

            v_d = c_d.get('volumes', {})
            cur_vols = [vo.dest_dir for vo in
                        DVolume.objects.filter(container=co)]
            # cur_vols can have entries not in the config for Shares mapped
            # post install.  If we have more volumes defined in the rock-on
            # definition than we have previously seen for this rockon, ie
            # volumes added in newer definition, then remove our existing
            # volumes record.
            if (len(set(v_d.keys()) - set(cur_vols)) != 0):
                # but only if the current state is 'available' (to install) or
                # 'install failed', otherwise raise warning about changing an
                # installed rock-ons.
                if (ro.state not in ('available', 'install_failed')):
                    e_msg = ('Cannot add/remove volume definitions of the '
                             'container ({}) as it belongs to an installed '
                             'Rock-on ({}). Uninstall it first and '
                             'try again.').format(co.name, ro.name)
                    handle_exception(Exception(e_msg), self.request)
                # Delete all volume entries for this container so that they
                # might be created a fresh.
                DVolume.objects.filter(container=co).delete()
            # If the existing rock-on db entry indicates this container is not
            # installed ie state available or install_failed then check if we
            # need to remove any now deprecated volume entries.
            # Ie updated config that has removed a previously seen volume.
            if (ro.state in ('available', 'install_failed')):
                if (len(set(cur_vols) - set(v_d.keys())) > 0):
                    # we have some current volumes in db that are no longer in
                    # our updated rock-on definition so remove all volumes for
                    # this rock-on so they might be updated whole sale.
                    # Delete all volume entries for this container so that they
                    # might be created a fresh.
                    DVolume.objects.filter(container=co).delete()

            # Cycle through all volumes in the rock-on json definition and
            # update or create the appropriate db volumes entry.
            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 this db entry previously existed then update it's
                # description and label to that found in our rock-on json
                # This ensures changes made in repo json to the description and
                # label's get updated in the local db.
                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()

            self._update_env(co, c_d)
            options = containers[c].get('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()

        l_d = r_d.get('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()
        self._update_cc(ro, r_d)
Ejemplo n.º 5
0
    def _create_update_meta(self, name, r_d):
        #Update our application state with any changes from hosted app
        #profiles(app.json files). Some attributes cannot be updated
        #if the Rock-on is currently installed. These will be logged and
        #ignored.
        ro_defaults = {'description': r_d['description'],
                       'website': r_d['website'],
                       'version': r_d['version'],
                       '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']
        cur_containers = [co.name for co in
                          DContainer.objects.filter(rockon=ro)]
        if (len(set(containers.keys()) ^ set(cur_containers)) != 0):
            if (ro.state not in ('available', 'install_failed')):
                e_msg = ('Cannot add/remove container definitions for %s as '
                         'it is not in available state. Uninstall the '
                         'Rock-on first and try again.' % ro.name)
                handle_exception(Exception(e_msg), self.request)
            #rock-on is in available state. we can safely wipe metadata
            #and start fresh.
            DContainer.objects.filter(rockon=ro).delete()

        for c in containers:
            c_d = containers[c]
            co = None
            if (DContainer.objects.filter(name=c).exists()):
                co = DContainer.objects.get(name=c)
                if (co.rockon.id != ro.id):
                    e_msg = ('Duplicate container(%s) definition detected. '
                             'It belongs to another Rock-on(%s). Uninstall '
                             'one of them and try again.' % (co.name, co.rockon.name))
                    handle_exception(Exception(e_msg), self.request)

                if (co.dimage.name != c_d['image']):
                    if (ro.state not in ('available', 'install_failed')):
                        e_msg = ('Cannot change image of the container(%s) '
                                 'as it belongs to an installed Rock-on(%s). '
                                 'Uninstall it first and try again.' %
                                 (co.name, ro.name))
                        handle_exception(Exception(e_msg), self.request)
                    co.dimage.delete()
            if (co is None):
                co = DContainer(name=c, rockon=ro)
            defaults = {'tag': c_d.get('tag', 'latest'),
                        'repo': 'na',}
            io, created = DImage.objects.get_or_create(name=c_d['image'],
                                                       defaults=defaults)
            co.dimage = io
            co.launch_order = c_d['launch_order']
            if ('uid' in c_d):
                co.uid = int(c_d['uid'])
            co.save()

            ports = containers[c].get('ports', {})
            cur_ports = [po.containerp for po in
                         DPort.objects.filter(container=co)]
            if (len(set(map(int, ports.keys())) ^ set(cur_ports)) != 0):
                if (ro.state not in ('available', 'install_failed')):
                    e_msg = ('Cannot add/remove port definitions of the '
                             'container(%s) as it belongs to an installed '
                             'Rock-on(%s). Uninstall it first and try again.' %
                             (co.name, ro.name))
                    handle_exception(Exception(e_msg), self.request)
                DPort.objects.filter(container=co).delete()

            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)
                    if (po.hostp_default != p_d['host_default']):
                        po.hostp_default = self._next_available_default_hostp(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 = self._next_available_default_hostp(p_d['host_default'])
                    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()

            v_d = c_d.get('volumes', {})
            cur_vols = [vo.dest_dir for vo in
                        DVolume.objects.filter(container=co)]
            # cur_vols can have entries not in the config for Shares mapped post
            # install.
            # If we have more volumes defined in the rock-on definition than
            # we have previously seen for this rockon, ie volumes added in newer
            # definition, then remove our existing volumes record.
            if (len(set(v_d.keys()) - set(cur_vols)) != 0):
                # but only if the current state is 'available' (to install) or
                # 'install failed', otherwise raise warning about changing an
                # installed rock-ons.
                if (ro.state not in ('available', 'install_failed')):
                    e_msg = ('Cannot add/remove volume definitions of the '
                             'container(%s) as it belongs to an installed '
                             'Rock-on(%s). Uninstall it first and try again.' %
                             (co.name, ro.name))
                    handle_exception(Exception(e_msg), self.request)
                # Delete all volume entries for this container so that they
                # might be created a fresh.
                DVolume.objects.filter(container=co).delete()
            # If the existing rock-on db entry indicates this container is not
            # installed ie state available or install_failed then check if we
            # need to remove any now deprecated volume entries.
            # Ie updated config that has removed a previously seen volume.
            if (ro.state in ('available', 'install_failed')):
                if (len(set(cur_vols) - set(v_d.keys())) > 0):
                    # we have some current volumes in db that are no longer in
                    # our updated rock-on definition so remove all volumes for
                    # this rock-on so they might be updated whole sale.
                    # Delete all volume entries for this container so that they
                    # might be created a fresh.
                    DVolume.objects.filter(container=co).delete()

            # Cycle through all volumes in the rock-on json definition and
            # update or create the appropriate db volumes entry.
            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 this db entry previously existed then update it's
                # description and label to that found in our rock-on json
                # This ensures changes made in repo json to the description and
                # label's get updated in the local db.
                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()

            self._update_env(co, c_d)
            options = containers[c].get('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()

        l_d = r_d.get('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()
        self._update_cc(ro, r_d)
Ejemplo n.º 6
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()