openstack添加新功能
#增加按钮功能【例如增加增量功能】 vim /opt/horizon-2012.1/horizon/dashboards/nova/instances_and_volumes/instances/tables.py class SnapshotLink(tables.LinkAction): #创建快照功能,快照流程分析 name = "snapshot" verbose_name = _("Snapshot") url = "horizon:nova:images_and_snapshots:snapshots:create" #连接目录如下: classes = ("ajax-modal", "btn-camera") def allowed(self, request, instance=None): return instance.status in ACTIVE_STATES 说明: vim /opt/horizon-2012.1/horizon/dashboards/nova/images_and_snapshots/snapshots/url.py # from django.conf.urls.defaults import patterns, url from .views import CreateView urlpatterns = patterns('', url(r'^(?P[^/]+)/create', CreateView.as_view(), name='create') #### vim /opt/horizon-2012.1/horizon/dashboards/nova/images_and_snapshots/snapshots/views.py class CreateView(forms.ModalFormView): #vim /opt/horizon-2012.1/horizon/forms/views.py form_class = CreateSnapshot template_name = 'nova/images_and_snapshots/snapshots/create.html' def get_initial(self): redirect = reverse('horizon:nova:instances_and_volumes:index') instance_id = self.kwargs["instance_id"] try: self.instance = api.server_get(self.request, instance_id) except: self.instance = None msg = _("Unable to retrieve instance.") exceptions.handle(self.request, msg, redirect) if self.instance.status != api.nova.INSTANCE_ACTIVE_STATE: msg = _('To create a snapshot, the instance must be in ' 'the "%s" state.') % api.nova.INSTANCE_ACTIVE_STATE raise exceptions.Http302(redirect, message=msg) return {"instance_id": instance_id, "tenant_id": self.request.user.tenant_id} def get_context_data(self, **kwargs): context = super(CreateView, self).get_context_data(**kwargs) context['instance'] = self.instance return context #修改实例:单击Snapshot按钮后出现的对话框如下: name = forms.CharField(max_length="20", label=_("shot Name")) #修改前 #name = forms.CharField(max_length="20", label=_("Snapshot Name")) #修改后 修改完毕,重启apache vim /opt/horizon-2012.1/horizon/forms/views.py import os from django import http from django.views import generic ## cd /usr/lib/python2.6/site-packages/django/views/generic class ModalFormView(generic.TemplateView): vim /usr/lib/python2.6/site-packages/django/views/generic/base.py # class View(object): """ Intentionally simple parent class for all views. Only implements dispatch-by-method and simple sanity checking. """ http_method_names = ['get', 'post', 'put', 'delete', 'head', 'options', 'trace'] def __init__(self, **kwargs): """ Constructor. Called in the URLconf; can contain helpful extra keyword arguments, and other things. """ # Go through keyword arguments, and either save their values to our # instance, or raise an error. for key, value in kwargs.iteritems(): setattr(self, key, value) @classonlymethod def as_view(cls, **initkwargs): """ Main entry point for a request-response process. """ # sanitize keyword arguments for key in initkwargs: if key in cls.http_method_names: raise TypeError(u"You tried to pass in the %s method name as a " u"keyword argument to %s(). Don't do that." % (key, cls.__name__)) if not hasattr(cls, key): raise TypeError(u"%s() received an invalid keyword %r" % ( cls.__name__, key)) def view(request, *args, **kwargs): self = cls(**initkwargs) return self.dispatch(request, *args, **kwargs) # take name and docstring from class update_wrapper(view, cls, updated=()) # and possible attributes set by decorators # like csrf_exempt from dispatch update_wrapper(view, cls.dispatch, assigned=()) return view def dispatch(self, request, *args, **kwargs): # Try to dispatch to the right method; if a method doesn't exist, # defer to the error handler. Also defer to the error handler if the # request method isn't on the approved list. if request.method.lower() in self.http_method_names: handler = getattr(self, request.method.lower(), self.http_method_not_allowed) else: handler = self.http_method_not_allowed self.request = request self.args = args self.kwargs = kwargs return handler(request, *args, **kwargs) def http_method_not_allowed(self, request, *args, **kwargs): allowed_methods = [m for m in self.http_method_names if hasattr(self, m)] logger.warning('Method Not Allowed (%s): %s' % (request.method, request.path), extra={ 'status_code': 405, 'request': self.request } ) return http.HttpResponseNotAllowed(allowed_methods) class TemplateResponseMixin(object): """ A mixin that can be used to render a template. """ template_name = None response_class = TemplateResponse def render_to_response(self, context, **response_kwargs): """ Returns a response with a template rendered with the given context. """ return self.response_class( request = self.request, template = self.get_template_names(), context = context, **response_kwargs ) def get_template_names(self): """ Returns a list of template names to be used for the request. Must return a list. May not be called if render_to_response is overridden. """ if self.template_name is None: raise ImproperlyConfigured( "TemplateResponseMixin requires either a definition of " "'template_name' or an implementation of 'get_template_names()'") else: return [self.template_name] class TemplateView(TemplateResponseMixin, View): #表示有两个父类 """ A view that renders a template. """ def get_context_data(self, **kwargs): return { 'params': kwargs } def get(self, request, *args, **kwargs): context = self.get_context_data(**kwargs) return self.render_to_response(context) #add by xk=新增项==============================================# class IncreaseLink(tables.LinkAction): name = "increase" verbose_name = _("Increase") url = "horizon:nova:images_and_snapshots:snapshots:create" classes = ("ajax-modal", "btn-camera") #def allowed(self, request, instance=None): # retturn instance.status in ACTIVE_STATES #============================================================# Add 虚拟机创建规则功能和主机选择功能 vim /opt/horizon-2012.1/horizon/dashboards/nova/images_and_snapshots/images/forms.py +175 class LaunchForm(forms.SelfHandlingForm): name = forms.CharField(max_length=80, label=_("Server Name")) image_id = forms.CharField(widget=forms.HiddenInput()) tenant_id = forms.CharField(widget=forms.HiddenInput()) user_data = forms.CharField(widget=forms.Textarea, label=_("User Data"), required=False) flavor = forms.ChoiceField(label=_("Flavor"), help_text=_("Size of image to launch.")) #add by xk 2012-12-27 rouler = forms.ChoiceField(label=_("rouler"), help_text=_("Rouler of image to create.")) #-------------------# .. .. api.server_create(request, data['name'], data['image_id'], data['flavor'], #add by xk 2012-12-27 data['rouler'], #--------------------# meta, data.get('keypair'), normalize_newlines(data.get('user_data')), data.get('security_groups'), dev_mapping, instance_count=data.get('count')) messages.success(request, _('Instance "%s" launched.') % data["name"]) 重启apache #效果如下 #=======launch按钮涉及的页面====================================# vim /opt/horizon-2012.1/horizon/dashboards/nova/templates/nova/images_and_snapshots/images/_launch.html vim /opt/horizon-2012.1/horizon/templates/horizon/common/_form_fields.html Managers interact with a particular type of API (servers, flavors, images, etc.) and provide CRUD operations for them. 《开源人》