Ejemplo n.º 1
0
def _render_custom_html(tpl, name, obj):
    if tpl:
        tpl = TextTemplate(tpl)

        ctx = {name: obj}
        stream = tpl.generate(**ctx)
        return stream.render()
    else:
        return None
Ejemplo n.º 2
0
def do_project_branch_imagedef_create(self, args):
   
    # https://$RBA/api/products/$PROJECT_SHORTNAME/versions/1.0/imageTypeDefinitions
    # PUT XML ... imagedef-esx-x86.template

    # $RBA
    # $PROJECT_SHORTNAME
    # $FREESPACE == 1024 (MB)

    moduledir = os.path.dirname(self.sys.modules['rpathcmd.systems'].__file__)
    xmldir = moduledir + '/xml/'
    templatefile = xmldir + 'imagedef-esx-x8664.template'
    templatedata = open(templatefile, 'r')

    (args, options) = parse_arguments(args)
    projectshortname = args[0]
    branch_name = args[1]
    freespace = args[2]

    values = {  'RBA': self.options.server,
                'PROJECT_SHORTNAME': projectshortname,
                'BRANCH_NAME': branch_name,
                'FREESPACE': freespace}

    template = TextTemplate(templatedata, lookup='lenient')
    stream = template.generate(**values)
    postxml = stream.render('text')


    print "-----------<POSTDATA>-----------"
    print postxml
    print "-----------<POSTDATA>-----------"

    # initialize httlib2 and add credentials
    h2 = httplib2.Http("~/.rpathcmd/.cache")
    h2.disable_ssl_certificate_validation = True
    h2.add_credentials(self.options.username, self.options.password)

    # make POST request
    returndata = h2.request('http://' + self.options.server +
                            '/api/products/' + str(projectshortname) + 
                            '/versions/' + branch_name + '/imageDefinitions',
                            headers={'Content-Type': 'application/xml'},
                            method="PUT",
                            body=postxml)

    #epdb.st()
    #pprint(returndata)
    if returndata[0]['status'] != '200':
        print "creation failed: %s" % returndata[0]['status']
        sys.exit(1)
    else:
        print "creation completed: %s" % returndata[0]['status']


    returnxml = xobj.parse(returndata[1])
    print returnxml
Ejemplo n.º 3
0
def _render_custom_html(tpl, name, obj):
    if tpl:
        tpl = TextTemplate(tpl)

        ctx = {name: obj}
        stream = tpl.generate(**ctx)
        return stream.render()
    else:
        return None
Ejemplo n.º 4
0
def do_project_create(self, args):
   
    # https://qa3.eng.rpath.com/api/v1/projects
    # POST XML ... project_template.xml

    # $NAME
    # $SHORT_NAME

    print "not done"
    moduledir = os.path.dirname(self.sys.modules['rpathcmd.systems'].__file__)
    xmldir = moduledir + '/xml/'
    templatefile = xmldir + 'project_template.xml'
    templatedata = open(templatefile, 'r')

    (args, options) = parse_arguments(args)
    projectname = args[0]
    projectshortname = args[1]

    values = {  'NAME': projectname,
                'SHORT_NAME': projectshortname}

    template = TextTemplate(templatedata, lookup='lenient')
    stream = template.generate(**values)
    postxml = stream.render('text')
    print "########## <POSTDATA> ##########"
    print postxml
    print "########## ^POSTDATA^ ##########"    


    # initialize httlib2 and add credentials
    h2 = httplib2.Http("~/.rpathcmd/.cache")
    h2.disable_ssl_certificate_validation = True
    h2.add_credentials(self.options.username, self.options.password)

    # make POST request
    returndata = h2.request('http://' + self.options.server +
                            '/api/v1/projects',
                            headers={'Content-Type': 'application/xml'},
                            method="POST",
                            body=postxml)

    #pprint(returndata)
    if returndata[0]['status'] != '200':
        print "creation failed: %s" % returndata[0]['status']
        sys.exit(1)
    else:
        print "creation completed: %s" % returndata[0]['status']


    returnxml = xobj.parse(returndata[1])
    #epdb.st()
    print "projectid: %s" % returnxml.project.project_id
    print "name: %s" % returnxml.project.name
    print "shortname: %s" % returnxml.project.short_name
    print "hostname: %s" % returnxml.project.hostname
    def _engine_genshi(self, expression, record):
        '''
        :param expression: Expression to evaluate
        :param record: Browse record
        '''
        if not expression:
            return u''

        template = TextTemplate(expression)
        template_context = self.template_context(record)
        return template.generate(**template_context).render(encoding='UTF-8')
    def _engine_genshi(self, expression, record):
        '''
        :param expression: Expression to evaluate
        :param record: Browse record
        '''
        if not expression:
            return u''

        template = TextTemplate(expression)
        template_context = self.template_context(record)
        return template.generate(**template_context).render(encoding='UTF-8')
Ejemplo n.º 7
0
    def _render_custom_html(self, tpl, obj):
        if tpl:
            tpl = TextTemplate(tpl)

            d = dict(obj)
            if '_id' in d:
                d['id'] = str(d.pop('_id'))

            ctx = {'entry': d}
            stream = tpl.generate(**ctx)
            return stream.render()
        else:
            return None
Ejemplo n.º 8
0
 def test_in_text_template(self):
     """
     Verify that the directive works as expected in a text template.
     """
     tmpl = TextTemplate("""
       #def echo(greeting, name='world')
         ${greeting}, ${name}!
       #end
       ${echo('Hi', name='you')}
     """)
     self.assertEqual("""
                   Hi, you!
     """, str(tmpl.generate()))
Ejemplo n.º 9
0
    def test_in_text_template(self):
        """
        Verify that the directive works as expected in a text template.
        """
        tmpl = TextTemplate("""
          #def echo(greeting, name='world')
            ${greeting}, ${name}!
          #end
          ${echo('Hi', name='you')}
        """)
        self.assertEqual("""
                      Hi, you!

        """, tmpl.generate().render(encoding=None))
Ejemplo n.º 10
0
def process_template(template_file, outpath, params):
  fh = open(template_file)
  tmpl = TextTemplate(fh.read())
  stream = tmpl.generate(
    title=params["title"],
    content=params["content"],
    project_name=params.get("project_name"),
    project_dir=params.get("project_dir"))

  path = os.path.dirname(outpath)
  if not os.path.exists(path):
    os.makedirs(path)

  out = open(outpath, 'w')
  out.write(stream.render())
  out.close()
Ejemplo n.º 11
0
    def get_email(self, record, sender, to, cc, bcc, languages):
        pool = Pool()
        Attachment = pool.get('notification.email.attachment')

        # TODO order languages to get default as last one for title
        content, title = get_email(self.content, record, languages)
        language = list(languages)[-1]
        from_ = sender
        with Transaction().set_context(language=language.code):
            notification = self.__class__(self.id)
            if notification.from_:
                from_ = notification.from_
            if self.subject:
                title = (TextTemplate(
                    notification.subject).generate(record=record).render())

        if self.attachments:
            msg = MIMEMultipart('mixed')
            msg.attach(content)
            for report in self.attachments:
                msg.attach(Attachment.get_mime(report, record, language.code))
        else:
            msg = content

        set_from_header(msg, sender, from_)
        msg['To'] = ', '.join(to)
        msg['Cc'] = ', '.join(cc)
        msg['Subject'] = Header(title, 'utf-8')
        msg['Auto-Submitted'] = 'auto-generated'
        return msg
Ejemplo n.º 12
0
def templatize():

    infile = sys.argv[1]
    infiledata = open(infile, 'r')

    env = os.environ.copy()
    #print env

    # use lenient mode to prevent errors on missing vars
    tmpl = TextTemplate(infiledata, lookup='lenient')

    # fill in values with env variables
    stream = tmpl.generate(**env)

    # print rendered template
    print stream.render('text')
Ejemplo n.º 13
0
 def test_in_text_template(self):
     """
     Verify that the directive works as expected in a text template.
     """
     tmpl = TextTemplate("""#choose
       #when 1 == 1
         1
       #end
       #when 2 == 2
         2
       #end
       #when 3 == 3
         3
       #end
     #end""")
     self.assertEqual("""            1\n""", str(tmpl.generate()))
Ejemplo n.º 14
0
 def test_in_text_template(self):
     """
     Verify that the directive works as expected in a text template.
     """
     tmpl = TextTemplate("""#choose
       #when 1 == 1
         1
       #end
       #when 2 == 2
         2
       #end
       #when 3 == 3
         3
       #end
     #end""")
     self.assertEqual("""            1\n""", str(tmpl.generate()))
Ejemplo n.º 15
0
    def get(self, record):
        pool = Pool()
        Model = pool.get(self.model.model)
        record = Model(int(record))

        values = {}
        for attr, key in [
                ('recipients', 'to'),
                ('recipients_secondary', 'cc'),
                ('recipients_hidden', 'bcc'),
                ]:
            field = getattr(self, attr)
            try:
                if field:
                    if field.name == 'id':
                        value = record
                    else:
                        value = getattr(record, field.name, None)
                    if value:
                        values[key] = self.get_addresses(value)
                else:
                    value = getattr(self, attr + '_pyson')
                    if value:
                        value = self.eval(record, value)
                        if value:
                            values[key] = self.get_addresses(value)
            except AccessError:
                continue

        if self.subject:
            try:
                values['subject'] = (TextTemplate(self.subject)
                    .generate(record=record)
                    .render())
            except AccessError:
                pass
        if self.body:
            try:
                values['body'] = (TextTemplate(self.body)
                    .generate(record=record)
                    .render())
            except AccessError:
                pass
        if self.reports:
            values['reports'] = [r.id for r in self.reports]
        return values
Ejemplo n.º 16
0
 def check_body(self):
     if not self.body:
         return
     try:
         TextTemplate(self.body)
     except Exception as exception:
         raise EmailTemplateError(
             gettext('ir.msg_email_template_invalid_body',
                     template=self.rec_name,
                     exception=exception)) from exception
Ejemplo n.º 17
0
 def check_subject(self):
     if not self.subject:
         return
     try:
         TextTemplate(self.subject)
     except Exception as exception:
         raise TemplateError(
             gettext(
                 'notification_email.'
                 'msg_notification_invalid_subject',
                 notification=self.rec_name,
                 exception=exception)) from exception
Ejemplo n.º 18
0
 def check_subject(cls, templates, field_names=None):
     if field_names and 'subject' not in field_names:
         return
     for template in templates:
         if not template.subject:
             continue
         try:
             TextTemplate(template.subject)
         except Exception as exception:
             raise EmailTemplateError(
                 gettext('ir.msg_email_template_invalid_subject',
                         template=template.rec_name,
                         exception=exception)) from exception
Ejemplo n.º 19
0
 def check_body(self, templates, field_names=None):
     if field_names and 'body' not in field_names:
         return
     for template in templates:
         if not template.body:
             continue
         try:
             TextTemplate(template.body)
         except Exception as exception:
             raise EmailTemplateError(
                 gettext('ir.msg_email_template_invalid_body',
                         template=template.rec_name,
                         exception=exception)) from exception
Ejemplo n.º 20
0
def load_layout(name, path, layouts, deps=None):
    """Load the given layout template."""

    template_path = join_path(path, '_layouts', name + '.genshi')
    template_file = open(template_path, 'rb')
    content = template_file.read()
    template_file.close()

    env = {}
    front_matter = match_yaml_frontmatter(content)

    if front_matter:
        env = load_yaml(front_matter.group(1))
        layout = env.pop('layout', None)
        if layout:
            if layout not in layouts:
                load_layout(layout, path, layouts)
            deps = layouts[layout]['__deps__']
            if deps:
                deps = [layout] + deps
            else:
                deps = [layout]
        content = replace_yaml_frontmatter('', content)

    if env.get('text_template'):
        try:
            template = TextTemplate(content, encoding='utf-8')
        except Exception:
            print "Error parsing template:", name
            raise
    else:
        try:
            template = MarkupTemplate(content, encoding='utf-8')
        except Exception:
            print "Error parsing template:", name
            raise

    layouts[name] = {
        '__deps__': deps,
        '__env__': env,
        '__mtime__': stat(template_path).st_mtime,
        '__name__': name,
        '__path__': template_path,
        '__template__': template,
        }
Ejemplo n.º 21
0
 def part_text(self, contentType, filename):
     template = TextTemplate(self.source[filename].read())
     stream = template.generate(**self.templateArgs)
     return MIMEText(stream.render("text"), contentType[1])
Ejemplo n.º 22
0
def genshi2():
    template = request.GET['template']
    tmpl = TextTemplate(template)
    return HttpResponse(tmpl)
Ejemplo n.º 23
0
def render_genshi(data_dict):
    from genshi.template import TextTemplate
    tmpl = TextTemplate(graph_template)
    stream = tmpl.generate(**data_dict)
    return str(stream)
Ejemplo n.º 24
0
 def part_text(self, contentType, filename):
     template = TextTemplate(self.source[filename].read())
     stream = template.generate(**self.templateArgs)
     return MIMEText(stream.render("text"), contentType[1])
Ejemplo n.º 25
0
    itemsBySection[section].append(item)

# Actually, sort items within each section by title
for s in sectionOrder:
    itemsBySection[s].sort(key=lambda i: i["title"])

# Merge our section order & dict of sections into an ordered list of sections
sections = [(s, itemsBySection[s]) for s in sectionOrder]

# Load templates
with file("list.xml", "r") as f:
    listTemplate = MarkupTemplate(f)
with file("item.xml", "r") as f:
    itemTemplate = MarkupTemplate(f)
with file("title.xml", "r") as f:
    titleTemplate = TextTemplate(f)

# Now let's write stuff, starting by nuking the output directory
try:
    shutil.rmtree(OUTDIR)
except OSError, e:
    pass
os.makedirs(OUTDIR)

# Write the single-file version
printHTML = listTemplate.generate(texts=TEXTS, sections=sections, printing=True).render("xhtml")
with file(os.path.join(OUTDIR, "print.html"), "w") as f:
    f.write(printHTML)

# Write the index page
listHTML = listTemplate.generate(texts=TEXTS, sections=sections, printing=False).render("xhtml")
Ejemplo n.º 26
0
def render_genshi(data_dict):
    from genshi.template import TextTemplate
    tmpl = TextTemplate(graph_template)
    stream = tmpl.generate(**data_dict)
    return str(stream)
Ejemplo n.º 27
0
def generate_configs(confparse, count):
    """Read out files and generate configs"""
    files = confparse['files']
    template_vars = confparse['template']
    templates = dict([(x, open(x, 'r').read()) for x in files.values()])
    nginx_conn = []
    supervisor_apps = []
    for k in range(count):
        out_wsgi_ini_fname = "%s%d.ini" % (template_vars['file_name'], k)
        out_wsgi = TextTemplate(templates[files['wsgi_template']])
        # Write out each of uwsgi config
        with open(out_wsgi_ini_fname, 'w') as out_fd:
            out_fd.write(out_wsgi.generate(count=k, **template_vars).__str__())

        out_nginx = TextTemplate(nginx_conn_str)
        nginx_conn.append(
            out_nginx.generate(count=k, **template_vars).__str__())
        out_super = TextTemplate(supervisor_app_str)
        supervisor_apps.append(
            out_super.generate(count=k, **template_vars).__str__())

    # Write out nginx config
    with open('site.conf', 'w') as out_fd:
        nginx_conn = "\n".join(nginx_conn)
        tmpl = TextTemplate(templates[files['nginx_template']])
        stream = tmpl.generate(server_block=nginx_conn, **template_vars)
        out_fd.write(stream.__str__())

    # Write out supervisord config
    with open('supervisord.conf', 'w') as out_fd:
        out_fd.write(open(files['supervisor_template'], 'r').read())
        out_fd.write("\n".join(supervisor_apps))
Ejemplo n.º 28
0
def do_project_branch_create(self, args):
   
    # https://qa3.eng.rpath.com/api/platforms 
    # https://$RBA/api/v1/projects/test-centos6-automation2-1347312349/project_branches
    # POST XML ... project_branch_template.xml

    # $PROJECT_SHORTNAME
    # $BRANCH_NAME
    # $RBA
    # $PLATFORM_LABEL
    # $PLATFORM_ID

    moduledir = os.path.dirname(self.sys.modules['rpathcmd.systems'].__file__)
    xmldir = moduledir + '/xml/'
    templatefile = xmldir + 'project_branch_template.xml'
    templatedata = open(templatefile, 'r')

    (args, options) = parse_arguments(args)
    projectshortname = args[0]
    branch_name = args[1]
    platform_id = args[2]
    platform_label = args[3]

    values = {  'RBA': self.options.server,
                'PROJECT_SHORTNAME': projectshortname,
                'PLATFORM_ID': platform_id,
                'PLATFORM_LABEL': platform_label,
                'BRANCH_NAME': branch_name}

    template = TextTemplate(templatedata, lookup='lenient')
    stream = template.generate(**values)
    postxml = stream.render('text')
    print "-----------<POSTDATA>-----------"
    print postxml
    print "-----------<POSTDATA>-----------" 

    # initialize httlib2 and add credentials
    h2 = httplib2.Http("~/.rpathcmd/.cache")
    h2.disable_ssl_certificate_validation = True
    h2.add_credentials(self.options.username, self.options.password)

    # make POST request
    returndata = h2.request('http://' + self.options.server +
                            '/api/v1/projects/' + str(projectshortname) + '/project_branches',
                            headers={'Content-Type': 'application/xml'},
                            method="POST",
                            body=postxml)

    #epdb.st()
    #pprint(returndata)
    if returndata[0]['status'] != '200':
        print "creation failed: %s" % returndata[0]['status']
        sys.exit(1)
    else:
        print "creation completed: %s" % returndata[0]['status']


    returnxml = xobj.parse(returndata[1])
    #epdb.st()
    print "projectid: %s" % returnxml.project_branch.project.id
    print "projectshortname: %s" % returnxml.project_branch.project.short_name
    print "branchid: %s" % returnxml.project.project_id
    print "branchname: %s" % returnxml.project_branch.name
    print "label: %s" % returnxml.project_branch.label
    print "platformlabel: %s" % returnxml.project_branch.platform_label
Ejemplo n.º 29
0
def do_image_descriptor_run(self, args):

    h2 = httplib2.Http("~/.rpathcmd/.cache")
    h2.disable_ssl_certificate_validation = True
    h2.add_credentials(self.options.username, self.options.password)

    (args, options) = parse_arguments(args)

    #epdb.st()
    filename = args[0]
    instancename = 'testvm'
    if len(args) > 1:
        instancename = args[1]

    f = open(filename)
    dataMap = yaml.load(f)
    f.close
    #epdb.st()
    '''
     'descriptor_type': 'launch',
     'event_type': 18,
     'fileid': 53,
     'imageid': 85,
     'targetid': 1}
    '''
    # set the instancename
    dataMap['Instance Name']['default'] = instancename

    # basic validation of static/known inputs 
    if dataMap['imageid'] == 'NULL':
        print "please set the imageid in %s" % filename
        sys.exit(1)

    if dataMap['fileid'] == 'NULL':
        print "please set the fileid in %s" % filename
        sys.exit(1)

    if dataMap['targetid'] == 'NULL':
        print "please set the targetid in %s" % filename   
        sys.exit(1)

    if dataMap['event_type'] == 'NULL':
        print "please set the event_type in %s" % filename   
        sys.exit(1)

    if dataMap['descriptor_type'] == 'NULL':
        print "please set the descriptor_type in %s" % filename   
        sys.exit(1)

    descriptorxml = ""  #this will get splattered into the POST XML
    errors = 0

    # basic validation of dynamic/unknown inputs
    for item in dataMap:
        try:
            # determine if item is required, and default is not NULL.
            # add item to descriptor xml if both conditions are true
            if dataMap[item]['required'] == True:
                if dataMap[item]['default'] == 'NULL':
                    print "please set the default for \"%s\" in %s" % (item, filename)
                    errors = errors + 1
                else:
                    descriptorxml += "<%s>%s</%s>" %(dataMap[item]['tag'], dataMap[item]['default'], dataMap[item]['tag'])
        except:
            pass

    #epdb.st()

    print "ERROR_COUNT: %s" % errors
    if errors > 0:
        sys.exit(1)


    # open template and templatize
    #   xml/image_launch.xml

    moduledir = os.path.dirname(self.sys.modules['rpathcmd.systems'].__file__)
    xmldir = moduledir + '/xml/'
    '''
    if dataMap['descriptor_type'] == 'deploy': 
        templatefile = xmldir + 'image_deploy.xml'
    elif dataMap['descriptor_type'] == 'launch':
        templatefile = xmldir + 'image_launch.xml'
    '''    
    templatefile = xmldir + 'image_job.xml'

    templatedata = open(templatefile, 'r')

    values = {  'RBA': self.options.server,
                'TARGET_ID': dataMap['targetid'],
                'FILE_ID': dataMap['fileid'],
                'IMAGE_ID': dataMap['imageid'], 
                'EVENT_TYPE': dataMap['event_type'],
                'EXTRA_DATA': descriptorxml  }

    template = TextTemplate(templatedata, lookup='lenient')
    #stream = template.generate(**datadict)
    stream = template.generate(**values)
    postxml = stream.render('text')

    print "-----POST_DATA-----"
    print postxml
    print "-----POST_DATA-----"

    # start job
    jobxml =  h2.request('http://' + self.options.server +
                            '/api/v1/images/' + str(dataMap['imageid']) + '/jobs',
                            headers={'Content-Type': 'application/xml'},
                            method="POST",
                            body=postxml)

    if jobxml[0]['status'] != '200':
        print "job failed: %s" % jobxml[0]['status']
        sys.exit(1)

    jobdata = xobj.parse(jobxml[1])

    job_url = jobdata.job.id
    job_status = jobdata.job.status_text
    job_status_code = jobdata.job.status_code

    while ((job_status != "Done") and
            (job_status != "Failed") and
            (job_status_code != '430')):
        jobxml = h2.request(job_url)
        jobdata = xobj.parse(jobxml[1])
        job_status = jobdata.job.status_text
        job_status_code = jobdata.job.status_code
        print job_status
        #epdb.st()
        time.sleep(2)    
Ejemplo n.º 30
0
def sendReport(contact_channel, start, end, title, frequency, server_groups, include_all_servers, show_average_response_time):

    contact = contact_channel.contact
    customer = contact.customer
    
    overall_avail = 0.
    total_outages = 0
    total_downtime = timedelta(seconds=0)
    num_servers = 0
    servers = []

    server_groups.sort(key=operator.attrgetter('nested_name'))

    for group in server_groups:

        group_servers = []
        for server in group.compound_services + group.servers:
            if server.status != 'active': continue
            (avail, outages) = server.getAvailability(start, end)
            overall_avail += avail
            outage_details = {}

            # Extract the availability information from the list of outages
            for (mp, num_outages, service_avail, downtime) in outages:
                total_outages += num_outages
                total_downtime += downtime
                avail_string = availabilityFormatString(service_avail*100., customer) % (100.*service_avail)

                if mp: 
                    key = mp.id
                    mp_name = mp.service_type.name
                    if mp.name: mp_name += " : %s" % mp.name
                else: 
                    key = "cs%s" % server.id
                    mp_name = ""

                if mp and show_average_response_time:
                    avg_response_time = customer.getAvailabilityFormat() % mp.getAverageResponseTime(start, end)
                else:
                    avg_response_time = ''
                outage_details[key] = (mp_name, num_outages, avail_string, downtime, avg_response_time)

            # Get average response time information for any servers that didn't have outages
            if server.__class__.__name__ != 'CompoundService':
                for mp in server.active_monitor_points:
                    if not outage_details.has_key(mp.id):
                        if show_average_response_time:
                            avg_response_time = customer.getAvailabilityFormat() % mp.getAverageResponseTime(start, end)
                        else:
                            avg_response_time = 0.
                        mp_name = mp.service_type.name
                        if mp.name: mp_name += unicode(" - %s" % mp.name)
                        outage_details[mp.id] = (mp_name,
                                                 0,
                                                 availabilityFormatString(100., customer) % 100., 
                                                 timedelta(hours=0), 
                                                 avg_response_time)
                    
            if include_all_servers or (avail != 1.0 or outages):
                # Only show a specific server if there's been an outage, unless the customer has 
                # chosen to show all servers
                avail_string = availabilityFormatString(avail*100., customer) % (100.*avail)
                group_servers.append((server, avail_string, sorted(outage_details.values())))
    
            num_servers += 1
        if group_servers: servers.append((group, group_servers))

    if num_servers:
        overall_avail = overall_avail*100./(1.0*num_servers)
        format_str = availabilityFormatString(overall_avail, customer)
        overall_avail = format_str % overall_avail
    else:
        # Don't send the email if they have no servers to report on
        return

    if total_outages:
        average_downtime = formatTimedelta(total_downtime/total_outages)
    else:
        average_downtime = unicode(_("N/A"))
    total_downtime = formatTimedelta(total_downtime)
    
    report_type = string.capwords(frequency)
   
    from_address = turbogears.config.get('from_address', '*****@*****.**')
    reply_to_address = turbogears.config.get('reply_to_address', '*****@*****.**')
    bcc_address = turbogears.config.get('bcc_address', '*****@*****.**')
    to_address = contact_channel.email_address

    if customer.brand and customer.brand.isWhiteLabel() and customer.brand.support_email_address:
        from_address = customer.brand.support_email_address
        reply_to_address = customer.brand.support_email_address

    # Get the fragments to use for building the report content
    html_start = customer.getTemplateFragment('email.report.header')
    header = customer.getTemplateFragment('email.header')
    intro = customer.getTemplateFragment('email.report.intro')
    conclusion = customer.getTemplateFragment('email.report.conclusion')
    copyright = customer.getTemplateFragment('email.copyright')

    # Generate the HTML version of the report - Genshi for the actual report body,
    # glued together with other fragments
    tmpl = MarkupTemplate(open("ReportTemplate.html"))
    tmpl.filters.insert(0, Translator(_))
    stream = tmpl.generate(overall_avail=overall_avail,
                           controlpanel_url=customer.getControlPanelURL().rstrip('/'),
                           servers=servers, 
                           title=title,
                           report_type=report_type,
                           total_downtime=total_downtime,
                           average_downtime=average_downtime, 
                           total_outages=total_outages, 
                           num_servers=num_servers,
                           formatTimedelta=formatTimedelta,
                           show_average_response_time=show_average_response_time)
    
    report_html = stream.render('html', None)

    if html_start:
        html = html_start.body_html
    else:
        html = HTML_HEADER

    if header: html += header.body_html 
    html += "<h1>%s</h1>" % title
    if intro: html += intro.body_html
    html += report_html
    if conclusion: html += conclusion.body_html
    if copyright: html += copyright.body_html

    # Generate the text version of the report
    text_tmpl = TextTemplate(unicode(open("ReportTemplate.txt").read(), 'utf8'))
    text_tmpl.filters.insert(0, Translator(_))
    text_stream = text_tmpl.generate(overall_avail=overall_avail,
                                     servers=servers,
                                     title=title,
                                     report_type=report_type,
                                     total_downtime=total_downtime,
                                     average_downtime=average_downtime, 
                                     total_outages=total_outages,
                                     num_servers=len(customer.servers),
                                     formatTimedelta=formatTimedelta,
                                     show_average_response_time=show_average_response_time,
                                     center=center)
    report_text = text_stream.render('text')
    text = u""
    if header: text += header.body_text + "\n"
    text += "\n%s\n===============================================================================\n\n" % title
    if intro: text += intro.body_text + "\n\n"

    text += report_text + "\n\n"
    if conclusion: text += conclusion.body_text + "\n\n"
    if copyright: text += copyright.body_text + "\n"

    msg = buildEmail(from_address, to_address, title, text, html, reply_to_address)

#     msg = MIMEMultipart('related')
#     msg['Subject'] = title
#     msg['From'] = from_address
#     msg['To'] = to_address
#     msg['Reply-To'] = reply_to_address
#     msg.preamble = "This is a multi-part message in MIME format."
   
#     # Encapsulate the plain and HTML versions of the message body in an
#     # 'alternative' part, so message agents can decide which they want to display.
#     msgAlternative = MIMEMultipart('alternative')
#     msg.attach(msgAlternative)
                
#     msg_text = MIMEText(text)
#     msgAlternative.attach(msg_text)
    
#     msgAlternative.attach(MIMEText(html, 'html'))
    
    username = turbogears.config.get("smtpuser", "")
    password = turbogears.config.get("smtppass", "")
    
    s = smtplib.SMTP(turbogears.config.get('smtpserver', 'localhost'))
    if username and password:
        s.login(username, password)
    s.sendmail(from_address, [to_address, bcc_address], msg.as_string())
    s.quit()
    logging.info("Sent report to %s" % to_address)