예제 #1
0
파일: models.py 프로젝트: kargig/ganetimgr
    def reinstall_instance(self, instance, action):
        from ganeti.utils import get_os_details

        def map_ssh_user(user, group=None, path=None):
            if group is None:
                if user == "root":
                    group = ""   # snf-image will expand to root or wheel
                else:
                    group = user
            if path is None:
                if user == "root":
                    path = "/root/.ssh/authorized_keys"
                else:
                    path = "/home/%s/.ssh/authorized_keys" % user
            return user, group, path

        action_os = action.operating_system
        if action.operating_system == 'noop':
            action_os = "none"
        details = get_os_details(action_os)
        if details:
            cache_key = self._instance_cache_key(instance)
            cache.delete(cache_key)
            osparams = {}
            if "ssh_key_param" in details:
                fqdn = "https://" + Site.objects.get_current().domain
                try:
                    key_url = self.get_instance_or_404(
                        instance
                    ).application.get_ssh_keys_url(fqdn)
                    if details["ssh_key_param"]:
                        osparams[details["ssh_key_param"]] = key_url
                except:
                    pass
            if "ssh_key_users" in details and details["ssh_key_users"]:
                ssh_keys = None
                try:
                    ssh_keys = self.get_instance_or_404(
                        instance
                    ).application.applicant.sshpublickey_set.all()
                except:
                    pass
                if ssh_keys:
                    ssh_lines = [key.key_line() for key in ssh_keys]
                    ssh_base64 = base64.b64encode("".join(ssh_lines))
                    if "img_personality" not in osparams:
                        osparams["img_personality"] = []
                    for user in os["ssh_key_users"].split():
                        # user[:group[:/path/to/authorized_keys]]
                        owner, group, path = map_ssh_user(*user.split(":"))
                        osparams["img_personality"].append({
                            "path": path,
                            "contents": ssh_base64,
                            "owner": owner,
                            "group": group,
                            "mode": 0600,
                        })
            osparams.update(details.get('osparams'))
            for (key, val) in osparams.iteritems():
            # Encode nested JSON. See
            # <https://code.google.com/p/ganeti/issues/detail?id=835>
                if not isinstance(val, basestring):
                    osparams[key] = json.dumps(val)
            job_id = self._client.ReinstallInstance(
                instance,
                os=details.get('provider'),
                osparams=osparams
            )
            # manually change os params because client has a bug
            self._client.ModifyInstance(instance, osparams=osparams)
            self._lock_instance(instance, reason="reinstalling", job_id=job_id)
            return job_id
        else:
            return False
예제 #2
0
    def reinstall_instance(self, instance, action):
        from ganeti.utils import get_os_details

        def map_ssh_user(user, group=None, path=None):
            if group is None:
                if user == "root":
                    group = ""  # snf-image will expand to root or wheel
                else:
                    group = user
            if path is None:
                if user == "root":
                    path = "/root/.ssh/authorized_keys"
                else:
                    path = "/home/%s/.ssh/authorized_keys" % user
            return user, group, path

        action_os = action.operating_system
        if action.operating_system == 'noop':
            action_os = "none"
        details = get_os_details(action_os)
        if details:
            cache_key = self._instance_cache_key(instance)
            cache.delete(cache_key)
            osparams = {}
            if "ssh_key_param" in details:
                fqdn = "https://" + Site.objects.get_current().domain
                try:
                    key_url = self.get_instance_or_404(
                        instance).application.get_ssh_keys_url(fqdn)
                    if details["ssh_key_param"]:
                        osparams[details["ssh_key_param"]] = key_url
                except:
                    pass
            if "ssh_key_users" in details and details["ssh_key_users"]:
                ssh_keys = None
                try:
                    ssh_keys = self.get_instance_or_404(
                        instance).application.applicant.sshpublickey_set.all()
                except:
                    pass
                if ssh_keys:
                    ssh_lines = [key.key_line() for key in ssh_keys]
                    ssh_base64 = base64.b64encode("".join(ssh_lines))
                    if "img_personality" not in osparams:
                        osparams["img_personality"] = []
                    for user in details["ssh_key_users"].split():
                        # user[:group[:/path/to/authorized_keys]]
                        owner, group, path = map_ssh_user(*user.split(":"))
                        osparams["img_personality"].append({
                            "path": path,
                            "contents": ssh_base64,
                            "owner": owner,
                            "group": group,
                            "mode": 0600,
                        })
            osparams.update(details.get('osparams'))
            reinstall_params = {}
            for (key, val) in osparams.iteritems():
                # Encode nested JSON. See
                # <https://code.google.com/p/ganeti/issues/detail?id=835>
                if not isinstance(val, basestring):
                    osparams[key] = json.dumps(val)
            reinstall_params['os'] = details.get('provider')
            reinstall_params['osparams'] = osparams
            if LooseVersion(self.get_version()) >= LooseVersion(
                    GANETI_VERSION_OSPARAMS):
                reinstall_params['clear_osparams'] = True
                job_id = self._client.ReinstallInstance(
                    instance, reinstall_params)
                self._lock_instance(instance,
                                    reason="reinstalling",
                                    job_id=job_id)
                return job_id
            else:
                job_id = self._client.ReinstallInstance(
                    instance, reinstall_params)
                self._client.ModifyInstance(instance, osparams=osparams)
                self._lock_instance(instance,
                                    reason="reinstalling",
                                    job_id=job_id)
                return job_id
        else:
            return False
예제 #3
0
def instance(request, cluster_slug, instance):
    cluster = get_object_or_404(Cluster, slug=cluster_slug)
    instance = cluster.get_instance_or_404(instance)
    if request.method == 'POST':
        configform = InstanceConfigForm(request.POST)
        if configform.is_valid():
            needs_reboot = False
            # The instance needs reboot if any of the hvparams have changed.
            if configform.cleaned_data['cdrom_type'] == 'none':
                configform.cleaned_data['cdrom_image_path'] = ""
            for key, val in configform.cleaned_data.items():
                if key == "cdrom_type":
                    continue
                if key == "whitelist_ip":
                    continue
                if configform.cleaned_data[key] != instance.hvparams[key]:
                    if instance.admin_state:
                        needs_reboot = True
            if configform.cleaned_data['cdrom_type'] == 'none':
                configform.cleaned_data['cdrom_image_path'] = ""
            elif (configform.cleaned_data['cdrom_image_path'] !=
                  instance.hvparams['cdrom_image_path']):
                # This should be an http URL
                if (not (
                        configform.cleaned_data['cdrom_image_path'].startswith(
                            'http://') or configform.
                        cleaned_data['cdrom_image_path'].startswith('https://')
                        or configform.cleaned_data['cdrom_image_path'] == "")):
                    # Remove this, we don't want them to
                    # be able to read local files
                    del configform.cleaned_data['cdrom_image_path']
            data = {}
            whitelistip = None
            for key, val in configform.cleaned_data.items():
                if key == "cdrom_type":
                    continue
                if key == "whitelist_ip":
                    whitelistip = val
                    if len(val) == 0:
                        whitelistip = None
                    continue
                data[key] = val
            auditlog = auditlog_entry(
                request, "Setting %s" % (", ".join(
                    ["%s:%s" % (key, value) for key, value in data.items()])),
                instance, cluster_slug)
            jobid = instance.set_params(hvparams=data)
            auditlog.update(job_id=jobid)
            if needs_reboot:
                instance.cluster.tag_instance(
                    instance.name,
                    ["%s:needsreboot" % (settings.GANETI_TAG_PREFIX)])
            if instance.whitelistip and whitelistip is None:
                auditlog = auditlog_entry(
                    request, "Remove whitelist %s" % instance.whitelistip,
                    instance, cluster_slug)
                jobid = instance.cluster.untag_instance(
                    instance.name, [
                        "%s:whitelist_ip:%s" %
                        (settings.GANETI_TAG_PREFIX, instance.whitelistip)
                    ])
                auditlog.update(job_id=jobid)
                instance.cluster.migrate_instance(instance.name)
            if whitelistip:
                if instance.whitelistip:
                    auditlog = auditlog_entry(
                        request, "Remove whitelist %s" % instance.whitelistip,
                        instance, cluster_slug)
                    jobid = instance.cluster.untag_instance(
                        instance.name, [
                            "%s:whitelist_ip:%s" %
                            (settings.GANETI_TAG_PREFIX, instance.whitelistip)
                        ])
                    auditlog.update(job_id=jobid)
                auditlog = auditlog_entry(request,
                                          "Add whitelist %s" % whitelistip,
                                          instance, cluster_slug)
                jobid = instance.cluster.tag_instance(instance.name, [
                    "%s:whitelist_ip:%s" %
                    (settings.GANETI_TAG_PREFIX, whitelistip)
                ])
                auditlog.update(job_id=jobid)
                instance.cluster.migrate_instance(instance.name)
            # Prevent form re-submission via browser refresh
            return HttpResponseRedirect(
                reverse('instance-detail',
                        kwargs={
                            'cluster_slug': cluster_slug,
                            'instance': instance
                        }))
    else:
        if 'cdrom_image_path' in instance.hvparams:
            if instance.hvparams['cdrom_image_path']:
                instance.hvparams['cdrom_type'] = 'iso'
            else:
                instance.hvparams['cdrom_type'] = 'none'
        else:
            instance.hvparams['cdrom_type'] = 'none'
        if instance.whitelistip:
            instance.hvparams['whitelist_ip'] = instance.whitelistip
        else:
            instance.hvparams['whitelist_ip'] = ''
        configform = InstanceConfigForm(instance.hvparams)
    instance.cpu_url = reverse('graph',
                               args=(cluster.slug, instance.name, 'cpu-ts'))
    instance.net_url = []
    for (nic_i, link) in enumerate(instance.nic_links):
        instance.net_url.append(
            reverse('graph',
                    args=(cluster.slug, instance.name, 'net-ts',
                          '/eth%s' % nic_i)))

    instance.netw = []
    try:
        instance.osname = get_os_details(instance.osparams['img_id']).get(
            'description', instance.osparams['img_id'])
    except Exception:
        try:
            instance.osname = instance.osparams['img_id']
        except Exception:
            instance.osname = instance.os
    instance.node_group_locked = instance.pnode in instance.cluster.locked_nodes_from_nodegroup(
    )
    for (nic_i, link) in enumerate(instance.nic_links):
        if instance.nic_ips[nic_i] is None:
            instance.netw.append("%s" % (instance.nic_links[nic_i]))
        else:
            instance.netw.append(
                "%s@%s" % (instance.nic_ips[nic_i], instance.nic_links[nic_i]))
    if instance.isolate and instance.whitelistip is None:

        djmessages.add_message(
            request, msgs.ERROR,
            "Your instance is isolated from the network and" +
            " you have not set an \"Allowed From\" address." +
            " To access your instance from a specific network range," +
            " you can set it via the instance configuration form")
    if instance.needsreboot:
        djmessages.add_message(
            request,
            msgs.ERROR,
            "You have modified one or more of your instance's core " +
            "configuration components  (any of network adapter, hard" +
            " disk type, boot device, cdrom). In order for these changes " +
            "to take effect, you need to <strong>Reboot</strong>" +
            " your instance.",
            extra_tags='safe')
    ret_dict = {'cluster': cluster, 'instance': instance}
    if not request.user.has_perm('ganeti.view_instances') or (
            request.user.is_superuser or request.user in instance.users
            or set.intersection(set(request.user.groups.all()),
                                set(instance.groups))):
        ret_dict['configform'] = configform
    return render(request, 'instances/instance.html', ret_dict)
예제 #4
0
def instance(request, cluster_slug, instance):
    cluster = get_object_or_404(Cluster, slug=cluster_slug)
    instance = cluster.get_instance_or_404(instance)
    if request.method == 'POST':
        configform = InstanceConfigForm(request.POST)
        if configform.is_valid():
            needs_reboot = False
            # The instance needs reboot if any of the hvparams have changed.
            if configform.cleaned_data['cdrom_type'] == 'none':
                configform.cleaned_data['cdrom_image_path'] = ""
            for key, val in configform.cleaned_data.items():
                if key == "cdrom_type":
                    continue
                if key == "whitelist_ip":
                    continue
                if configform.cleaned_data[key] != instance.hvparams[key]:
                    if instance.admin_state:
                        needs_reboot = True
            if configform.cleaned_data['cdrom_type'] == 'none':
                configform.cleaned_data['cdrom_image_path'] = ""
            elif (configform.cleaned_data['cdrom_image_path'] !=
                  instance.hvparams['cdrom_image_path']):
                # This should be an http URL
                if (
                    not (
                        configform.cleaned_data['cdrom_image_path'].startswith(
                            'http://'
                        ) or
                        configform.cleaned_data['cdrom_image_path'].startswith(
                            'https://'
                        ) or
                        configform.cleaned_data['cdrom_image_path'] == ""
                    )
                ):
                    # Remove this, we don't want them to
                    # be able to read local files
                    del configform.cleaned_data['cdrom_image_path']
            data = {}
            whitelistip = None
            for key, val in configform.cleaned_data.items():
                if key == "cdrom_type":
                    continue
                if key == "whitelist_ip":
                    whitelistip = val
                    if len(val) == 0:
                        whitelistip = None
                    continue
                data[key] = val
            auditlog = auditlog_entry(
                request,
                "Setting %s" % (
                    ", ".join(
                        [
                            "%s:%s" % (key, value) for key, value in data.iteritems()
                        ]
                    )
                ),
                instance,
                cluster_slug
            )
            jobid = instance.set_params(hvparams=data)
            auditlog.update(job_id=jobid)
            if needs_reboot:
                instance.cluster.tag_instance(
                    instance.name,
                    ["%s:needsreboot" % (settings.GANETI_TAG_PREFIX)]
                )
            if instance.whitelistip and whitelistip is None:
                auditlog = auditlog_entry(
                    request,
                    "Remove whitelist %s" % instance.whitelistip,
                    instance,
                    cluster_slug
                )
                jobid = instance.cluster.untag_instance(
                    instance.name,
                    ["%s:whitelist_ip:%s" % (
                        settings.GANETI_TAG_PREFIX,
                        instance.whitelistip
                    )]
                )
                auditlog.update(job_id=jobid)
                instance.cluster.migrate_instance(instance.name)
            if whitelistip:
                if instance.whitelistip:
                    auditlog = auditlog_entry(
                        request,
                        "Remove whitelist %s" % instance.whitelistip,
                        instance,
                        cluster_slug
                    )
                    jobid = instance.cluster.untag_instance(
                        instance.name,
                        ["%s:whitelist_ip:%s" % (
                            settings.GANETI_TAG_PREFIX,
                            instance.whitelistip
                        )])
                    auditlog.update(job_id=jobid)
                auditlog = auditlog_entry(
                    request,
                    "Add whitelist %s" % whitelistip, instance, cluster_slug
                )
                jobid = instance.cluster.tag_instance(
                    instance.name,
                    ["%s:whitelist_ip:%s" % (settings.GANETI_TAG_PREFIX, whitelistip)]
                )
                auditlog.update(job_id=jobid)
                instance.cluster.migrate_instance(instance.name)
            # Prevent form re-submission via browser refresh
            return HttpResponseRedirect(
                reverse(
                    'instance-detail',
                    kwargs={'cluster_slug': cluster_slug, 'instance': instance}
                )
            )
    else:
        if 'cdrom_image_path' in instance.hvparams.keys():
            if instance.hvparams['cdrom_image_path']:
                instance.hvparams['cdrom_type'] = 'iso'
            else:
                instance.hvparams['cdrom_type'] = 'none'
        else:
            instance.hvparams['cdrom_type'] = 'none'
        if instance.whitelistip:
            instance.hvparams['whitelist_ip'] = instance.whitelistip
        else:
            instance.hvparams['whitelist_ip'] = ''
        configform = InstanceConfigForm(instance.hvparams)
    instance.cpu_url = reverse(
        'graph',
        args=(cluster.slug, instance.name, 'cpu-ts')
    )
    instance.net_url = []
    for (nic_i, link) in enumerate(instance.nic_links):
        instance.net_url.append(
            reverse(
                'graph',
                args=(cluster.slug, instance.name, 'net-ts', '/eth%s' % nic_i)
            )
        )

    instance.netw = []
    try:
        instance.osname = get_os_details(
            instance.osparams['img_id']).get(
            'description', instance.osparams['img_id']
        )
    except Exception:
        try:
            instance.osname = instance.osparams['img_id']
        except Exception:
            instance.osname = instance.os
    instance.node_group_locked = instance.pnode in instance.cluster.locked_nodes_from_nodegroup()
    for (nic_i, link) in enumerate(instance.nic_links):
        if instance.nic_ips[nic_i] is None:
            instance.netw.append("%s" % (instance.nic_links[nic_i]))
        else:
            instance.netw.append("%s@%s" % (
                instance.nic_ips[nic_i], instance.nic_links[nic_i])
            )
    if instance.isolate and instance.whitelistip is None:

        djmessages.add_message(
            request,
            msgs.ERROR,
            "Your instance is isolated from the network and" +
            " you have not set an \"Allowed From\" address." +
            " To access your instance from a specific network range," +
            " you can set it via the instance configuration form"
        )
    if instance.needsreboot:
        djmessages.add_message(
            request,
            msgs.ERROR,
            "You have modified one or more of your instance's core " +
            "configuration components  (any of network adapter, hard" +
            " disk type, boot device, cdrom). In order for these changes " +
            "to take effect, you need to <strong>Reboot</strong>" +
            " your instance.",
            extra_tags='safe'
        )
    ret_dict = {'cluster': cluster,
                'instance': instance
                }
    if not request.user.has_perm('ganeti.view_instances') or (
        request.user.is_superuser or
        request.user in instance.users or
        set.intersection(set(request.user.groups.all()), set(instance.groups))
    ):
            ret_dict['configform'] = configform
    return render(
        request,
        'instances/instance.html',
        ret_dict
    )