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