├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── README_en-US.md ├── bib ├── detail.bib ├── intro.bib ├── tech.bib ├── test.bib └── thesis.bib ├── bst └── GBT7714-2005NLang.bst ├── compile.bat ├── figure ├── detail │ ├── apidoc.png │ ├── detail.graffle │ ├── log.png │ ├── tree.png │ └── vcs.png ├── example │ ├── flow_chart.tex │ ├── sjtulogo.eps │ ├── sjtulogo.jpg │ ├── sjtulogo.pdf │ └── sjtulogo.png ├── impl │ ├── design.graffle │ ├── design.png │ ├── vcs.png │ └── workflow.png ├── sjtu.jpg ├── sjtubadge.png ├── sjtubanner.png ├── tech │ ├── architecture.png │ ├── architure.graffle │ ├── container.png │ └── vm.png ├── test │ ├── distributed.png │ ├── test.graffle │ └── test.png └── 为了证明pull时间最长.png ├── latexmkrc ├── pdf ├── authorization.pdf └── original.pdf ├── sjtuthesis.cfg ├── sjtuthesis.cls ├── statement.pdf ├── tex ├── abstract.tex ├── ack.tex ├── app_cjk.tex ├── app_eq.tex ├── app_log.tex ├── app_setup.tex ├── big-english-abstract.txt ├── config.tex ├── detail.tex ├── end_english_abstract.tex ├── example.tex ├── faq.tex ├── id.tex ├── impl.tex ├── intro.tex ├── patents.tex ├── projects.tex ├── projectsreview.tex ├── pub.tex ├── pubreview.tex ├── req.tex ├── summary.tex ├── symbol.tex ├── tech.tex ├── test.tex └── test_result.tex ├── texcount.pl ├── thesis.pdf └── thesis.tex /.gitignore: -------------------------------------------------------------------------------- 1 | *.pdf 2 | !thesis.pdf 3 | !statement.pdf 4 | *.bak 5 | *.fls 6 | *.aux 7 | *.log 8 | *.lot 9 | *.out 10 | *.toc 11 | *.blg 12 | *.bbl 13 | *.lof 14 | *.swp 15 | *.swo 16 | *.xdv 17 | *~ 18 | *.fdb_latexmk 19 | *.zip 20 | *.gz 21 | *.bcf 22 | *.xml 23 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {2015} {Jianwen Wei} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | THESIS = thesis 2 | # TEX, BIB, TEST dir 3 | TEX_DIR = tex 4 | BIB_DIR = bib 5 | 6 | # Option for latexmk 7 | LATEXMK_OPT_BASE = -xelatex -gg -silent 8 | LATEXMK_OPT = $(LATEXMK_OPT_BASE) -f 9 | LATEXMK_OPT_PVC = $(LATEXMK_OPT_BASE) -pvc 10 | 11 | all: $(THESIS).pdf 12 | 13 | .PHONY : all clean pvc view wordcount git zip 14 | 15 | $(THESIS).pdf : $(THESIS).tex $(TEX_DIR)/*.tex $(BIB_DIR)/*.bib sjtuthesis.cls sjtuthesis.cfg Makefile 16 | -latexmk $(LATEXMK_OPT) $(THESIS) 17 | 18 | pvc : 19 | latexmk $(LATEXMK_OPT_PVC) $(THESIS) 20 | 21 | validate : 22 | xelatex -no-pdf -halt-on-error $(THESIS) 23 | biber --debug $(THESIS) 24 | 25 | view : $(THESIS).pdf 26 | open $< 27 | 28 | wordcount: 29 | @perl texcount.pl $(THESIS).tex -inc | awk '/total/ {getline; print "词数 :",$$4}' 30 | @perl texcount.pl $(THESIS).tex -inc -char | awk '/total/ {getline; print "字符数 :",$$4}' 31 | @perl texcount.pl $(THESIS).tex -inc -ch-only | awk '/total/ {getline; print "中文字数:",$$4}' 32 | 33 | clean : 34 | latexmk -C 35 | -@rm -f *.xdv *.bbl *.fls $(TEX_DIR)/*.xdv $(TEX_DIR)/*.aux $(TEX_DIR)/*.log $(TEX_DIR)/*.fls _tmp_.pdf *.xml 2> /dev/null || true 36 | 37 | s3 : $(THESIS).pdf 38 | s3cmd put $< s3://sjtuthesis/README_0.7.pdf 39 | 40 | git : 41 | for b in "0.7.x" "0.8.x" "develop" "develop-0.7" "develop-0.8"; do git co $${b}; git push --tags -f -u gitlab $${b}; git push --tags -f -u github $${b}; git push -f -u gitcafe $${b}; done 42 | git co master; git push gitlab master; git push github master; git push gitcafe master 43 | 44 | zip : 45 | git archive --format zip --output thesis.zip master 46 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 上海交通大学学位论文模板 2 | 3 | [English README](README_en-US.md) 4 | 5 | 这是为撰写上海交通大学学士、硕士或博士论文而准备的 XeLaTeX 模板,非官方出品。生成的学位论文文件参见 [README.pdf][README],详细使用说明参见 [SJTUThesis Wiki](https://github.com/weijianwen/SJTUThesis/wiki),欢迎大家分享使用经验。 6 | 7 | ## 如何使用 8 | 9 | SJTUThesis可以在本地编译,也可以在线编译。 10 | 11 | ### 本地编译 - 系统需求 12 | 13 | #### TeX 发行版 14 | 15 | SJTUThesis 需要使用 XeTeX 引擎编译。2014和2015年的 [TeXLive](https://www.tug.org/texlive/) 和 [MacTeX](https://www.tug.org/mactex/) 发行版都能编译此模板。Windows 下的 CTeX(2.9.2) 也能顺利编译此模板。**Windows用户**推荐使用 [Babun](http://babun.github.io/) 作为命令行终端。Babun 已默认安装有这些工具:git(版本控制)、GNUmake(编译控制)、perl(字数统计)。 16 | 17 | #### 字体 18 | 19 | 中英文分别依赖 Adobe 的四套简体中文字体和 TeX Gyre Termes 西文字体。Tex Gyre Termes 可从 [CTAN](http://www.ctan.org/tex-archive/fonts/tex-gyre/fonts/opentype/public/tex-gyre) 下载四种不同字型。出于版权考虑,需要大家自行解决 AdobeSongStd, AdobeKaitiStd, AdobeHeitiStd, AdobeFangsongStd 四款中文字体的授权问题。 20 | 21 | ### 在线编译 - ShareLaTeX 22 | 23 | [ShareLaTeX](https://www.sharelatex.com/) 是一个优秀的 LaTeX 在线编译站点,可以完成 SJTUThesis 0.8.1 版本的编译。在[SJTUThesis-0.8](https://www.sharelatex.com/project/56701ac8d63cd1d9646a622f)页面将该项目复制到自己的列表中,就可以开始在模版上工作了。更详细的使用说明,请参考[Usage - 使用文档](https://github.com/weijianwen/SJTUThesis/wiki/Usage)。 24 | 25 | ### 获取模板 26 | 27 | 根据「系统需求」中情形选择适合你系统情况的分支,然后根据情况选择 git 克隆最新版代码或者下载稳定版压缩包。 28 | 29 | #### 终端中克隆最新版 30 | 31 | cd 32 | git clone https://github.com/weijianwen/SJTUThesis.git 33 | 34 | 如果之前有克隆过此模板但是想与 GitHub 上的最新版本同步,以`master`分支为例,执行以下命令更新到最新版。 35 | 36 | git pull origin master 37 | 38 | 若是自己 fork 后克隆下来的,则执行以下命令。 39 | ``` 40 | git pull upstream master 41 | ``` 42 | 43 | #### 压缩包下载 44 | 45 | SJTUThesis提供了多个稳定版供您使用,这些版本的输出结果具有相近的外观,但依赖不同的TeXLive发行版和参考文献处理程序。 46 | 47 | | TeXLive发行版 | 参考文献处理程序 | SJTUThesis版本 | 48 | |---------------|------------------------------|----------------| 49 | | 2015 | biber+biblatex+caspervector | [0.9.3][0.9.3] | 50 | | 2015 | bibtex+GBT7714-2005NLang.bst | [0.7.7][0.7.7] | 51 | | 2014 | biber+biblatex+caspervector | [0.8.7][0.8.7] | 52 | | 2013 | bibtex+GBT7714-2005NLang.bst | [0.7.1][0.7.1] | 53 | 54 | ### 编译模板 55 | 56 | 编译模板,生成学位论文PDF文件。GNUMake将调用`latexmk`程序,自动完成模板的多轮编译。 57 | 58 | make pvc 59 | 60 | 定稿后可使用以下命令生成最终版本。 61 | 62 | make clean thesis.pdf 63 | 64 | 若需要生成用于提交盲审的论文(隐去作者、导师等信息),可在`thesis.tex`中为`sjtuthesis`文档类添加`review`选项。 若需要生成包含“原创性声明扫描件”和“授权书”签名扫描件的学位论文,请将扫描件分别保存为`pdf/origignal.pdf`和`pdf/authorization.pdf`,然后添加`submit`选项重新编译模板。 65 | 66 | #### Windows用户编译 67 | 68 | 双击`compile.bat`即可完成编译过程,生成`thesis.pdf`,不依赖于 GNUMake。 69 | 70 | ### 字数统计 71 | 72 | make wordcount 73 | 74 | ### 问题诊断 75 | 76 | 编译失败时,可以尝试手动逐次编译。 77 | 结合文档 [README.pdf][README] 中的说明,有助于定位故障。 78 | 79 | xelatex -no-pdf thesis 80 | bibtex thesis 81 | xelatex thesis 82 | xelatex thesis 83 | 84 | ## 反馈问题 85 | 86 | 建议以如下的顺序反馈使用问题: 87 | 88 | * [在 GitHub 项目主页开 issue](https://github.com/weijianwen/SJTUThesis/issues) 89 | * [在水源 BBS TeX_LaTeX 版发帖](https://bbs.sjtu.edu.cn/bbsdoc?board=TeX_LaTeX) 90 | 91 | ## 后续工作计划 92 | 93 | * 精简代码; 94 | * 改进开章页设计; 95 | 96 | ## 软件许可证 97 | 98 | 上海交通大学校徽图片(`sjtulog.png`)和横幅图片(`sjtubanner.png`)的版权归原作者所有。其他部分使用 [Apache License 2.0](LICENSE) 授权。 99 | 100 | [README]: https://s3.amazonaws.com/sjtuthesis/README_0.7.pdf 101 | [0.9.3]: https://github.com/weijianwen/SJTUThesis/releases/tag/0.9.3 102 | [0.8.7]: https://github.com/weijianwen/SJTUThesis/releases/tag/0.8.7 103 | [0.7.7]: https://github.com/weijianwen/SJTUThesis/releases/tag/0.7.7 104 | [0.7.1]: https://github.com/weijianwen/SJTUThesis/releases/tag/0.7.1 105 | -------------------------------------------------------------------------------- /README_en-US.md: -------------------------------------------------------------------------------- 1 | # What is SJTUThesis? 2 | 3 | SJTUThesis is an *unofficial* XeLaTeX template for preparing bachelor, master, or doctor thesis in Shanghai Jiao Tong University. 4 | 5 | The generated thesis example PDF file can be found at `README.pdf` (this file has been removed, see weijianwen/SJTUThesis/#26 contributing PDF into repo will increase the repo size) . The user guide will be found at [SJTUThesis Wiki](https://github.com/weijianwen/SJTUThesis/wiki),welcome for contribution。 6 | 7 | ## User Guide 8 | 9 | `SJTUThesis` can be compile at your local machine, or on the Cloud service. 10 | 11 | ### System Requirement of Locally Compile 12 | 13 | #### TeX Distribution 14 | 15 | SJTUThesis requires XeTeX。[TeXLive](https://www.tug.org/texlive/) distributed on 2014 and 2015, [MacTeX](https://www.tug.org/mactex/) released distribution can be used for compile this Template. CTeX(2.9.2) in Windows can be also compile this successfully. 16 | 17 | [Babun](http://babun.github.io/) is recommended for **Windows User** as the `bash` terminal, which contains `git`, `GNUmake` and `perl` by default. 18 | 19 | #### Fonts 20 | 21 | Chinese contents depend on four Adobe Simplified Chinese fonts, and English depends on TeX Gyre Termes font. Tex Gyre Termes can be found from [CTAN](http://www.ctan.org/tex-archive/fonts/tex-gyre/fonts/opentype/public/tex-gyre) . However, in order NOT to violate the font license, we don't provide AdobeSongStd, AdobeKaitiStd, AdobeHeitiStd or AdobeFangsongStd. (see weijianwen/SJTUThesis/#74 ) 22 | 23 | ### Cloud Compiling by ShareLaTeX 24 | 25 | [ShareLaTeX](https://www.sharelatex.com/) can be used for compiling the SJTUThesis 0.8.1. 26 | Copy the page named [SJTUThesis-0.8](https://www.sharelatex.com/project/56701ac8d63cd1d9646a622f) and then start to write your thesis. 27 | 28 | For details, please read [Usage](https://github.com/weijianwen/SJTUThesis/wiki/Usage). 29 | 30 | ### Get the Template 31 | 32 | Determine the `git branch` you will use depending on your system environment. `clone` this repo or download the stable distribution package. 33 | 34 | #### Git Clone 35 | 36 | # clone a new copy 37 | cd 38 | git clone https://github.com/weijianwen/SJTUThesis.git 39 | # OR update the latest code from Github 40 | git pull origin master 41 | # OR update to your fork repo 42 | git pull upstream master 43 | 44 | 45 | #### Release Package 46 | 47 | SJTUThesis provides multiple stale release package, the are used under different TeXLive distribution and different `bib` compiler: 48 | 49 | | TeXLive distribution | bibliography compiler | SJTUThesis version | 50 | |---------------|------------------------------|----------------| 51 | | 2015 | biber+biblatex+caspervector | [0.9.3][0.9.3] | 52 | | 2015 | bibtex+GBT7714-2005NLang.bst | [0.7.7][0.7.7] | 53 | | 2014 | biber+biblatex+caspervector | [0.8.7][0.8.7] | 54 | | 2013 | bibtex+GBT7714-2005NLang.bst | [0.7.1][0.7.1] | 55 | 56 | ### Compiling the SJTUThesis 57 | 58 | # compile the SJTUThesis on --watch mode 59 | make pvc 60 | # compile, build and release the final PDF 61 | make clean thesis.pdf 62 | 63 | Adding `review` option in `thesis.tex` can remove the name of your supervisor and you 64 | in order to submit for blind review. 65 | 66 | \documentclass[master, adobefonts, review]{sjtuthesis} 67 | 68 | The location of _Original Work Declaration_ and _Authorization_ must be `./pdf`: 69 | 70 | \includepdf{pdf/original.pdf} 71 | \cleardoublepage 72 | \includepdf{pdf/authorization.pdf} 73 | \cleardoublepage 74 | 75 | 76 | #### Windows User Guide 77 | 78 | Double click the `complie.bat`, the final PDF file will be named as `thesis.pdf`. 79 | 80 | 81 | ### Word Count 82 | 83 | make wordcount 84 | 85 | ### Diagnosis 86 | 87 | # compile manully when fail to `make` 88 | xelatex -no-pdf thesis 89 | biber --debug thesis 90 | xelatex thesis 91 | xelatex thesis 92 | 93 | ## Feedback 94 | 95 | We are hearing from: 96 | 97 | * [issue page of Github](https://github.com/weijianwen/SJTUThesis/issues) 98 | * [SJTU BBS](https://bbs.sjtu.edu.cn/bbsdoc?board=TeX_LaTeX) 99 | 100 | ## Further Plan 101 | 102 | * Code refactor, 103 | * Improve the style of Chapter title page 104 | 105 | ## License 106 | 107 | The copyright of image sources including SJTU badge (`sjtulog.png`) and 108 | banner (`sjtubanner.png`) belongs to the original owner. 109 | 110 | The remain part is under [Apache License 2.0](LICENSE) 111 | 112 | [README]: https://s3.amazonaws.com/sjtuthesis/README.pdf 113 | [0.9.3]: https://github.com/weijianwen/SJTUThesis/releases/tag/0.9.3 114 | [0.8.7]: https://github.com/weijianwen/SJTUThesis/releases/tag/0.8.7 115 | [0.7.7]: https://github.com/weijianwen/SJTUThesis/releases/tag/0.7.7 116 | [0.7.1]: https://github.com/weijianwen/SJTUThesis/releases/tag/0.7.1 117 | -------------------------------------------------------------------------------- /bib/detail.bib: -------------------------------------------------------------------------------- 1 | @article{websocket, 2 | title={Rfc 6455: The websocket protocol}, 3 | author={Fette, I and Melnikov, A}, 4 | journal={IETF, December}, 5 | year={2011} 6 | } 7 | -------------------------------------------------------------------------------- /bib/intro.bib: -------------------------------------------------------------------------------- 1 | %# -*- coding: utf-8-unix -*- 2 | 3 | @book{Booch, 4 | title={Object Oriented Design: With Applications}, 5 | author={Booch, G.}, 6 | isbn={9780805300918}, 7 | lccn={90034884}, 8 | series={The Benjamin/Cummings Series in Ada and Software Engineering}, 9 | url={https://books.google.com/books?id=w5VQAAAAMAAJ}, 10 | year={1991}, 11 | publisher={Benjamin/Cummings Pub.} 12 | } 13 | 14 | @mastersthesis{CruiseControls, 15 | title={基于 Jenkins 的持续集成方案设计与实现}, 16 | author={卞孟春}, 17 | year={2014}, 18 | school={中国科学院大学 (工程管理与信息技术学院)} 19 | } 20 | -------------------------------------------------------------------------------- /bib/tech.bib: -------------------------------------------------------------------------------- 1 | %# -*- coding: utf-8-unix -*- 2 | 3 | @inproceedings{soltesz2007container, 4 | title={Container-based operating system virtualization: a scalable, high-performance alternative to hypervisors}, 5 | author={Soltesz, Stephen and P{\"o}tzl, Herbert and Fiuczynski, Marc E and Bavier, Andy and Peterson, Larry}, 6 | booktitle={ACM SIGOPS Operating Systems Review}, 7 | volume={41}, 8 | number={3}, 9 | pages={275--287}, 10 | year={2007}, 11 | organization={ACM} 12 | } 13 | 14 | @article{bernstein2014containers, 15 | title={Containers and cloud: From lxc to docker to kubernetes}, 16 | author={Bernstein, David}, 17 | journal={IEEE Cloud Computing}, 18 | number={3}, 19 | pages={81--84}, 20 | year={2014}, 21 | publisher={IEEE} 22 | } 23 | 24 | @article{boettiger2015introduction, 25 | title={An introduction to Docker for reproducible research}, 26 | author={Boettiger, Carl}, 27 | journal={ACM SIGOPS Operating Systems Review}, 28 | volume={49}, 29 | number={1}, 30 | pages={71--79}, 31 | year={2015}, 32 | publisher={ACM} 33 | } 34 | 35 | @inproceedings{dua2014virtualization, 36 | title={Virtualization vs containerization to support paas}, 37 | author={Dua, Rajdeep and Raja, A Reddy and Kakadia, Dharmesh}, 38 | booktitle={Cloud Engineering (IC2E), 2014 IEEE International Conference on}, 39 | pages={610--614}, 40 | year={2014}, 41 | organization={IEEE} 42 | } 43 | -------------------------------------------------------------------------------- /bib/test.bib: -------------------------------------------------------------------------------- 1 | @article{cloc, 2 | title={Cloc--count lines of code}, 3 | author={Danial, Al}, 4 | journal={Open source}, 5 | year={2009} 6 | } 7 | -------------------------------------------------------------------------------- /bib/thesis.bib: -------------------------------------------------------------------------------- 1 | %# -*- coding: utf-8-unix -*- 2 | 3 | @book{Booch, 4 | title={Object Oriented Design: With Applications}, 5 | author={Booch, G.}, 6 | isbn={9780805300918}, 7 | lccn={90034884}, 8 | series={The Benjamin/Cummings Series in Ada and Software Engineering}, 9 | url={https://books.google.com/books?id=w5VQAAAAMAAJ}, 10 | year={1991}, 11 | publisher={Benjamin/Cummings Pub.} 12 | } 13 | 14 | @mastersthesis{CruiseControls, 15 | title={基于 Jenkins 的持续集成方案设计与实现}, 16 | author={卞孟春}, 17 | year={2014}, 18 | school={中国科学院大学 (工程管理与信息技术学院)} 19 | } 20 | 21 | @inproceedings{Borg, 22 | title={Large-scale cluster management at Google with Borg}, 23 | author={Verma, Abhishek and Pedrosa, Luis and Korupolu, Madhukar and Oppenheimer, David and Tune, Eric and Wilkes, John}, 24 | booktitle={Proceedings of the Tenth European Conference on Computer Systems}, 25 | pages={18}, 26 | year={2015}, 27 | organization={ACM} 28 | } 29 | 30 | @inproceedings{soltesz2007container, 31 | title={Container-based operating system virtualization: a scalable, high-performance alternative to hypervisors}, 32 | author={Soltesz, Stephen and P{\"o}tzl, Herbert and Fiuczynski, Marc E and Bavier, Andy and Peterson, Larry}, 33 | booktitle={ACM SIGOPS Operating Systems Review}, 34 | volume={41}, 35 | number={3}, 36 | pages={275--287}, 37 | year={2007}, 38 | organization={ACM} 39 | } 40 | 41 | @article{bernstein2014containers, 42 | title={Containers and cloud: From lxc to docker to kubernetes}, 43 | author={Bernstein, David}, 44 | journal={IEEE Cloud Computing}, 45 | number={3}, 46 | pages={81--84}, 47 | year={2014}, 48 | publisher={IEEE} 49 | } 50 | 51 | @article{boettiger2015introduction, 52 | title={An introduction to Docker for reproducible research}, 53 | author={Boettiger, Carl}, 54 | journal={ACM SIGOPS Operating Systems Review}, 55 | volume={49}, 56 | number={1}, 57 | pages={71--79}, 58 | year={2015}, 59 | publisher={ACM} 60 | } 61 | 62 | @inproceedings{dua2014virtualization, 63 | title={Virtualization vs containerization to support paas}, 64 | author={Dua, Rajdeep and Raja, A Reddy and Kakadia, Dharmesh}, 65 | booktitle={Cloud Engineering (IC2E), 2014 IEEE International Conference on}, 66 | pages={610--614}, 67 | year={2014}, 68 | organization={IEEE} 69 | } 70 | 71 | @article{websocket, 72 | title={Rfc 6455: The websocket protocol}, 73 | author={Fette, I and Melnikov, A}, 74 | journal={IETF, December}, 75 | year={2011} 76 | } 77 | 78 | @article{cloc, 79 | title={Cloc--count lines of code}, 80 | author={Danial, Al}, 81 | journal={Open source}, 82 | year={2009} 83 | } 84 | 85 | @mastersthesis{wangfei, 86 | title={基于 Docker 的研发部署管理平台的设计与实现}, 87 | author={王飞}, 88 | year={2015}, 89 | school={北京交通大学} 90 | } 91 | 92 | @article{zhangjian, 93 | title={基于 Docker 的平台即服务架构研究}, 94 | author={张建 and 谢天钧}, 95 | journal={信息技术与信息化}, 96 | number={10}, 97 | pages={131--134}, 98 | year={2014} 99 | } 100 | 101 | @article{mayue, 102 | title={基于 Docker 的应用软件虚拟化研究}, 103 | author={马越 and 黄刚}, 104 | journal={软件}, 105 | volume={3}, 106 | pages={003}, 107 | year={2015} 108 | } -------------------------------------------------------------------------------- /compile.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | del thesis.pdf >nul 2>nul 3 | if exist thesis.pdf ( 4 | echo Close the file: thesis.pdf!!! 5 | echo Or use Sumatra to open thesis.pdf 6 | pause 7 | exit 8 | ) 9 | 10 | echo Compile... 11 | echo xelatex -no-pdf thesis... 12 | xelatex -no-pdf thesis >nul 13 | echo biber --debug thesis... 14 | biber --debug thesis >nul 15 | echo xelatex thesis... 16 | xelatex thesis >nul 17 | xelatex thesis >nul 18 | echo clean files... 19 | del *.aux *.run.xml *.bcf *.log *.xdv *.bbl *.bak *.blg *.out *.thm *.toc *.synctex* *.glg *.glo *.gls *.ist *.idx *.ilg *.ind *.acn *.acr *.lof *.lot *.alg *.glsdefs >nul 2>nul 20 | cd tex 21 | del *.aux *.run.xml *.bcf *.log *.xdv *.bbl *.bak *.blg *.out *.thm *.toc *.synctex* *.glg *.glo *.gls *.ist *.idx *.ilg *.ind *.acn *.acr *.lof *.lot *.alg *.glsdefs >nul 2>nul 22 | echo finish... 23 | pause 24 | -------------------------------------------------------------------------------- /figure/detail/apidoc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gaocegege/bachelor-paper-2016/29030d0abb9a84f698551c842ea1198d8d0b1b55/figure/detail/apidoc.png -------------------------------------------------------------------------------- /figure/detail/detail.graffle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gaocegege/bachelor-paper-2016/29030d0abb9a84f698551c842ea1198d8d0b1b55/figure/detail/detail.graffle -------------------------------------------------------------------------------- /figure/detail/log.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gaocegege/bachelor-paper-2016/29030d0abb9a84f698551c842ea1198d8d0b1b55/figure/detail/log.png -------------------------------------------------------------------------------- /figure/detail/tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gaocegege/bachelor-paper-2016/29030d0abb9a84f698551c842ea1198d8d0b1b55/figure/detail/tree.png -------------------------------------------------------------------------------- /figure/detail/vcs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gaocegege/bachelor-paper-2016/29030d0abb9a84f698551c842ea1198d8d0b1b55/figure/detail/vcs.png -------------------------------------------------------------------------------- /figure/example/flow_chart.tex: -------------------------------------------------------------------------------- 1 | \begin{tikzpicture}[node distance=2cm] 2 | \node (pic) [startstop] {待测图片}; 3 | \node (bg) [io, below of=pic] {读取背景}; 4 | \node (pair) [process, below of=bg] {匹配特征点对}; 5 | \node (threshold) [decision, below of=pair, yshift=-0.5cm] {多于阈值}; 6 | \node (clear) [decision, right of=threshold, xshift=3cm] {清晰?}; 7 | \node (capture) [process, right of=pair, xshift=3cm, yshift=0.5cm] {重采}; 8 | \node (matrix_p) [process, below of=threshold, yshift=-0.8cm] {透视变换矩阵}; 9 | \node (matrix_a) [process, right of=matrix_p, xshift=3cm] {仿射变换矩阵}; 10 | \node (reg) [process, below of=matrix_p] {图像修正}; 11 | \node (return) [startstop, below of=reg] {配准结果}; 12 | 13 | %连接具体形状 14 | \draw [arrow](pic) -- (bg); 15 | \draw [arrow](bg) -- (pair); 16 | \draw [arrow](pair) -- (threshold); 17 | 18 | \draw [arrow](threshold) -- node[anchor=south] {否} (clear); 19 | 20 | \draw [arrow](clear) -- node[anchor=west] {否} (capture); 21 | \draw [arrow](capture) |- (pic); 22 | \draw [arrow](clear) -- node[anchor=west] {是} (matrix_a); 23 | \draw [arrow](matrix_a) |- (reg); 24 | 25 | \draw [arrow](threshold) -- node[anchor=east] {是} (matrix_p); 26 | \draw [arrow](matrix_p) -- (reg); 27 | \draw [arrow](reg) -- (return); 28 | \end{tikzpicture} 29 | -------------------------------------------------------------------------------- /figure/example/sjtulogo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gaocegege/bachelor-paper-2016/29030d0abb9a84f698551c842ea1198d8d0b1b55/figure/example/sjtulogo.jpg -------------------------------------------------------------------------------- /figure/example/sjtulogo.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gaocegege/bachelor-paper-2016/29030d0abb9a84f698551c842ea1198d8d0b1b55/figure/example/sjtulogo.pdf -------------------------------------------------------------------------------- /figure/example/sjtulogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gaocegege/bachelor-paper-2016/29030d0abb9a84f698551c842ea1198d8d0b1b55/figure/example/sjtulogo.png -------------------------------------------------------------------------------- /figure/impl/design.graffle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gaocegege/bachelor-paper-2016/29030d0abb9a84f698551c842ea1198d8d0b1b55/figure/impl/design.graffle -------------------------------------------------------------------------------- /figure/impl/design.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gaocegege/bachelor-paper-2016/29030d0abb9a84f698551c842ea1198d8d0b1b55/figure/impl/design.png -------------------------------------------------------------------------------- /figure/impl/vcs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gaocegege/bachelor-paper-2016/29030d0abb9a84f698551c842ea1198d8d0b1b55/figure/impl/vcs.png -------------------------------------------------------------------------------- /figure/impl/workflow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gaocegege/bachelor-paper-2016/29030d0abb9a84f698551c842ea1198d8d0b1b55/figure/impl/workflow.png -------------------------------------------------------------------------------- /figure/sjtu.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gaocegege/bachelor-paper-2016/29030d0abb9a84f698551c842ea1198d8d0b1b55/figure/sjtu.jpg -------------------------------------------------------------------------------- /figure/sjtubadge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gaocegege/bachelor-paper-2016/29030d0abb9a84f698551c842ea1198d8d0b1b55/figure/sjtubadge.png -------------------------------------------------------------------------------- /figure/sjtubanner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gaocegege/bachelor-paper-2016/29030d0abb9a84f698551c842ea1198d8d0b1b55/figure/sjtubanner.png -------------------------------------------------------------------------------- /figure/tech/architecture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gaocegege/bachelor-paper-2016/29030d0abb9a84f698551c842ea1198d8d0b1b55/figure/tech/architecture.png -------------------------------------------------------------------------------- /figure/tech/architure.graffle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gaocegege/bachelor-paper-2016/29030d0abb9a84f698551c842ea1198d8d0b1b55/figure/tech/architure.graffle -------------------------------------------------------------------------------- /figure/tech/container.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gaocegege/bachelor-paper-2016/29030d0abb9a84f698551c842ea1198d8d0b1b55/figure/tech/container.png -------------------------------------------------------------------------------- /figure/tech/vm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gaocegege/bachelor-paper-2016/29030d0abb9a84f698551c842ea1198d8d0b1b55/figure/tech/vm.png -------------------------------------------------------------------------------- /figure/test/distributed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gaocegege/bachelor-paper-2016/29030d0abb9a84f698551c842ea1198d8d0b1b55/figure/test/distributed.png -------------------------------------------------------------------------------- /figure/test/test.graffle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gaocegege/bachelor-paper-2016/29030d0abb9a84f698551c842ea1198d8d0b1b55/figure/test/test.graffle -------------------------------------------------------------------------------- /figure/test/test.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gaocegege/bachelor-paper-2016/29030d0abb9a84f698551c842ea1198d8d0b1b55/figure/test/test.png -------------------------------------------------------------------------------- /figure/为了证明pull时间最长.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gaocegege/bachelor-paper-2016/29030d0abb9a84f698551c842ea1198d8d0b1b55/figure/为了证明pull时间最长.png -------------------------------------------------------------------------------- /latexmkrc: -------------------------------------------------------------------------------- 1 | # uncomment the # before $ to enable PDF update automatically 2 | # see man latexmk for more info 3 | 4 | ## Mac OS X - Skim 5 | #$pdf_previewer = 'osascript -e "set theFile to POSIX file \"%S\" as alias" -e "set thePath to POSIX path of theFile" -e "tell application \"Skim\"" -e "open theFile" -e "end tell"'; 6 | #$pdf_update_method = 4; 7 | #$pdf_update_command = 'osascript -e "set theFile to POSIX file \"%S\" as alias" -e "set thePath to POSIX path of theFile" -e "tell application \"Skim\"" -e "set theDocs to get documents whose path is thePath" -e "try" -e "if (count of theDocs) > 0 then revert theDocs" -e "end try" -e "open theFile" -e "end tell"'; 8 | 9 | ## GNU/Linux - Evince 10 | 11 | ## Windows - Sumatra 12 | -------------------------------------------------------------------------------- /pdf/authorization.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gaocegege/bachelor-paper-2016/29030d0abb9a84f698551c842ea1198d8d0b1b55/pdf/authorization.pdf -------------------------------------------------------------------------------- /pdf/original.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gaocegege/bachelor-paper-2016/29030d0abb9a84f698551c842ea1198d8d0b1b55/pdf/original.pdf -------------------------------------------------------------------------------- /sjtuthesis.cfg: -------------------------------------------------------------------------------- 1 | %# -*- coding: utf-8-unix -*- 2 | %%================================================== 3 | %% sjtuthesis.cfg for SJTU Thesis 4 | %%================================================== 5 | 6 | \ProvidesFile{sjtuthesis.cfg}[2015/05/01 v0.7 sjtuthesis configuration file] 7 | 8 | %% 目录、插图索引、表格索引 9 | \def\sjtu@contentsname{目~~~~录} 10 | \def\sjtu@listfigurename{插图索引} 11 | \def\sjtu@listtablename{表格索引} 12 | \def\sjtu@listalgorithmname{算法索引} 13 | 14 | %% 15 | %% labels in the title page 16 | %% 17 | \def\sjtu@label@coadvisor{副导师} 18 | \def\sjtu@label@major{\CJKspace{专\quad{}\quad{}业}} 19 | \def\sjtu@label@title{论文题目} 20 | \def\sjtu@label@author{学生姓名} 21 | \def\sjtu@label@classification{分类号} 22 | \def\sjtu@label@confidential{密级} 23 | \def\sjtu@label@UDC{UDC} 24 | \def\sjtu@label@serialnumber{编号} 25 | \def\sjtu@label@thesis{学位论文} 26 | \def\sjtu@label@advisor{指导教师} 27 | \def\sjtu@label@degree{申请学位级别} 28 | \def\sjtu@label@submitdate{论文提交日期} 29 | \def\sjtu@label@defenddate{答辩日期} 30 | \def\sjtu@label@institute{学院(系)} 31 | \def\sjtu@label@school{学位授予单位} 32 | \def\sjtu@label@chairman{答辩委员会主席} 33 | \def\sjtu@label@studentnumber{学生学号} 34 | \def\sjtu@label@sjtu{SHANGHAI JIAO TONG UNIVERSITY} 35 | 36 | %% 37 | %% string values filled in the title page 38 | %% 39 | 40 | \def\sjtu@value@classification{} 41 | \def\sjtu@value@confidential{} 42 | \def\sjtu@value@serialnumber{} 43 | \def\sjtu@value@school{} 44 | \ifsjtu@bachelor 45 | \def\sjtu@value@chinesedegree{学士} 46 | \def\sjtu@label@bacheloreng{BACHELOR'S THESIS} 47 | \def\sjtu@value@englishdegree{Bachelor} 48 | \else 49 | \ifsjtu@master 50 | \def\sjtu@value@chinesedegree{硕士} 51 | \def\sjtu@value@englishdegree{Master} 52 | \else 53 | \ifsjtu@doctor 54 | \def\sjtu@value@chinesedegree{博士} 55 | \def\sjtu@value@englishdegree{Doctor} 56 | \else 57 | \ClassError{sjtuthesis}% 58 | {Unknown value for degree.}{} 59 | \fi 60 | \fi 61 | \fi 62 | \def\sjtu@label@statement{\sjtu@value@chinesedegree\sjtu@label@thesis} 63 | 64 | % 论文原创性声明 65 | \def\sjtu@label@original{学位论文原创性声明} 66 | \def\sjtu@label@authorization{学位论文版权使用授权书} 67 | \def\sjtu@label@authorsign{学位论文作者签名:} 68 | \def\sjtu@label@Supervisorsign{指导教师签名:} 69 | \def\sjtu@label@originalDate{日\hspace{1em}期:\hrulefill\hrulefill 年 \hrulefill 月 \hrulefill 日} 70 | \def\sjtu@label@originalcontent{本人郑重声明:所呈交的学位论文,是本人在导师的指导下, 独立进行研究工作所取得的成果。除文中已经注明引用的内容外,本论文不包含任何其他个人或集体已经发表或撰写过的作品成果。对本文的研究做出重要贡献的个人和集体,均已在文中以明确方式标明。本人完全意识到本声明的法律结果由本人承担。 71 | } 72 | \def\sjtu@label@authorizationcontent{本学位论文作者完全了解学校有关保留、使用学位论文的规定,同意学校保留并向国家有关部门或机构送交论文的复印件和电子版,允许论文被查阅和借阅。本人授权上海交通大学可以将本学位论文的全部或部分内容编入有关数据库进行检索,可以采用影印、缩印或扫描等复制手段保存和汇编本学位论文。\par 73 | 本学位论文属于\\ 74 | \hspace*{9em}\textbf{保\hspace{1em}密} $\square$,在~\hrulefill~年解密后适用本授权书。\\ 75 | \hspace*{9em}\textbf{不保密} $\square$。\\ 76 | (请在以上方框内打$\checked$) 77 | } 78 | 79 | 80 | %% 81 | %% labels in the english title page 82 | %% 83 | \def\sjtu@label@englishadvisor{Advisor} 84 | \def\sjtu@label@englishcoadvisor{Co-advisor} 85 | \def\sjtu@label@englishstatement{Submitted in total fulfillment 86 | of the requirements for the degree of \sjtu@value@englishdegree \\ 87 | in \sjtu@value@englishmajor} 88 | 89 | %% 90 | %% labels in the abstracts 91 | %% 92 | \def\sjtu@label@abstract{摘~~~~要} 93 | \def\sjtu@label@englishabstract{ABSTRACT} 94 | \def\sjtu@label@keywords{关键词:} 95 | \def\sjtu@label@englishkeywords{KEY WORDS:~} 96 | 97 | %% labels in the summary 98 | \def\sjtu@label@summary{全文总结} 99 | 100 | %% 101 | %% labels in the publications 102 | %% 103 | \def\sjtu@label@publications{攻读学位期间发表的学术论文} 104 | 105 | %% 106 | %% labels in the publications 107 | %% 108 | \def\sjtu@label@patents{攻读学位期间申请的专利} 109 | 110 | %% 111 | %% labels in the projects 112 | %% 113 | \def\sjtu@label@projects{攻读学位期间参与的项目} 114 | 115 | 116 | %% 117 | %% labels in the resume 118 | %% 119 | \def\sjtu@label@resume{简~~~~历} 120 | 121 | 122 | %% 123 | %% labels in the thanks 124 | %% 125 | \def\sjtu@label@thanks{致~~~~谢} 126 | 127 | %%% 128 | %% listings name 129 | %% 130 | \def\sjtu@value@listingname{代码} 131 | 132 | %% 133 | %% the theorem name definitions 134 | %% 135 | \def\sjtu@label@algo{算法} 136 | \def\sjtu@label@thm{定理} 137 | \def\sjtu@label@lem{引理} 138 | \def\sjtu@label@prop{命题} 139 | \def\sjtu@label@cor{推论} 140 | \def\sjtu@label@defn{定义} 141 | \def\sjtu@label@conj{猜想} 142 | \def\sjtu@label@exmp{例} 143 | \def\sjtu@label@rem{注} 144 | \def\sjtu@label@case{情形} 145 | \def\sjtu@label@proof{证明} 146 | 147 | \endinput 148 | 149 | %% End of file `sjtuthesis.cfg'. 150 | -------------------------------------------------------------------------------- /sjtuthesis.cls: -------------------------------------------------------------------------------- 1 | %# -*- coding: utf-8-unix -*- 2 | %================================================== 3 | %% sjtuthesis.cls for SJTU Master Thesis 4 | %%================================================== 5 | 6 | \NeedsTeXFormat{LaTeX2e}[1995/12/01] 7 | \ProvidesClass{sjtuthesis}[2015/3/15 v0.7 Shanghai Jiao Tong University Template] 8 | \def\version{v0.7} 9 | \newif\ifsjtu@bachelor\sjtu@bachelorfalse 10 | \newif\ifsjtu@master\sjtu@masterfalse 11 | \newif\ifsjtu@doctor\sjtu@doctorfalse 12 | \newif\ifsjtu@review\sjtu@reviewfalse 13 | \newif\ifsjtu@submit\sjtu@submitfalse 14 | \newif\ifsjtu@typeinfo \sjtu@typeinfotrue 15 | \DeclareOption{notypeinfo}{\sjtu@typeinfofalse} 16 | \DeclareOption{bachelor}{\sjtu@bachelortrue} 17 | \DeclareOption{master}{\sjtu@mastertrue} 18 | \DeclareOption{doctor}{\sjtu@doctortrue} 19 | \DeclareOption{review}{\sjtu@reviewtrue} 20 | \DeclareOption{submit}{\sjtu@submittrue} 21 | \DeclareOption*{\PassOptionsToClass{\CurrentOption}{ctexbook}} 22 | \ProcessOptions\relax 23 | \LoadClass[a4paper,UTF8,scheme=chinese]{ctexbook} 24 | \ifsjtu@bachelor\relax\else 25 | \ifsjtu@master\relax\else 26 | \ifsjtu@doctor\relax\else 27 | \ClassError{sjtuthesis}% 28 | {You have to specify one of thesis options: bachelor, master or doctor.}{} 29 | \fi 30 | \fi 31 | \fi 32 | 33 | %% sjtuthesis.cls segments 34 | % 0. Import sjtuthesis.cfg 35 | % 1. Import and configure LaTeX packages. 36 | % 2. Define general-purpose LaTeX commands. 37 | % 3. Configure the imported packages, also extend LaTeX command in sjtuthesis 38 | % 4. Draw the sjtuthesis 39 | 40 | %========== 41 | % Segment 0. Import sjtuthesis.cfg 42 | %========== 43 | 44 | %% 导入 sjtuthesis.cfg 文件 45 | \AtEndOfClass{\input{sjtuthesis.cfg}} 46 | 47 | 48 | %========== 49 | % Segment 1. Import LaTeX packages. 50 | %========== 51 | 52 | \RequirePackage[centering,a4paper,body={16cm,22cm}]{geometry} %设置版面 53 | \RequirePackage{fancyhdr} 54 | \RequirePackage{lastpage} 55 | \RequirePackage{fontspec} 56 | \RequirePackage{metalogo,doc} 57 | \RequirePackage{threeparttable} 58 | \RequirePackage{dcolumn} 59 | \RequirePackage{multirow} 60 | \RequirePackage{booktabs} 61 | \RequirePackage{mathtools,amsthm,amsfonts,amssymb,bm,mathrsfs} 62 | \RequirePackage{upgreek} 63 | \RequirePackage{graphicx} 64 | \RequirePackage{subfigure} 65 | \RequirePackage{ccaption} 66 | \RequirePackage[sort&compress,numbers]{natbib} 67 | \RequirePackage{xcolor} 68 | \RequirePackage{wasysym} 69 | \RequirePackage{listings} 70 | \RequirePackage[xetex, bookmarksnumbered, colorlinks, urlcolor=black, linkcolor=black, citecolor=black, plainpages=false, pdfstartview=FitH]{hyperref} 71 | \RequirePackage{longtable} 72 | \RequirePackage[perpage, bottom]{footmisc} 73 | \RequirePackage[inline]{enumitem} 74 | \RequirePackage{pdfpages} 75 | \RequirePackage{calc} 76 | \RequirePackage{algorithm, algorithmic} 77 | \RequirePackage{siunitx} 78 | \RequirePackage{tikz} 79 | \usetikzlibrary{shapes.geometric, arrows} 80 | 81 | %========== 82 | % Segment 2. Define general-purpose LaTeX commands. 83 | %========== 84 | 85 | \setcounter{secnumdepth}{4} % 章节编号深度 (part 对应 -1) 86 | \setcounter{tocdepth}{2} % 目录深度 (part 对应 -1) 87 | 88 | % User defined command list 89 | %% \me \mi \mj \dif \cleardoublepage \cndash \CJKLaTeX \upcite 90 | 91 | % A new column type 92 | \newcolumntype{d}[1]{D{.}{.}{#1}}% or D{.}{,}{#1} or D{.}{\cdot}{#1} 93 | 94 | % upper math letter 95 | \newcommand{\me}{\mathrm{e}} 96 | \newcommand{\mi}{\mathrm{i}} 97 | \newcommand{\mj}{\mathrm{j}} 98 | \newcommand{\dif}{\mathrm{d}} 99 | 100 | \def\cleardoublepage{\clearpage% 101 | \if@openright% 102 | \ifodd 103 | \c@page% 104 | \else% 105 | \thispagestyle{empty}% 106 | \hbox{}% 107 | \newpage% 108 | \fi% 109 | \fi} 110 | 111 | % CJK-LaTeX Logo \CJKLaTeX 112 | \newcommand{\CJKLaTeX}{CJK--\LaTeX} 113 | 114 | % Upper quote 115 | \newcommand{\upcite}[1]{\textsuperscript{\cite{#1}}} 116 | 117 | % cndash 118 | \newcommand{\cndash}{\rule{0.0em}{0pt}\rule[0.35em]{1.4em}{0.05em}\rule{0.2em}{0pt}} 119 | 120 | %========== 121 | % Segment 3. Configure the imported packages, also extend LaTeX command in sjtuthesis 122 | %========== 123 | 124 | % Set the mainfont 125 | \setmainfont{TeX Gyre Termes} 126 | 127 | %% 行距缩放因子 128 | \linespread{1.3} 129 | 130 | %% CTeX Settings 131 | % 名称:目录、表格索引、插图索引、算法、算法索引、代码 132 | \ctexset{contentsname={\sjtu@contentsname}} 133 | \ctexset{listfigurename={\sjtu@listfigurename}} 134 | \ctexset{listtablename={\sjtu@listtablename}} 135 | \floatname{algorithm}{\sjtu@label@algo} 136 | \renewcommand{\listalgorithmname}{\sjtu@listalgorithmname} 137 | \renewcommand{\lstlistingname}{\sjtu@value@listingname} 138 | % Title Settings at the chapter Level 139 | \ctexset{chapter={ 140 | nameformat={\Large\bfseries}, 141 | titleformat={\Large\bfseries}, 142 | beforeskip={15\p@}, 143 | afterskip={12\p@}, 144 | } 145 | } 146 | % Title Settings at the section Level 147 | \ctexset{section={ 148 | format={\large\bfseries}, 149 | afterskip={1.0ex \@plus .2ex}, 150 | } 151 | } 152 | % Title Settings at the subection Level 153 | \ctexset{subsection={ 154 | format={\bfseries\normalsize}, 155 | indent={0\ccwd}, 156 | afterskip={1.0ex \@plus .2ex}, 157 | } 158 | } 159 | % Title Settings at the subsubection Level 160 | \ctexset{subsubsection={ 161 | format={\normalfont\normalsize}, 162 | indent={0\ccwd}, 163 | afterskip={1.0ex \@plus .2ex}, 164 | } 165 | } 166 | 167 | % bullets in the item 168 | \renewcommand{\labelitemi}{\ensuremath{\bullet}} 169 | 170 | %% Graphic path & file extension 171 | \graphicspath{{fig/}{figure/}{figures/}{logo/}{logos/}{graph/}{graphs}} 172 | \DeclareGraphicsExtensions{.pdf,.eps,.png,.jpg,.jpeg} 173 | 174 | % Caption setting in ccaption pacakge 175 | \captiondelim{\ } 176 | \captionnamefont{\kaishu\small} 177 | \captiontitlefont{\kaishu\small} 178 | 179 | % Floating parameters 180 | \renewcommand{\textfraction}{0.15} 181 | \renewcommand{\topfraction}{0.85} 182 | \renewcommand{\bottomfraction}{0.65} 183 | \renewcommand{\floatpagefraction}{0.60} 184 | 185 | % 定公式、图、表、算法的编号为"3-1"的形式,即分隔符由.变为短杠 186 | \renewcommand{\theequation}{\arabic{chapter}--\arabic{equation}} 187 | \renewcommand{\thefigure}{\arabic{chapter}--\arabic{figure}} 188 | \renewcommand\p@subfigure{\thefigure} 189 | \renewcommand{\thetable}{\arabic{chapter}--\arabic{table}} 190 | \renewcommand{\thealgorithm}{\arabic{chapter}--\arabic{algorithm}} 191 | 192 | % 使用enumitem宏包配制列表环境 193 | % 紧凑间距 194 | \setlist{nosep} 195 | % 列表和段落头对齐 196 | \setlist*{leftmargin=*} 197 | \setlist[1]{labelindent=\parindent} % Only the level 1 198 | 199 | % 流程图定义基本形状 200 | \tikzstyle{startstop} = [rectangle, rounded corners, minimum width=2cm, minimum height=1cm, text centered, draw=black] 201 | \tikzstyle{io} = [trapezium, trapezium left angle=75, trapezium right angle=105, minimum width=1cm, minimum height=1cm, text centered, draw=black] 202 | \tikzstyle{process} = [rectangle, minimum width=2cm, minimum height=1cm, text centered, draw=black] 203 | \tikzstyle{decision} = [diamond, minimum width=2cm, minimum height=1cm, text centered, draw=black] 204 | \tikzstyle{arrow} = [thick,->,>=stealth] 205 | 206 | % Setting Package listings/lstlistings 207 | \lstset{tabsize=4, % 208 | frame=shadowbox, %把代码用带有阴影的框圈起来 209 | commentstyle=\color{red!50!green!50!blue!50},%浅灰色的注释 210 | rulesepcolor=\color{red!20!green!20!blue!20},%代码块边框为淡青色 211 | keywordstyle=\color{blue!90}\bfseries, %代码关键字的颜色为蓝色,粗体 212 | showstringspaces=false,%不显示代码字符串中间的空格标记 213 | stringstyle=\ttfamily, % 代码字符串的特殊格式 214 | keepspaces=true, % 215 | breakindent=22pt, % 216 | numbers=left,%左侧显示行号 217 | stepnumber=1,% 218 | numberstyle=\tiny, %行号字体用小号 219 | basicstyle={\footnotesize\ttfamily}, % 220 | showspaces=false, % 221 | flexiblecolumns=true, % 222 | breaklines=true, %对过长的代码自动换行 223 | breakautoindent=true,% 224 | breakindent=4em, % 225 | aboveskip=1em, %代码块边框 226 | %% added by http://bbs.ctex.org/viewthread.php?tid=53451 227 | fontadjust, 228 | captionpos=t, 229 | framextopmargin=2pt,framexbottommargin=2pt,abovecaptionskip=-3pt,belowcaptionskip=3pt, 230 | xleftmargin=4em,xrightmargin=4em, % 设定listing左右的空白 231 | texcl=true, 232 | % 设定中文冲突,断行,列模式,数学环境输入,listing数字的样式 233 | extendedchars=false,columns=flexible,mathescape=true 234 | numbersep=-1em 235 | } 236 | % 参考文献风格 GBT7714-2005 237 | \bibliographystyle{bst/GBT7714-2005NLang} 238 | 239 | % 定理环境 240 | \newtheoremstyle{break}% name 241 | {}% Space above, empty = `usual value' 242 | {}% Space below 243 | {\itshape}% Body font 244 | {}% Indent amount (empty = no indent, \parindent = para indent) 245 | {\bfseries}% Thm head font 246 | {.}% Punctuation after thm head 247 | {\newline}% Space after thm head: \newline = linebreak 248 | {}% Thm head spec 249 | \theoremstyle{plain} 250 | \newtheorem{algo}{\sjtu@label@algo~}[chapter] 251 | \newtheorem{thm}{\sjtu@label@thm~}[chapter] 252 | \newtheorem{lem}[thm]{\sjtu@label@lem~} 253 | \newtheorem{prop}[thm]{\sjtu@label@prop~} 254 | \newtheorem{cor}[thm]{\sjtu@label@cor~} 255 | \theoremstyle{definition} 256 | \newtheorem{defn}{\sjtu@label@defn~}[chapter] 257 | \newtheorem{conj}{\sjtu@label@conj~}[chapter] 258 | \newtheorem{exmp}{\sjtu@label@exmp~}[chapter] 259 | \newtheorem{rem}{\sjtu@label@rem~} 260 | \newtheorem{case}{\sjtu@label@case~} 261 | \theoremstyle{break} 262 | \newtheorem{bthm}[thm]{\sjtu@label@thm~} 263 | \newtheorem{blem}[thm]{\sjtu@label@lem~} 264 | \newtheorem{bprop}[thm]{\sjtu@label@prop~} 265 | \newtheorem{bcor}[thm]{\sjtu@label@cor~} 266 | \renewcommand{\proofname}{\bf\sjtu@label@proof} 267 | 268 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 269 | % The following definitions are to extend the LaTeX algorithmic 270 | % package with SWITCH statements and one-line structures. 271 | % The extension is by 272 | % Prof. Farn Wang 273 | % Dept. of Electrical Engineering, 274 | % National Taiwan University. 275 | % 276 | \newcommand{\SWITCH}[1]{\STATE \textbf{switch} (#1)} 277 | \newcommand{\ENDSWITCH}{\STATE \textbf{end switch}} 278 | \newcommand{\CASE}[1]{\STATE \textbf{case} #1\textbf{:} \begin{ALC@g}} 279 | \newcommand{\ENDCASE}{\end{ALC@g}} 280 | \newcommand{\CASELINE}[1]{\STATE \textbf{case} #1\textbf{:} } 281 | \newcommand{\DEFAULT}{\STATE \textbf{default:} \begin{ALC@g}} 282 | \newcommand{\ENDDEFAULT}{\end{ALC@g}} 283 | \newcommand{\DEFAULTLINE}[1]{\STATE \textbf{default:} } 284 | % 285 | % End of the LaTeX algorithmic package extension. 286 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 287 | 288 | %========== 289 | % Segment 4. Draw the sjtuthesis 290 | %========== 291 | 292 | \newcommand\classification[1]{\def\sjtu@value@classification{#1}} 293 | \newcommand\studentnumber[1]{\def\sjtu@value@studentnumber{#1}} 294 | \newcommand\confidential[1]{\def\sjtu@value@confidential{#1}} 295 | \newcommand\school[1]{\def\sjtu@value@school{#1}} 296 | \newcommand\chinesedegree[1]{\def\sjtu@value@chinesedegree{#1}} 297 | \renewcommand\title[2][\sjtu@value@title]{% 298 | \def\sjtu@value@title{#2} 299 | \def\sjtu@value@titlemark{\MakeUppercase{#1}}} 300 | \renewcommand\author[1]{\def\sjtu@value@author{#1}} 301 | \newcommand\advisor[1]{\def\sjtu@value@advisor{#1}} 302 | \newcommand\coadvisor[1]{\def\sjtu@value@coadvisor{#1}} 303 | \newcommand\major[1]{\def\sjtu@value@major{#1}} 304 | \newcommand\submitdate[1]{\def\sjtu@value@submitdate{#1}} 305 | \newcommand\defenddate[1]{\def\sjtu@value@defenddate{#1}} 306 | \newcommand\institute[1]{\def\sjtu@value@institute{#1}} 307 | \newcommand\chairman[1]{\def\sjtu@value@chairman{#1}} 308 | 309 | % sjtuspace 310 | \newcommand\sjtuspace{\protect\CTEX@spaceChar\protect\CTEX@spaceChar} 311 | \def\sjtu@getfileinfo#1 #2 #3\relax#4\relax{% 312 | \def\sjtufiledate{#1}% 313 | \def\sjtufileversion{#2}% 314 | \def\sjtufileinfo{#3}}% 315 | \expandafter\ifx\csname ver@sjtuthesis.cls\endcsname\relax 316 | \edef\reserved@a{\csname ver@ctextemp_sjtuthesis.cls\endcsname} 317 | \else 318 | \edef\reserved@a{\csname ver@sjtuthesis.cls\endcsname} 319 | \fi 320 | \expandafter\sjtu@getfileinfo\reserved@a\relax? ? \relax\relax 321 | \def\sjtu@underline[#1]#2{% 322 | \CTEXunderline{\hbox to #1{\hfill#2\hfill}}} 323 | \def\sjtuunderline{\@ifnextchar[\sjtu@underline\CTEXunderline} 324 | 325 | % “绘制”SJTU中文标题页 326 | \renewcommand\maketitle[1]{% 327 | \cleardoublepage 328 | \thispagestyle{empty} 329 | \begin{center} 330 | \begin{figure}[!htp] 331 | \centering 332 | \includegraphics[angle=0,origin=br,width=13cm]{figure/sjtu} 333 | \end{figure} 334 | \heiti\zihao{-2}\sjtu@label@sjtu 335 | \vskip 15pt 336 | \textbf{\kaishu\zihao{1}\sjtu@label@statement} 337 | \vskip 5pt 338 | \heiti\zihao{-2}\sjtu@label@bacheloreng 339 | \begin{figure}[!htp] 340 | \centering 341 | \includegraphics[angle=0,origin=br,width=4cm]{figure/sjtubadge} 342 | \end{figure} 343 | \vskip 20pt 344 | \begin{tabular}{ll} 345 | \huge{\kaishu\sjtu@label@title} &\kaishu 346 | \sjtuunderline[350pt]{\sjtu@value@title} 347 | \end{tabular} 348 | \vskip 5pt 349 | {\fangsong\zihao{4}} 350 | \def\tabcolsep{1pt} 351 | \def\arraystretch{1} 352 | \begin{tabular}{lc} 353 | \kaishu\sjtu@label@author &\kaishu 354 | \sjtuunderline[150pt]{\sjtu@value@author} 355 | \\ 356 | \kaishu\sjtu@label@studentnumber &\kaishu 357 | \sjtuunderline[150pt]{\sjtu@value@studentnumber} 358 | \\ 359 | \kaishu\sjtu@label@advisor &\kaishu 360 | \sjtuunderline[150pt]{\sjtu@value@advisor} 361 | \\ 362 | \kaishu\sjtu@label@major &\kaishu 363 | \sjtuunderline[150pt]{\sjtu@value@major} 364 | \\ 365 | \kaishu\sjtu@label@institute &\kaishu 366 | \sjtuunderline[150pt]{\sjtu@value@institute} 367 | \end{tabular} 368 | \end{center} 369 | \vskip \stretch{0.5} 370 | \clearpage 371 | \if@twoside 372 | \thispagestyle{empty} 373 | \ifsjtu@typeinfo 374 | \fi 375 | \cleardoublepage 376 | \fi 377 | } 378 | 379 | % English Title Page 380 | \newcommand\englishtitle[1]{\def\sjtu@value@englishtitle{#1}} 381 | \newcommand\englishauthor[1]{\def\sjtu@value@englishauthor{#1}} 382 | \newcommand\englishadvisor[1]{\def\sjtu@value@englishadvisor{#1}} 383 | \newcommand\englishcoadvisor[1]{\def\sjtu@value@englishcoadvisor{#1}} 384 | \newcommand\englishschool[1]{\def\sjtu@value@englishschool{#1}} 385 | \newcommand\englishinstitute[1]{\def\sjtu@value@englishinstitute{#1}} 386 | \newcommand\englishdate[1]{\def\sjtu@value@englishdate{#1}} 387 | \newcommand\englishdegree[1]{\def\sjtu@value@englishdegree{#1}} 388 | \newcommand\englishmajor[1]{\def\sjtu@value@englishmajor{#1}} 389 | % "绘制"英文标题页 390 | \newcommand\makeenglishtitle[1]{% 391 | \cleardoublepage 392 | \thispagestyle{empty} 393 | \begin{center} 394 | {\normalfont\zihao{4} \sjtu@label@englishstatement} 395 | \vspace{20pt} \vskip\stretch{1} 396 | {\huge\sjtu@value@englishtitle \vskip 1pt} 397 | \vskip \stretch{1} 398 | \ifsjtu@review 399 | \vskip \stretch{1} 400 | \vskip 3pt 401 | \vskip \stretch{2} 402 | \else 403 | {\normalfont\zihao{4}\sjtu@value@englishauthor} 404 | \vskip \stretch{1} 405 | {\normalfont\zihao{4}\sjtu@label@englishadvisor} 406 | \vskip 2pt 407 | {\normalfont\zihao{4}\sjtu@value@englishadvisor} 408 | \vskip 5pt 409 | \ifx\sjtu@value@englishcoadvisor\undefined\else 410 | {\normalfont\zihao{4}\sjtu@label@englishcoadvisor} 411 | \vskip 2pt 412 | {\normalfont\zihao{4}\sjtu@value@englishcoadvisor} 413 | \vskip \stretch{2} 414 | \fi 415 | \fi 416 | \normalfont\sjtu@value@englishinstitute \vskip 30pt 417 | \normalfont\sjtu@value@englishdate \vskip 20pt 418 | \end{center} 419 | \cleardoublepage 420 | } 421 | 422 | % 原创性声明 423 | \newcommand\makeDeclareOriginal{% 424 | \cleardoublepage 425 | \thispagestyle{empty} 426 | \begin{center} 427 | {\bf\zihao{3} \sjtu@value@school}\\ 428 | {\bf\zihao{3} \sjtu@label@original} 429 | \end{center} 430 | \vskip 10pt 431 | {\par\zihao{-4}\sjtu@label@originalcontent\par} 432 | \vskip 60pt 433 | \hspace{13em}\sjtu@label@authorsign\hrulefill\hspace{1.5em} 434 | \vskip 15pt 435 | \hspace{16em}\sjtu@label@originalDate\hspace{1em} 436 | \cleardoublepage 437 | } 438 | 439 | 440 | % 授权声明 441 | \newcommand\makeDeclareAuthorization{% 442 | \cleardoublepage 443 | \thispagestyle{empty} 444 | \begin{center} 445 | {\bf\zihao{3} \sjtu@value@school}\\ 446 | {\bf\zihao{3} \sjtu@label@authorization} 447 | \end{center} 448 | \vskip 10pt 449 | {\par\zihao{-4}\sjtu@label@authorizationcontent\par} 450 | \vskip 60pt 451 | \sjtu@label@authorsign\hrulefill\hspace{3em}\sjtu@label@Supervisorsign\hrulefill 452 | \vskip 15pt 453 | \sjtu@label@originalDate\hfill\hspace{3em}\sjtu@label@originalDate 454 | \cleardoublepage 455 | } 456 | 457 | % fancyhdr页眉页脚设置 458 | \ifsjtu@bachelor 459 | % 本科学位论文页眉页脚设置 460 | %% 正文页眉页脚 461 | \fancypagestyle{main}{ 462 | \fancyhf{} 463 | \fancyhead[L]{\includegraphics[width=0.22\textwidth]{figure/sjtubanner}} 464 | \fancyhead[R]{\nouppercase{\small\kaishu\sjtu@value@titlemark}} 465 | \fancyfoot[C]{\small 第~{\bfseries\thepage}~页\,共~{\bfseries\pageref{last}}~页} 466 | \renewcommand{\headheight}{32pt} 467 | } 468 | \fancypagestyle{front}{ 469 | \fancyhf{} 470 | \fancyhead[L]{\includegraphics[width=0.22\textwidth]{figure/sjtubanner}} 471 | \fancyhead[R]{\nouppercase{\small\kaishu\sjtu@value@titlemark}} 472 | \renewcommand{\headheight}{32pt} 473 | } 474 | %% 英文大摘要 475 | \fancypagestyle{biglast}{ 476 | \fancyhf{} 477 | \fancyhead[L]{\includegraphics[width=0.22\textwidth]{figure/sjtubanner}} 478 | \fancyhead[R]{\nouppercase{\small\kaishu\sjtu@value@titlemark}} 479 | \fancyfoot[C]{\small 第~{\bfseries\thepage}~页\,共~{\bfseries\pageref{biglast}}~页} 480 | \renewcommand{\headheight}{32pt} 481 | } 482 | %% 开章页页眉页脚 483 | \fancypagestyle{plain}{% 设置开章页页眉页脚风格(只有页码作为页脚) 484 | \fancyhf{} 485 | \fancyhead[L]{\nouppercase{\small\kaishu\includegraphics[width=0.22\textwidth]{figure/sjtubanner}}} 486 | \fancyhead[R]{\nouppercase{\small\kaishu\sjtu@value@titlemark}} 487 | \fancyfoot[C]{\small 第~{\bf\thepage}~页\,共~{\bf\pageref{last}}~页} 488 | \renewcommand{\headheight}{32pt} 489 | } 490 | \else 491 | % 研究生学位论文页眉页脚设置 492 | \if@twoside 493 | %% 正文页眉页脚 494 | \fancypagestyle{main}{ 495 | \fancyhead[LO, RE]{\small\kaishu\sjtu@value@school\sjtu@value@chinesedegree\sjtu@label@thesis} 496 | \fancyhead[RO]{\nouppercase{\small\kaishu\leftmark}} 497 | \fancyhead[LE]{\nouppercase{\small\kaishu\sjtu@value@titlemark}} 498 | \fancyfoot[C]{\small ---~{\bfseries\thepage}~---} 499 | \renewcommand{\headheight}{32pt} 500 | } 501 | %% 开章页页眉页脚 502 | \fancypagestyle{plain}{ 503 | \fancyhf{} 504 | \fancyhead[LO,RE]{\nouppercase{\small\kaishu\sjtu@value@school\sjtu@value@chinesedegree\sjtu@label@thesis}} 505 | \fancyhead[RO]{\nouppercase{\small\kaishu\leftmark}} 506 | \fancyhead[LE]{\nouppercase{\small\kaishu\sjtu@value@titlemark}} 507 | \fancyfoot[C]{\small ---~{\bf\thepage}~---} 508 | \renewcommand{\headheight}{32pt} 509 | } 510 | \else 511 | %% 正文页 512 | \fancypagestyle{main}{ 513 | \fancyhead[L]{\small\kaishu\sjtu@value@school\sjtu@value@chinesedegree\sjtu@label@thesis} 514 | \fancyhead[R]{\nouppercase{\small\kaishu\leftmark}} 515 | \fancyfoot[C]{\small ---~{\bf\thepage}~---} 516 | \renewcommand{\headheight}{32pt} 517 | } 518 | \fancypagestyle{plain}{ 519 | \fancyhf{} 520 | \fancyhead[L]{\nouppercase{\small\kaishu\sjtu@value@school\sjtu@value@chinesedegree\sjtu@label@thesis}} 521 | \fancyhead[R]{\nouppercase{\small\kaishu\leftmark}} 522 | % \fancyhead[L]{\small {\it\sjtu@value@titlemark}} 523 | \fancyfoot[C]{\small ---~{\bf\thepage}~---} 524 | \renewcommand{\headheight}{32pt} 525 | } 526 | \fi 527 | \fi 528 | 529 | % 中英文摘要 530 | \newenvironment{abstract}{\chapter*{\zihao{3}\sjtu@value@title\vskip 20pt\zihao{4}\sjtu@label@abstract}\markboth{\sjtu@label@abstract}{}}{} 531 | \newcommand\keywords[1]{\vspace{4ex}\noindent{\heiti\zihao{-4}\sjtu@label@keywords} #1} 532 | \newenvironment{englishabstract}{\chapter*{\zihao{3}\MakeUppercase{\sjtu@value@englishtitle}\vskip 20pt\bfseries \zihao{4}\sjtu@label@englishabstract}\markboth{\sjtu@label@englishabstract}{}}{} 533 | \newcommand\englishkeywords[1]{\vspace{2ex}\noindent{\bf\zihao{-4} \sjtu@label@englishkeywords} #1} 534 | 535 | \renewcommand\tableofcontents{% 536 | \chapter*{\contentsname} 537 | \@mkboth{\MakeUppercase\contentsname}{\MakeUppercase\contentsname}% 538 | \@starttoc{toc}% 539 | } 540 | 541 | \addtocontents{toc}{\let\string\CTEX@spaceChar\relax} 542 | 543 | \newenvironment{publications}[1] 544 | {\chapter{\sjtu@label@publications}% 545 | \@mkboth{\MakeUppercase\sjtu@label@publications} 546 | {\MakeUppercase\sjtu@label@publications}% 547 | \list{\@biblabel{\@arabic\c@enumiv}}% 548 | {\settowidth\labelwidth{\@biblabel{#1}}% 549 | \leftmargin\labelwidth 550 | \advance\leftmargin\labelsep 551 | \@openbib@code 552 | \usecounter{enumiv}% 553 | \let\p@enumiv\@empty 554 | \renewcommand\theenumiv{\@arabic\c@enumiv}}% 555 | \sloppy 556 | \clubpenalty4000 557 | \@clubpenalty \clubpenalty 558 | \widowpenalty4000% 559 | \sfcode`\.\@m} 560 | {\def\@noitemerr 561 | {\@latex@warning{Empty `publications' environment}}% 562 | \endlist} 563 | 564 | \newenvironment{patents}[1] 565 | {\chapter{\sjtu@label@patents}% 566 | \@mkboth{\MakeUppercase\sjtu@label@patents} 567 | {\MakeUppercase\sjtu@label@patents}% 568 | \list{\@biblabel{\@arabic\c@enumiv}}% 569 | {\settowidth\labelwidth{\@biblabel{#1}}% 570 | \leftmargin\labelwidth 571 | \advance\leftmargin\labelsep 572 | \@openbib@code 573 | \usecounter{enumiv}% 574 | \let\p@enumiv\@empty 575 | \renewcommand\theenumiv{\@arabic\c@enumiv}}% 576 | \sloppy 577 | \clubpenalty4000 578 | \@clubpenalty \clubpenalty 579 | \widowpenalty4000% 580 | \sfcode`\.\@m} 581 | {\def\@noitemerr 582 | {\@latex@warning{Empty `patents' environment}}% 583 | \endlist} 584 | 585 | \newenvironment{projects}[1] 586 | {\chapter{\sjtu@label@projects}% 587 | \@mkboth{\MakeUppercase\sjtu@label@projects} 588 | {\MakeUppercase\sjtu@label@projects}% 589 | \list{\@biblabel{\@arabic\c@enumiv}}% 590 | {\settowidth\labelwidth{\@biblabel{#1}}% 591 | \leftmargin\labelwidth 592 | \advance\leftmargin\labelsep 593 | \@openbib@code 594 | \usecounter{enumiv}% 595 | \let\p@enumiv\@empty 596 | \renewcommand\theenumiv{\@arabic\c@enumiv}}% 597 | \sloppy 598 | \clubpenalty4000 599 | \@clubpenalty \clubpenalty 600 | \widowpenalty4000% 601 | \sfcode`\.\@m} 602 | {\def\@noitemerr 603 | {\@latex@warning{Empty `projects' environment}}% 604 | \endlist} 605 | 606 | \newenvironment{resume} 607 | {\chapter{\sjtu@label@resume}} 608 | {} 609 | 610 | \newenvironment{resumesection}[1] 611 | {{\noindent\normalfont\bfseries #1} 612 | \list{}{\labelwidth\z@ 613 | \leftmargin 2\ccwd} 614 | \item\relax} 615 | {\endlist} 616 | 617 | \newenvironment{resumelist}[1] 618 | {{\noindent\normalfont\bfseries #1} 619 | \list{}{\labelwidth\z@ 620 | \leftmargin 4\ccwd 621 | \itemindent -2\ccwd 622 | \listparindent\itemindent} 623 | \item\relax} 624 | {\endlist} 625 | 626 | \renewenvironment{thanks} 627 | {\chapter{\sjtu@label@thanks}\label{last}} 628 | {} 629 | 630 | \newenvironment{bigabstract} 631 | { 632 | \setcounter{page}{1} 633 | \fancypagestyle{biglast}{ 634 | \fancyhf{} 635 | \fancyhead[L]{\includegraphics[width=0.22\textwidth]{figure/sjtubanner}} 636 | \fancyhead[R]{\nouppercase{\small\kaishu\sjtu@value@titlemark}} 637 | \fancyfoot[C]{\small 第~{\bfseries\thepage}~页\,共~{\bfseries\pageref{biglast}}~页} 638 | \renewcommand{\headheight}{32pt} 639 | } 640 | 641 | \fancypagestyle{plain}{% 设置开章页页眉页脚风格(只有页码作为页脚) 642 | \fancyhf{} 643 | \fancyhead[L]{\includegraphics[width=0.22\textwidth]{figure/sjtubanner}} 644 | \fancyhead[R]{\nouppercase{\small\kaishu\sjtu@value@titlemark}} 645 | \fancyfoot[C]{\small 第~{\bf\thepage}~页\,共~{\bf\pageref{biglast}}~页} 646 | \renewcommand{\headheight}{32pt} 647 | } 648 | 649 | \chapter*{\bf\MakeUppercase{\sjtu@value@englishtitle}\vskip 20pt } 650 | } 651 | {\label{biglast}} 652 | 653 | \newenvironment{summary} 654 | {\chapter*{\sjtu@label@summary\markboth{\sjtu@label@summary}{}}\addcontentsline{toc}{chapter}{\sjtu@label@summary} 655 | }{} 656 | 657 | \newenvironment{symbolnote}{\chapter{\sjtu@label@symbolnote}}{} 658 | 659 | \endinput 660 | 661 | %% 662 | %% End of file `sjtuthesis.cls'. 663 | 664 | -------------------------------------------------------------------------------- /statement.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gaocegege/bachelor-paper-2016/29030d0abb9a84f698551c842ea1198d8d0b1b55/statement.pdf -------------------------------------------------------------------------------- /tex/abstract.tex: -------------------------------------------------------------------------------- 1 | %# -*- coding: utf-8-unix -*- 2 | %%================================================== 3 | %% abstract.tex for SJTU Master Thesis 4 | %%================================================== 5 | 6 | \begin{abstract} 7 | \thispagestyle{front} 8 | 9 | 最近几年来,以Docker为代表的容器虚拟化技术越来越被业界所接受,成为部署应用时的另一种选择。而容器集群技术使得开发者无需关注底层架构与环境的情况下,快速部署自己的应用,快速响应需求。 10 | 11 | 容器和容器集群使得应用的部署变得简单,而本文希望能够在基于容器集群的架构上,实现从代码提交,到持续集成,再到最后的持续部署发布的全流程的自动化系统Fornax,进一步简化运维工作。Fornax在构建阶段使用了容器虚拟化技术来进行构建的隔离,并且在每次构建后产出一个版本镜像,实现了代码与运行环境两者的共同管理。而持续集成与持续部署,是建立在Kubernetes容器集群上的。 12 | 13 | 在本文的最后部分,对Fornax的功能性测试以及分布式的部署进行了探索,保证了Fornax的功能的合约以及在生产环境下的可用性。目前Fornax已经在线上运行,为用户提供服务,这也从另一方面证明了Fornax的可用性。 14 | 15 | \keywords{\large 容器虚拟化 \quad 版本管理 \quad 持续集成} 16 | \end{abstract} 17 | 18 | \begin{englishabstract} 19 | \thispagestyle{front} 20 | 21 | In recent years, operating-system-level virtualization is increasingly being accepted by the industry, and has become another option when deploying applications. The clustering system helps programmers to respond to customer demand quickly and efficiently. 22 | 23 | Operating-system-level virtualization makes applications easier to deploy, and this paper want to implement a automation system for continuous integration, continuous deployment and version release management. Fornax uses operating-system-level virtualization to isolate the building tasks. And When the building task is done, Fornax would push a image to registry, makes both the code and runtime under control. And continuous integration and continuous deployment are based on Kubernetes. 24 | 25 | In the end, Fornax introduces the end-to-end test and distributed architecture, to illustrate the functionality and usability. Now Fornax is running in production, on the other hand it shows the availability of Fornax. 26 | 27 | \englishkeywords{\large Containerization, Version Control, Continuous Integration} 28 | \end{englishabstract} 29 | -------------------------------------------------------------------------------- /tex/ack.tex: -------------------------------------------------------------------------------- 1 | %# -*- coding: utf-8-unix -*- 2 | \begin{thanks} 3 | 4 | 在本科学位论文的写作过程中,受到了很多老师、同学以及其他的朋友们的帮助。 5 | 6 | 首先,最需要感谢的是我的导师任锐老师。从项目的立项,到后来的实现,再到最后的论文写作,任老师都给予了很多中肯的意见,使得我在实现系统,撰写论文时绕过了很多弯路。同时任老师对待工作与学术的认真也给我留下了极深的印象。 7 | 8 | 其次,还需要感谢才云科技的邓德源、高建桥和陈曦先生。才云科技是一家容器集群即服务的创业公司,在Fornax的实现过程中提供了很多帮助。在实现过程中经常与邓德源先生进行深入的讨论与交流,受其指导颇多,收获也很大。 9 | 10 | 与此同时,还要感谢实验室里同一级的同学们,包括张坚鑫同学、孙浩然同学以及李恫宇同学。我们为了毕业设计一起努力,之后的三年时间里希望能够与三位同学继续保持这样的态度读过在交大的研究生生活。 11 | 12 | 最后,要感谢我的父母,他们给了我很大的自由空间,让我可以按照自己的心意读过大学四年的生活。他们也是我最坚强的后盾,愿他们健康。 13 | 14 | 除此之外还有很多值得感谢的人,在这里不一一列举了,希望能够在以后能再次与各位合作交流,也谢谢大家一直以来的帮助,使我能够顺利完成学位论文的写作。 15 | 16 | \end{thanks} 17 | -------------------------------------------------------------------------------- /tex/app_cjk.tex: -------------------------------------------------------------------------------- 1 | %# -*- coding: utf-8-unix -*- 2 | \chapter{从 \CJKLaTeX 转向 \XeTeX } 3 | \label{chap:whydvipdfm} 4 | 5 | 我习惯把v0.2a使用dvipdfmx编译的硕士学位论文模板称为“ \CJKLaTeX 模板”,而这个使用 \XeTeX 引擎(xelatex程序)处理的模板则被称为“{\XeTeX/\LaTeX}模板”。 6 | 从 \CJKLaTeX 模板迁移到{\XeTeX\LaTeX}模板的好处有下: 7 | \begin{enumerate} 8 | \item[\large\smiley] 搭建 \XeTeX 环境比搭建 \CJKLaTeX 环境更容易; 9 | \item[\large\smiley] 更简单的字体控制; 10 | \item[\large\smiley] 完美支持PDF/EPS/PNG/JPG图片,不需要“bound box(.bb)”文件; 11 | \item[\large\smiley] 支持OpenType字体的复杂字型变化功能; 12 | \end{enumerate} 13 | 14 | 当然,这也是有代价的。由于 \XeTeX 比较新,在我看来,使用 \XeTeX 模板所必须付出的代价是: 15 | 16 | \begin{enumerate} 17 | \item[\large\frownie] 必须把你“古老的” \TeX 系统更新为较新的版本。TeXLive 2012和CTeX 2.9.2能够编译这份模板,而更早的版本则无能为力。 18 | \item[\large\frownie] 需要花一些时间把你在老模板上的工作迁移到新模板上。 19 | \end{enumerate} 20 | 21 | 第一条就看你如何取舍了,新系统通常意味着更好的兼容性,值得升级。而转换模板也不是什么特别困难的事情,可以这样完成: 22 | 23 | \begin{enumerate} 24 | \item 备份你要转换的源文件,以防你的工作成果丢失; 25 | \item 将你原来的tex以及bib文件另存为UTF-8编码的文件。iconv、vim、emacs、UEdit等等工具都可以完成。WinEdt对文件编码识别功能很差(到了v6.0还是如此),不推荐作为字符编码转换工具; 26 | \item 将diss.tex导言区中的内容替换为XeTeX模板diss.tex导言区的内容; 27 | \item 将你对原先导言区的修改,小心翼翼地合并到新的导言区中; 28 | \item 使用XeTeX模板中的GBT7714-2005NLang.bst替换原有的bst文件,新的bst文件只是将字符编码转换为UTF-8; 29 | \item 删除bouding box文件; 30 | \item 使用本文\ref{sec:process}介绍的方法,重新编译文档; 31 | \end{enumerate} 32 | 33 | -------------------------------------------------------------------------------- /tex/app_eq.tex: -------------------------------------------------------------------------------- 1 | %# -*- coding: utf-8-unix -*- 2 | %% app2.tex for SJTU Master Thesis 3 | %% based on CASthesis 4 | %% modified by wei.jianwen@gmail.com 5 | %% version: 0.3a 6 | %% Encoding: UTF-8 7 | %% last update: Dec 5th, 2010 8 | %%================================================== 9 | 10 | \chapter{Maxwell Equations} 11 | 12 | 选择二维情况,有如下的偏振矢量: 13 | \begin{subequations} 14 | \begin{eqnarray} 15 | {\bf E}&=&E_z(r,\theta)\hat{\bf z} \\ 16 | {\bf H}&=&H_r(r,\theta))\hat{ \bf r}+H_\theta(r,\theta)\hat{\bm 17 | \theta} 18 | \end{eqnarray} 19 | \end{subequations} 20 | 对上式求旋度: 21 | \begin{subequations} 22 | \begin{eqnarray} 23 | \nabla\times{\bf E}&=&\frac{1}{r}\frac{\partial E_z}{\partial\theta}{\hat{\bf r}}-\frac{\partial E_z}{\partial r}{\hat{\bm\theta}}\\ 24 | \nabla\times{\bf H}&=&\left[\frac{1}{r}\frac{\partial}{\partial 25 | r}(rH_\theta)-\frac{1}{r}\frac{\partial 26 | H_r}{\partial\theta}\right]{\hat{\bf z}} 27 | \end{eqnarray} 28 | \end{subequations} 29 | 因为在柱坐标系下,$\overline{\overline\mu}$是对角的,所以Maxwell方程组中电场$\bf E$的旋度: 30 | \begin{subequations} 31 | \begin{eqnarray} 32 | &&\nabla\times{\bf E}=\mathbf{i}\omega{\bf B} \\ 33 | &&\frac{1}{r}\frac{\partial E_z}{\partial\theta}{\hat{\bf 34 | r}}-\frac{\partial E_z}{\partial 35 | r}{\hat{\bm\theta}}=\mathbf{i}\omega\mu_rH_r{\hat{\bf r}}+\mathbf{i}\omega\mu_\theta 36 | H_\theta{\hat{\bm\theta}} 37 | \end{eqnarray} 38 | \end{subequations} 39 | 所以$\bf H$的各个分量可以写为: 40 | \begin{subequations} 41 | \begin{eqnarray} 42 | H_r=\frac{1}{\mathbf{i}\omega\mu_r}\frac{1}{r}\frac{\partial 43 | E_z}{\partial\theta } \\ 44 | H_\theta=-\frac{1}{\mathbf{i}\omega\mu_\theta}\frac{\partial E_z}{\partial r} 45 | \end{eqnarray} 46 | \end{subequations} 47 | 同样地,在柱坐标系下,$\overline{\overline\epsilon}$是对角的,所以Maxwell方程组中磁场$\bf H$的旋度: 48 | \begin{subequations} 49 | \begin{eqnarray} 50 | &&\nabla\times{\bf H}=-\mathbf{i}\omega{\bf D}\\ 51 | &&\left[\frac{1}{r}\frac{\partial}{\partial 52 | r}(rH_\theta)-\frac{1}{r}\frac{\partial 53 | H_r}{\partial\theta}\right]{\hat{\bf 54 | z}}=-\mathbf{i}\omega{\overline{\overline\epsilon}}{\bf 55 | E}=-\mathbf{i}\omega\epsilon_zE_z{\hat{\bf z}} \\ 56 | &&\frac{1}{r}\frac{\partial}{\partial 57 | r}(rH_\theta)-\frac{1}{r}\frac{\partial 58 | H_r}{\partial\theta}=-\mathbf{i}\omega\epsilon_zE_z 59 | \end{eqnarray} 60 | \end{subequations} 61 | 由此我们可以得到关于$E_z$的波函数方程: 62 | \begin{eqnarray} 63 | \frac{1}{\mu_\theta\epsilon_z}\frac{1}{r}\frac{\partial}{\partial r} 64 | \left(r\frac{\partial E_z}{\partial r}\right)+ 65 | \frac{1}{\mu_r\epsilon_z}\frac{1}{r^2}\frac{\partial^2E_z}{\partial\theta^2} 66 | +\omega^2 E_z=0 67 | \end{eqnarray} 68 | -------------------------------------------------------------------------------- /tex/app_log.tex: -------------------------------------------------------------------------------- 1 | %# -*- coding: utf-8-unix -*- 2 | \chapter{模板更新记录} 3 | \label{chap:updatelog} 4 | 5 | \textbf{2015年2月15日} v0.7发布,增加盲审选项,调用外部工具插入扫描件。 6 | 7 | \textbf{2015年2月14日} v0.6.5发布,修正一些小问题,缩减git仓库体积,仓库由sjtu-thesis-template-latex更名为SJTUThesis。 8 | 9 | \textbf{2014年12月17日} v0.6发布,学士、硕士、博士学位论文模板合并在了一起。 10 | 11 | \textbf{2013年5月26日} v0.5.3发布,更正subsubsection格式错误,这个错误导致如"1.1 小结"这样的标题没有被正确加粗。 12 | 13 | \textbf{2012年12月27日} v0.5.2发布,更正拼写错误。在diss.tex加入ack.tex。 14 | 15 | \textbf{2012年12月21日} v0.5.1发布,在 \LaTeX 命令和中文字符之间留了空格,在Makefile中增加release功能。 16 | 17 | \textbf{2012年12月5日} v0.5发布,修改说明文件的措辞,更正Makefile文件,使用metalog宏包替换xltxtra宏包,使用mathtools宏包替换amsmath宏包,移除了所有CJKtilde(\verb+~+)符号。 18 | 19 | \textbf{2012年5月30日} v0.4发布,包含交大学士、硕士、博士学位论文模板。模板在\href{https://github.com/weijianwen/sjtu-thesis-template-latex}{github}上管理和更新。 20 | 21 | \textbf{2010年12月5日} v0.3a发布,移植到 \XeTeX/\LaTeX 上。 22 | 23 | \textbf{2009年12月25日} v0.2a发布,模板由CASthesis改名为sjtumaster。在diss.tex中可以方便地改变正文字号、切换但双面打印。增加了不编号的一章“全文总结”。 24 | 添加了可伸缩符号(等号、箭头)的例子,增加了长标题换行的例子。 25 | 26 | \textbf{2009年11月20日} v0.1c发布,增加了Linux下使用ctex宏包的注意事项、.bib条目的规范要求, 27 | 修正了ctexbook与listings共同使用时的断页错误。 28 | 29 | \textbf{2009年11月13日} v0.1b发布,完善了模板使用说明,增加了定理环境、并列子图、三线表格的例子。 30 | 31 | \textbf{2009年11月12日} 上海交通大学硕士学位论文 \LaTeX 模板发布,版本0.1a。 32 | 33 | -------------------------------------------------------------------------------- /tex/app_setup.tex: -------------------------------------------------------------------------------- 1 | %# -*- coding: utf-8-unix -*- 2 | \chapter{搭建模板编译环境} 3 | 4 | \section{安装TeX发行版} 5 | 6 | \subsection{Mac OS X} 7 | 8 | Mac用户可以从MacTeX主页\footnote{\url{https://tug.org/mactex/}}下载MacTeX 2015。 9 | 也可以通过brew包管理器\footnote{\url{http://caskroom.io}}安装MacTeX 2015。 10 | 11 | \begin{lstlisting}[basicstyle=\small\ttfamily, numbers=none] 12 | brew cask install mactex 13 | \end{lstlisting} 14 | 15 | \subsection{Linux} 16 | 17 | 建议Linux用户使用TeXLive主页\footnote{\url{https://www.tug.org/texlive/}}的脚本来安装TeXLive 2015。 18 | 以下命令将把TeXLive发行版安装到当前用户的家目录下。 19 | 若计划安装一个供系统上所有用户使用的TeXLive,请使用root账户操作。 20 | 21 | \begin{lstlisting}[basicstyle=\small\ttfamily, numbers=none] 22 | wget http://mirror.ctan.org/systems/texlive/tlnet/install-tl-unx.tar.gz 23 | tar xzvpf install-tl-unx.tar.gz 24 | cd install-tl-20150411/ 25 | ./install-tl 26 | \end{lstlisting} 27 | 28 | \section{安装中文字体} 29 | 30 | \subsection{Mac OS X、Deepin} 31 | 32 | Mac和Deepin用户双击字体文件即可安装字体。 33 | 34 | \subsection{RedHat/CentOS用户} 35 | 36 | RedHat/CentOS用户请先将字体文件复制到字体目录下,调用fc-cache刷新缓存后即可在TeXLive中使用新字体。 37 | 38 | \begin{lstlisting}[basicstyle=\small\ttfamily, numbers=none] 39 | mkdir ~/.fonts 40 | cp *.ttf ~/.fonts # 当前用户可用新字体 41 | cp *.ttf /usr/share/fonts/local/ # 所有用户可以使用新字体 42 | fc-cache -f 43 | \end{lstlisting} 44 | 45 | -------------------------------------------------------------------------------- /tex/big-english-abstract.txt: -------------------------------------------------------------------------------- 1 | Operating-system-level virtualization has been the hottest topic in Computer System and Cloud Computing. Docker is the most popular implementation of operating-system-level virtualization, it allows the programmers to build, ship and run their applications easily. Docker is hosted on Github, with 31256 stars by Mar 16th, 2016. Since Docker is now generally acceptable, there are many services and tools based on it. Kubernetes is a open-source system for automating deployment, operations, and scaling of containerized applications. The ecosystem of Docker is growing up rapidly. 2 | 3 | Fornax is a release management system, which is built on Docker. Fornax aims to provide the continuous integration, continuous deployment and version control of microservices. 4 | 5 | Continuous integration is a main feature in Fornax. Every time the programmers push their local changes to the remote repository, which is taken over by a specific version control system, such as Git or SVN, Fornax would create a continous integration task and run the customized commands. And Fornax is designed to integrate with popular CI tool like jenkins, to facilitate existing infrastructure. 6 | 7 | Continuous deployment is an important software engineering approach to agile software development. Fornax integrates with Kubernetes, to deploy microservices. When the integration test passed, Fornax would build a conatiner image from the commit, push it to registry, and deploy it to the container cluster. And Fornax allows to declare which cluster and which partition to deploy, and support to deploy on multiple cloud architectures such as public cloud, private cloud or hybrid cloud. The deployment cloud be flexible. 8 | 9 | Those two features make the Fornax a available continuous integration or continuous deployment tool, and the support for version control of microservices makes Fornax meet the demand of the modern software process. Repository in the traditional version control system is equivalent to a service in Fornax. Fornax would take over the version control of the programmers' application. So Fornax integrates with version control systems and Docker image service to make both code and runtime of the applications traceable and able to roll back. 10 | 11 | There are two concept in Fornax, service and version. Service is equivalent to a repository in the version control system. And version contains the code by a commit and a Docker image built from the code. A service would have more than one version, and the version could deploy to Kubernetes cluster. Fornax has a reasonable workflow, First The programmers should input the necessary information, including the URL of repository, the type of verson control system and the token for authorization if needed. Fornax would create a service for the repository, and check whether the information is correct. When the service is created successfully, Fornax would take over the version control of the service. When a commit is pushed to remote repository, Fornax would start a continuous integration task. If the task passes, Fornax would build a Docker image from the code, push it to the customized Docker Registry and store the information of the version. If the programmers have defined the settings about continuous deployment, Fornax would deploy the new version to user-defined cluster. From the perspective of programmers, they just need to push their commit to remote, and Fornax will take over the continuous intergation, version control and continuous deployment. 12 | 13 | Fornax has eight components: API module, async event manager, Docker manager, version control system manager(VCS manager), continuous integration manager(CI manager), Docker Daemon manager, log module, and datebase collection manager. 14 | 15 | API module wraps the Fornax as REST API. Fornax run as a HTTP server, listening a specific port. All the requests would reach the API module first and API module would filter the requests, ensure the requests are valid, then would handle the requests. It's a lot of time to create services or versions, so it is asynchronous. When API module receives the requests to create services or versions, it would send a event to async event manager. 16 | 17 | Async event manager schedules the event queue, it receives the events sent from API module, and handle these events asynchronously. There are two kinds of events: create services and create versions. Async event manager uses channels, the feature in golang, to perform a event loop. And it will integrates with Docker manager, CI manager and VCS manager to deal with the two kinds of events. 18 | 19 | Docker manager is a wrapper around Docker Client. Fornax would build and push the image to Docker Registry by Docker manager. And To push the image isolatedly, Fornax implements Docker Daemon manager to manages multiple Docker manager. When async event manager should call Docker manager to push the image, it would acquire a idle Docker manager from Docker Daemon manger, then push the image to Docker Registry. 20 | 21 | VCS manager is a wrapper around the version control systems, Continuous integration requires some VCS operations, so Fornax need to import the VCS bundle. Now VCS manager supports Git and SVN, and in the future, other version control systems would be adapted. 22 | 23 | CI manager is the most important module in Fornax. CI manager take over the life cycle of a version, from continuous integration and deployment. First, CI manager would check whether the file named caicloud.yml exists. The file is the config during creating version process. It defines the operations that should be executed when the version is created. If the file doesn't exists, the CI manager wouldn't work, and Fornax just builds and pushes docker image to Docker Registry. Then CI manager parses the config file, and run continuous integration, before-build-hook, build, push, post-build-hook and deploy one by one. 24 | 25 | At the continuous integration step, CI manager would run the dependencies and the service as containers, these containers would communicate with each other via DNS name resolution. CI manager promises that the containers in one request would discover each other, but containers in different requests could do that. 26 | 27 | At the before-build-hook and post-build-hook step, CI manager would run a single container, and execute the customized commands. Fornax supports the hooks to improve usability. 28 | 29 | Build and push are two default steps in Fornax. A version could have some optional steps to run, such as continuous integration or before-build-hook, and two default steps, build and push. In these two steps, Fornax would build the docker image, and push it to Docker Registry. 30 | 31 | CI manager is a monolithic module, and in the future, CI manager would be refactored. 32 | 33 | log module is another module, which is focuing on logs during the version creating process. At first, Fornax stores logs locally. With the increase of throughput, Fornax shuold be deployed as a distributed application. So log module imports Kafka, an open source messaging system, to store logs in the distributed architecture. And log module communicates with the clients by WebSocket, WebSocket allows Fornax to push real-time logs to client. 34 | 35 | Datebase collection manager wraps the connection to MongoDB, Fornax would store the services and versions into MongoDB by database collection manager. It's a global module exposed to all other modules. 36 | 37 | To avoid serious bugs, Fornax has many sound test cases. There are 11 test cases about services and 24 test cases about versions. The test cases are end-to-end, and covers the main workflow of Fornax and some alternative flow. These test cases help us keep the code in high quality. 38 | 39 | And with the growth of throughput, Fornax imports HAProxy, an open source load balancer to distribute. Fornax is designed to stateless, so the requests could route to an arbitrary Fornax instance. Distributed architecture improves the availability, makes Fornax production-ready. 40 | 41 | Although Fornax is production-ready, it also has a lot of problems to solve, especially in CI manager and log module. In some situation, CI manager could recycle the containers and the network, which would cause the resource leak. And log module now is not stable enough, in the future, Fornax would fix these problems to make it much more robust. -------------------------------------------------------------------------------- /tex/config.tex: -------------------------------------------------------------------------------- 1 | \chapter{Fornax配置文件格式} 2 | 3 | 以下为Fornax配置文件格式。配置文件是YAML格式的文本文件,一般存在于用户的远端仓库中,在Fornax进行构建版本时会根据其中内容进行自定义的操作。 4 | 5 | \begin{lstlisting}[caption={配置文件格式}] 6 | integration: 7 | image: 8 | environment: 9 | - = 10 | - = 11 | commands: 12 | - 13 | - 14 | services: 15 | : 16 | image: 17 | environment: 18 | - = 19 | - = 20 | commands: 21 | - 22 | - 23 | ... 24 | pre_build: 25 | dockerfile_path: 26 | image: 27 | environment: 28 | - = 29 | - = 30 | commands: 31 | - 32 | - 33 | outputs: 34 | - 35 | - 36 | build: 37 | dockerfile_path: 38 | post_build: 39 | image: 40 | environment: 41 | - = 42 | - = 43 | commands: 44 | - 45 | - 46 | deploy: 47 | - : 48 | cluster: 49 | partition: 50 | \end{lstlisting} -------------------------------------------------------------------------------- /tex/detail.tex: -------------------------------------------------------------------------------- 1 | \chapter{Fornax实现细节分析} 2 | \label{chap:detail} 3 | 4 | 本章从细节实现的角度出发,自顶而下地介绍了Fornax每个模块的具体实现。在第\ref{chap:impl}章中提到,API模块是Fornax与客户端交互的入口。因此对实现的具体细节分析,将从最顶层的API模块入手。 5 | 6 | \section{Fornax初始化} 7 | 8 | Fornax在实现上依赖很多外部的服务,其中包括MongoDB,Kafka,和Docker等。因此,如果要运行Fornax,必须有这些依赖的支持。为了实现依赖的可配置,Fornax采取了环境变量的方式定义这些依赖。表\ref{tab:env}列出了Fornax中所有的环境变量。其中前两项为MongoDB和Kafka服务所在的地址,通常是以IP或者域名的形式给出,而端口则是在两个服务启动时所在的默认端口。而DOCKER\_HOST和DOCKER\_HOST\_DIR是为了支持多个Docker Host做构建而定义的环境变量。而以REGISTRY为前缀的三个环境变量是与Docker Registry相关的配置,它们定义了地址与用户名密码,它们的作用会在之后进行更为详细的阐述。上面提到的环境变量是Fornax中为了解决依赖可配置而引入的,而其他的环境变量则是出于便于开发的目的,在此不做过多介绍。 9 | 10 | 在读取环境变量后,Fornax会将API模块中的所有API注册到一个HTTP服务器上,然后在主线程里运行该服务器,监听相应端口(默认为7099)。同时,Fornax会将额外启动一个线程来运行异步事件处理器的事件循环,事件循环可以被视为一个不会停止的循环,它接受一个通道(channel)的消息,并进行处理。还有一个WebSocket的服务器,同样会运行在一个独立的线程中,该线程主要负责将日志实时地推送给接收方。因此,在初始化后,Fornax会有三个线程在运行。 11 | 12 | \begin{table}[!hpb] 13 | \centering 14 | \caption{Fornax环境变量配置} 15 | \label{tab:env} 16 | \begin{tabular}{ll} \toprule 17 | 环境变量 & 描述 \\ \midrule 18 | MONGO\_DB\_IP & MongoDB服务地址 \\ 19 | KAFKA\_SERVER\_IP & Kafka服务地址 \\ 20 | DOCKER\_HOST & Docker Host地址 \\ 21 | DOCKER\_HOST\_DIR & Docker Host目录 \\ 22 | REGISTRY\_LOCATION & Docker Registry地址 \\ 23 | REGISTRY\_USERNAME & Docker Registry用户名 \\ 24 | REGISTRY\_PASSWORD & Docker Registry密码 \\ 25 | DOCKER\_CERT\_PATH & Docker认证目录 \\ 26 | ENABLE\_CAICLOUD\_AUTH & 是否开启用户认证 \\ \bottomrule 27 | \end{tabular} 28 | \end{table} 29 | 30 | \section{API模块实现} 31 | 32 | % 有error? 33 | \begin{table}[!hpb] 34 | \centering 35 | \caption{Fornax REST API} 36 | \label{tab:api} 37 | \begin{tabular}{lll} \toprule 38 | URL & 方法 & 描述 \\ \midrule 39 | /\{user\_id\}/services & POST & 创建新的服务 \\ 40 | /\{user\_id\}/services & GET & 获得所有服务 \\ 41 | /\{user\_id\}/services/\{service\_id\} & GET & 根据ServiceID查询服务 \\ 42 | /\{user\_id\}/services/\{service\_id\} & DELETE & 根据ServiceID删除服务 \\ 43 | /\{user\_id\}/services/\{code\_repository\}/requesttoken & GET & 根据用户请求私有仓库的Token \\ 44 | /services/\{code\_repository\}/authcallback & GET & 授权的回调处理 \\ 45 | /\{user\_id\}/services/\{code\_repository\}/listrepo & GET & 使用请求的Token列出所有仓库 \\ 46 | /\{user\_id\}/services/\{code\_repository\}/logout & GET & 从Fornax中登出该Token \\ 47 | /\{user\_id\}/versions & POST & 创建新的版本 \\ 48 | /\{user\_id\}/versions/\{version\_id\} & GET & 根据ServiceID查询版本 \\ 49 | /\{user\_id\}/versions/\{version\_id\}/logs & GET & 获得日志(默认无WebSocket支持)\\ 50 | /\{user\_id\}/services/\{service\_id\}/versions & GET & 列出一个服务对应的所有版本 \\ 51 | /apidocs & GET & API文档(默认不生成) \\ \bottomrule 52 | \end{tabular} 53 | \end{table} 54 | 55 | Fornax中的服务,是以REST API的形式暴露给外界的,而API模块就是对于REST API的封装。在之前的章节中提到,服务和版本是Fornax中两个最重要的实体概念。因此在REST API中这两个模型也是最主要的数据实体。Fornax所有的API在表\ref{tab:api}中列出。 56 | 57 | % \begin{figure}[!htp] 58 | % \centering 59 | % \includegraphics[width=0.9\textwidth]{detail/apidoc.png} 60 | % \bicaption[fig:api]{Fornax API文档图}{Fornax API文档图}{Fig}{} 61 | % \end{figure} 62 | 63 | 通过定义了REST API,并将其与相应的逻辑处理器关联起来,最终以HTTP服务器的方式运行起来,以实现对外服务的功能。值得一提的是,Fornax在API模块中也实现了一项对开发者而言比较友好功能,即根据代码来直接生成REST API文档,而不再像是传统的方式那样,手动地维护一份API文档以供参考。在代码中定义REST API的部分,通过加入少量的说明,Fornax可以在运行时通过Flag的方式来决定是否将在运行的同时在/apidocs下生成一份API文档。首先,根据Fornax中原本的代码,会首先生成一个JSON格式的API规约,然后利用著名的API工具Swagger,产生一份人类可阅读的,HTML格式的文档。在API文档中不仅包括API的请求参数,以及返回的参数,还可以浏览到在代码中对应的相应的模型的定义,同时也可以直接通过文档发送请求,测试API的可用性。API模块的这一功能,使得外部与Fornax交互时可以感知到最新的接口,不会出现因为长时间没有维护API文档而导致的一系列问题。 64 | 65 | \section{异步事件管理模块} 66 | 67 | 异步事件管理模块,是处理服务与版本创建的模块。在Fornax最初的设计中,所有的逻辑处理都是在主线程中完成,后来随着服务与版本在创建时的复杂性的提高,这样的设计不能满足需求,因此引入了异步事件管理模块,将创建服务与版本的过程异步化,使得它们不会阻塞主进程。 68 | 69 | 异步事件管理模块的运行模型是传统的事件循环模型,异步事件管理模块的运行过程可以抽象为一个永远不会退出的循环,当收到来自API模块发送到来的消息时,会调用相关的处理器来处理该事件,并且会在处理结束后执行定义的钩子函数,来进行数据库操作,或者收尾工作等等。采取事件循环的模型,使得Fornax在请求量巨大时,不会因为同时处理多个构建任务而崩溃。而这样的模型使得Fornax支持通过拒绝一部分请求,或者限制最大请求队列长度等方式来解决请求过载的问题。 70 | 71 | % \begin{lstlisting}[caption={抽象后的异步事件管理器结构与实现}] 72 | % type AsyncManager struct { 73 | % operations map[Operation]OperationHandler 74 | % events map[EventID]*Event 75 | % newEvents chan *Event 76 | % deleteEvents chan *Event 77 | % lock sync.Mutex 78 | % } 79 | 80 | % func (am *AsyncManager) Start() { 81 | % go func() { 82 | % for { 83 | % select { 84 | % case event := <-am.newEvents: 85 | % go func() { 86 | % operationHandler, ok := am.operations[event.Operation] 87 | % err := operationHandler(event) 88 | % event.Lock.Lock() 89 | % defer event.Lock.Unlock() 90 | % // Deal with the error and call the post hook function. 91 | % }() 92 | % case event := <-am.deleteEvents: 93 | % delete(am.events, event.EventID) 94 | % } 95 | % } 96 | % }() 97 | % } 98 | % \end{lstlisting} 99 | 100 | \begin{algorithm} 101 | \caption{异步事件管理模块事件循环} 102 | \label{algo:eventloop} 103 | \begin{algorithmic} 104 | \LOOP 105 | \IF {there is a new event sent to the async event manager} 106 | \STATE Create a new goroutine and call the handler function for the event. 107 | \ELSIF {There is a command to delete a event} 108 | \STATE Delete the event from the manager. 109 | \ENDIF 110 | \ENDLOOP 111 | \end{algorithmic} 112 | \end{algorithm} 113 | 114 | 在其他语言中实现这样事件驱动的模型,是比较复杂的。而在go语言中,因为其对于通道(channel)和轻量级线程(goroutine)的支持,所以实现这样一个模型非常简单,这也是Fornax最终采取这样的模型进行异步化创建服务和版本任务的原因之一。异步事件管理器的数据结构如代码所示,其由一个以操作为键,以处理器函数为值的图、一个以事件的唯一标识符为键,以对应的事件的指针为值的图、以及两个通道和一个互斥锁构成。在执行Start函数时,首先会创建一个新的线程,并在该线程中进入一个无限循环,在循环中,会使用go语言中的select特性,来进行对事件的监听。如果接收到新的事件,就会去operations中寻找对应的处理器函数,并调用其进行处理。目前只有两种有意义的操作类型,即创建服务和创建版本,而因为两者之间不存在数据竞争,因此在进行处理时不需要加锁,只有在涉及到对事件本身的属性的修改时才需要加锁。 115 | 116 | 异步事件管理模块与Docker管理模块、持续集成管理模块、和版本控制系统管理模块在处理器函数中进行交互。在创建服务的过程中,Fornax会将用户指定的仓库Clone到本地,进行简单地校验,然后在结束时会将服务的元数据写入数据库。因此在创建服务的处理器函数中,会与版本控制系统管理模块进行交互。而在创建版本时,则会与三个模块都有交互。 117 | 118 | \section{Docker管理模块} 119 | 120 | Docker管理模块是在执行镜像的构建与打包时会被调用的模块。Docker管理模块会负责与Docker Host交互,当有创建版本的请求被发起时,会涉及到对于版本镜像的构建和发布。因此,Docker管理模块需要维护在构建与发布镜像时的所有信息。而且在构建镜像时,也需要对Docker Registry进行设定,保证用户可以从其可见的基础镜像中构建新的镜像。 121 | 122 | % \begin{lstlisting}[caption={Docker管理模块结构}] 123 | % type DockerManager struct { 124 | % client *docker_client.Client 125 | % registry string 126 | % authConfig *AuthConfig 127 | % endPoint string 128 | % } 129 | % \end{lstlisting} 130 | 131 | Docker管理模块的结构相对于其他模块而言比较简单,其中最主要的对象是Docker Client的抽象对象,该对象会负责与Docker Host进行交互,而诸如构建、发布等功能也是通过该对象进行的。而其他的对象,是在执行构建与发布时需要用到的参数。在构建与发布时,用户通常会将镜像推送到自建的Docker Registry上,这样的需求要求在进行构建与发布时,允许用户来指定一些用来认证的配置,以保证推送的成功。 132 | 133 | \section{版本管理系统管理模块} 134 | 135 | 版本管理系统管理模块是唯一一个在创建服务与创建版本时都会使用的模块。不同于其他类型的模块,它们只有一种实现,版本管理系统管理模块因为需要适配多种版本管理系统,因此有着更高的抽象。 136 | 137 | \begin{figure}[!htp] 138 | \centering 139 | \includegraphics[width=0.7\textwidth]{detail/vcs.png} 140 | \caption{Fornax版本管理系统管理模块UML类图} 141 | \label{fig:vcs} 142 | \end{figure} 143 | 144 | 由图\ref{fig:vcs}所示,版本管理系统管理模块向外暴露两个接口,分别对应着Clone操作和给一个指定的分支打上标签的操作。这两个操作会在异步事件管理模块处理相应事件时被调用。而为了满足适配多种版本管理系统的要求,版本管理系统管理模块将所有对于版本管理系统的操作抽象成了一个接口,由接口定义了一系列标准地,Fornax需要调用版本管理系统来支持的功能。而不同的版本管理系统需要分别实现对应的功能,以满足接口的要求。而对于版本管理系统的封装与版本管理系统管理模块是解耦合的,当需要使用其进行相应操作时,版本管理系统管理模块会根据用户的设定,先创建出操作对应的版本管理系统的对象,然后根据该对象进行操作。目前所有版本管理系统的实现是通过在go语言中调用Shell程序,来使用本地的版本管理系统的命令行工具来进行支持的。所以版本管理系统的封装本身是无状态的,因此重复创建并不会带来太大的开销。 145 | 146 | 一方面,go语言作为一门新兴的语言,目前没有能满足Fornax需求的对版本管理系统进行操作的第三方库支持,另一方面,调用Shell的方法可以满足现在的需求。所以Fornax采取了这样的方式来解决对于版本管理系统的依赖,在之后的愿景中,Fornax希望借助第三方库的支持,能够对版本管理系统进行更加准确地定义和使用。 147 | 148 | \section{持续集成管理模块} 149 | 150 | 持续集成管理模块是Fornax中较为复杂的模块之一。其职责不仅包括对代码执行持续集成,还有对于除了构建与发布镜像之外的所有在创建版本时需要进行的操作,比如构建前的钩子,构建后的钩子,以及发布管理等等。因此这样的命名不能反应其明确的功能,但是在Fornax中还是以这样的方式去命名的,因为在最初时它只是为了进行持续集成而存在的。 151 | 152 | \subsection{配置文件解析} 153 | 154 | 因为持续集成管理模块贯穿了创建版本流程的始终,因此对于该模块的实现介绍将从创建版本的流程出发。在创建版本的过程中,第一步是将仓库的代码进行Clone,接下来是解析代码中的配置文件。配置文件是用户定义的,与代码存放在相同目录下的一个YAML格式的文件。Fornax定义了一种语法与惯例,使得用户在按照语法将自己的需求以YAML文件的形式描述后Fornax可以根据该文件执行相应的操作。该文件默认名为caicloud.yml,如果在用户的仓库中存在以此命名的文件,Fornax会尝试解析该文件。这是持续集成管理模块的第一项职责。 155 | 156 | \begin{lstlisting}[caption={配置文件实例}] 157 | integration: 158 | services: 159 | mongo: 160 | image: mongo:2.4 161 | command: mongod 162 | image: golang:1.5 163 | volumes: 164 | - .:/go/src/github.com/gaocegege/the-big-brother-is-watching-you 165 | env: 166 | - GOPATH=/go 167 | commands: 168 | - pwd 169 | - ls 170 | - go get github.com/tools/godep 171 | - godep go build -race . 172 | - ./the-big-brother-is-watching-you --mongo-db-ip=mongo 173 | \end{lstlisting} 174 | 175 | 代码所示是一个完整的配置文件。其中包括了五个阶段的配置信息,分别是持续集成、构建前、构建与发布、构建后、以及发布。在Fornax中,整个创建版本的过程都是由该配置文件进行控制的。用户可以通过定义各个阶段的配置,来确定构建阶段的行为。持续集成管理模块会对该配置文件进行解析,将其解析为一个运行时的树状结构,然后逐一执行。解析过程与传统编译器的词法分析器和语法分析器的实现类似,通过将配置文件的结构以结构体的形式定义,将配置文件解析为树状结构。树状结构可以直接被持续集成管理模块中的运行时所解释,从而根据配置执行相应的任务。 176 | 177 | \subsection{执行树构建} 178 | 179 | \begin{table}[!hpb] 180 | \centering 181 | \caption{语法树节点类型} 182 | \label{tab:nodetype} 183 | \begin{tabular}{ll} \toprule 184 | 节点类型 & 描述 \\ \midrule 185 | NodeList & 根节点类型,用以构造多叉树 \\ 186 | NodePreBuild & 构建前节点类型 \\ 187 | NodeBuild & 持续集成中有关构建的节点类型 \\ 188 | NodePostBuild & 构建后节点类型 \\ 189 | NodeService & 持续集成中有关服务的节点类型 \\ \bottomrule 190 | \end{tabular} 191 | \end{table} 192 | 193 | 执行树是一个多叉树结构,是由配置文件解析生成的,运行时执行的一个树状结构。表\ref{tab:nodetype}是树状结构中的节点类型。其中根节点是一个以节点为元素的列表。而其他节点类型都是以节点形式存在于该列表中。目前,执行树的深度最大为一,即所有的节点都直接与根节点相连。除了根节点外,其余所有节点都是一个包含了部分用户的配置信息的节点。而配置信息与节点的对应关系并不是一对一的,比如持续集成节点就对应着零个或多个服务节点,以及一个构建节点。因此执行树并不是一个语法树,而是一个由语法树得到的为了运行时而存在的结构。 194 | 195 | 运行时的环境除了执行树之外,还有一些用来进行资源隔离,以及与数据库等进行交互的对象。这些对象共同构成了持续集成管理模块的运行时环境。在运行时,除了根节点之外,所有的节点都与一个Docker容器对应。不同的阶段都对应着一个或者多个Docker容器,因此持续集成、构建前和构建后的钩子等等功能,都是通过Docker的容器机制实现的。 196 | 197 | \begin{figure}[!htp] 198 | \centering 199 | \includegraphics[width=0.7\textwidth]{detail/tree.png} 200 | \caption{Fornax执行树模型} 201 | \label{fig:tree} 202 | \end{figure} 203 | 204 | 使用容器来执行各个阶段的任务,是出于资源隔离的考虑。容器本身具有轻量级,隔离性较好等特性,非常适合用来处理构建任务。构建任务需要在任务内所有的资源共享而构建任务之间应该具有良好地资源隔离性。为了实现这一要求,Fornax在网络,处理器,内存等的使用上都做了一些处理。首先从网络层面,为了保证构建内的所有容器可以相互交互而构建外的容器不可感知到其存在,Fornax使用了Docker的网络特性,为每一次构建都新建了一个Docker的网络。如图\ref{fig:tree}所示,在一次构建内,所有的容器都在一个为构建任务新建的Docker的网络中。在网络中,所有的容器都可以通过容器的名字或者定义的别名去对其他容器进行服务发现,这是由DNS的名字解析来实现的。而在同一个Docker Host中不允许有同名的容器,因此为了解决名字冲突问题,Fornax对需要暴露服务的容器会将其的名字以网络中的别名的形式出现,而对于容器名则进行一定的随机以保证不存在名字冲突。因此对于容器而言,其不感知自己名字而可以通过别名的方式让其他的容器与其进行交互。 205 | 206 | 引入Docker的网络是为了解决网络的隔离问题,而处理器和内存的隔离问题的解决相对而言要简单很多。容器本身在运行时就支持指定一定的处理器与内存配额,其实现方式取决于容器引擎的实现。目前Docker是依赖内核中的一些特性来实现的,其功能已经可以满足Fornax对隔离性的要求。因此Fornax会在启动容器时指定容器可用的最大处理器与内存配额,在之后Fornax的愿景是可以根据构建任务的需求,允许用户在一定的范围内指定配额,或者向用户推荐其最合适的配额。 207 | 208 | 除此之外,使用容器技术解决隔离问题,会涉及到代码目录应该如何映射到容器中的问题。因为对于一次构建而言,会有多个容器被启动。因此在容器中进行Clone是低效的选择,而Fornax使用Docker的数据卷特性,先把代码仓库Clone到本地,之后绑定到容器中,这样的实现方式也使得容器对于目录的修改会被保留在本地,在整个创建版本的流程中所有的工件都可以保留下来。 209 | 210 | \subsection{持续集成} 211 | 212 | 持续集成是持续集成管理模块中比较重要,也是实现难度比较大的一个功能,对于持续集成的支持是Fornax在设计之初最重要的需求之一。对于用户代码的持续集成,不仅是允许用户对其代码执行一些简单的测试,也要同时支持在测试同时将用户的环境依赖运行起来,满足一些端到端测试的需要。因此,在持续集成中,也存在一个服务的概念。此处的服务与Fornax中的服务并不是同一概念,Fornax中的服务是与用户的仓库相对应的一个概念,代表了用户的一个功能模块。而在持续集成中的服务,是指用户的代码在运行时的环境依赖。比如一个典型的网站应用,会由前端、后端服务器和数据库组成,而对于前端的端到端的测试,需要将后端的服务器和数据库运行起来才能进行,而在持续集成的概念里,后端的服务器与数据库在此时即可被视为服务。而Fornax支持用户的持续集成对于服务的依赖,是使用容器技术来对其进行支持的。 213 | 214 | 在之前的配置文件一节中,配置持续集成不仅可以指定持续集成的命令,环境变量等,还有一个其他的阶段都不存在的配置,即服务配置。用户可以通过定义服务配置,在持续集成时先将服务运行起来,随后再执行定义的持续集成命令。因此在持续集成阶段,会有多个容器被启动,容器之间都会被加入到同一个Docker的网络中以相互通信。在持续集成结束后,Fornax会先将所有的容器都删除,之后再将构建中使用的Docker的网络删除,保证没有构建垃圾的残余。如果持续集成完成,会继续执行树结构上的其他节点,完成创建版本的流程,而如持续集成失败,就会返回错误,结束所有流程。因为对于构建垃圾的清理,以及数据库操作等都是以异步事件管理模块中的钩子来实现的,所以无论成功与否,都不会留下残留的垃圾,这也是异步事件管理模块在设计上的一种好处。 215 | 216 | 在持续集成时,持续集成管理模块会与Docker管理模块共用一个Docker Client对象,因此目前Docker管理模块与持续集成管理模块会有所耦合。 217 | 218 | \subsection{构建时钩子} 219 | 220 | Fornax支持构建前和构建后的钩子,由于两者所运行的时间不同,因此有不同的实现。对于构建前的钩子而言,往往是为了配合构建。在有关Docker的生产实践中,两个Dockerfile完成构建的应用场景越来越多,而这样的应用场景只通过构建与发布的过程,并不能得到满足。而引入了构建前的钩子,就可以满足这样的需求。在实现上,Fornax会在持续集成结束后,再次根据构建前的钩子运行一个容器,该容器会执行在配置中定义的内容,而且采取了绑定目录的方式解决目录问题,所以在构建前的钩子中所产生的输出在构建时刻都是可见的。 221 | 222 | 构建后的钩子是为了执行一些用户定义的发布任务。因为在一些应用场景中,用户不仅仅需要产出一个版本镜像,还会有一些自定义的内容需要发布,构建后的钩子就是来解决这样的需求的。相比于其他的步骤而言,其实现较为简单,以一个容器的方式运行,并且执行用户定义的脚本。 223 | 224 | \subsection{部署} 225 | 226 | 除了构建与发布之外,所有的环节都由配置文件所控制。因此在部署时,也是由用户在配置文件中写明要部署的具体集群与位置,Fornax会负责与其后的容器集群进行交互,完成部署任务。在部署时,是通过集群的REST API与其进行交互。因此相对于容器集群而言,Fornax是一个服务的前端,用户可以通过原本的方式进行部署,也可以在Fornax中使用配置的方式完成自动部署。 227 | 228 | \section{Docker后台管理模块} 229 | 230 | Docker后台管理模块是为了更好地解决并发构建而引入的模块。通过Docker网络的支持,Fornax使得每次构建之间不会出现端口的冲突,而这并不能完全解决并发的构建问题。除此之外,还存在一个问题,就是在同一时间内的同一个镜像,Docker只允许有一个镜像被推送,而这样是不能满足Fornax的需求的,因此需要引入Docker后台管理模块来解决该问题。 231 | 232 | Docker后台管理模块是在开发的后期被引入的一个模块,它会管理多个连接不同Docker Host的Docker管理模块,可以被理解为是维护一个可用的Docker管理模块的资源池的模块。当需要使用Docker管理模块进行镜像的构建与发布时,Fornax会向Docker后台管理模块请求一个空闲的Docker管理模块实例,之后的操作中会使用该实例进行镜像的推送与发布。 233 | 234 | \section{日志模块} 235 | 236 | 日志对于Fornax而言的重要性毋庸置疑。而Fornax为了保证日志可以准确而实时地推送给用户前端的同时,保持Fornax的资源高效利用,因此设计了一套基于WebSocket的与客户端进行通信的简易协议。该协议允许Fornax与客户端建立WebSocket连接,在有日志产生时,实时地将日志推送给用户端。同时在用户端一定时间内没有回应时,Fornax会自行关闭该连接,以保证不会因为保持过多的连接造成资源的浪费。 237 | 238 | 日志模块的实现依赖Kafka,一个使用阿帕奇许可证开源的高吞吐量的分布式消息中间件系统。Kafka支持发布者-订阅者的模式,对一个指定的主题(Topic)进行订阅,订阅者会在有新消息被提交时收到该消息。Fornax会在每次构建时,新建一个Kafka的主题,该主题会对应一次构建,在该构建中的所有日志都会发送至该主题。而Fornax会负责将主题持久化,并且在有订阅者订阅该主题时进行推送。 239 | 240 | 在Fornax中,通过Kafka实现了对日志的订阅,而与客户端进行交互则是使用了WebSocket连接。WebSocket是在RFC 6455\cite{websocket}中被提出来的一种建立在单个TCP连接上的全双工的通信协议。它允许服务端向用户端主动地推送数据或信息,这正是日志推送所需要的功能。 241 | 242 | \begin{figure}[!htp] 243 | \centering 244 | \includegraphics[width=0.9\textwidth]{detail/log.png} 245 | \caption{Fornax日志模块交互图} 246 | \label{fig:log} 247 | \end{figure} 248 | 249 | 为了实现日志实时推送的功能,Fornax在其主线程之外还有一个监听其他端口的日志服务器线程,该服务器只负责有关日志获取的部分逻辑。它从Kafka中获取日志,并将其推送给订阅相关日志的客户端。客户端、Fornax主服务器线程、Fornax日志服务器线程与Kafka之间的交互如图\ref{log}所示,当客户端发起一次构建时,Fornax会先生成一个唯一的标识符代表这次构建产生的版本,而随后会由异步事件管理模块调度构建的运行。在运行时,构建产生的日志会由Fornax推送给Kafka,而指定的主题是由发起构建的用户唯一标识符,构建所在的服务的唯一标识符,和代表该次构建的唯一标识符拼接而成。所有在构建时的日志都会被推送至该主题中。 250 | 251 | 因此,所有构建时的日志都会推送至Kafka中,而Fornax日志服务器线程,其本质是一个只与Kafka进行交互的独立线程。它会监听一个独立于Fornax主线程的端口,接受来自客户端的请求并处理。当接收到来自客户端的请求时,Fornax日志模块会去订阅相应的日志主题,然后当Fornax在构建时的日志被推送到Kafka中时,日志管理模块就可以订阅到该推送,并借由之前建立的连接推送至客户端,完成日志的推送工作。 252 | 253 | 为了完成这一步,Fornax设计了一个简单的应用层通信协议,保证日志可以实时准确地推送到客户端的同时不会占用过多的资源。首先,客户端会与Fornax的日志管理模块建立WebSocket连接,以便客户端与Fornax之间进行通信,客户端与Fornax通信的数据格式为JSON。请求与返回的数据包格式如表\ref{tab:protocol-client}和表\ref{tab:protocol-server}所示。在客户端想订阅日志时,会先向Fornax发送一个数据包,该数据包有如表\ref{tab:protocol-client}所示的字段。其中第一个字段动作在客户端发往Fornax的请求中会被置为查看日志,而接口字段会被统一置为创建服务或者创建版本,因为只有在创建服务或者版本时Fornax才有日志被写入Kafka中。而后面的用户、服务、与版本的唯一标识符是为了确定请求对应的具体日志。此时是客户端向Fornax发送的第一个包,用以通知Fornax该客户端希望订阅一个具体的日志。因此请求包中的日志字段为空,操作字段会被置为开始,以通知Fornax该客户端希望开始接收该次构建的日志推送。而唯一标识符则是唯一的标识该包的字段,会被设为一个自动生成的通用唯一识别码(Universally Unique Identifier)。通用唯一识别码的目的在于唯一的标识该包,在客户端与Fornax密集通信时保持请求与回应的一致。 254 | 255 | \begin{table}[!hpb] 256 | \centering 257 | \caption{Fornax日志模块请求的数据包格式} 258 | \label{tab:protocol-client} 259 | \begin{tabular}{ll} \toprule 260 | 字段 & 说明 \\ \midrule 261 | action & 动作 \\ 262 | api & 接口 \\ 263 | user\_id & 用户名 \\ 264 | service\_id & 服务唯一标识符 \\ 265 | version\_id & 版本唯一标识符 \\ 266 | log & 日志内容 \\ 267 | operation & 操作 \\ 268 | id & 唯一标识符 \\ \bottomrule 269 | \end{tabular} 270 | \end{table} 271 | 272 | \begin{table}[!hpb] 273 | \centering 274 | \caption{Fornax日志模块返回的数据包格式} 275 | \label{tab:protocol-server} 276 | \begin{tabular}{ll} \toprule 277 | 字段 & 说明 \\ \midrule 278 | action & 动作 \\ 279 | reponse & 返回 \\ 280 | id\_ack & 请求的唯一标识符 \\ 281 | error\_code & 错误码 \\ 282 | error\_msg & 错误信息 \\ \bottomrule 283 | \end{tabular} 284 | \end{table} 285 | 286 | 在Fornax收到动作字段为查看日志的请求包,并且该包中操作字段为开始时,会返回一个包以表示收到该请求包,返回的包格式如表\ref{tab:protocol-server}所示,在返回的包中,动作字段统一会被置为返回,而返回字段会被置为收到请求,请求的唯一标识符字段会被置为之前请求包中自动生成的通用唯一识别码,而错误码为零,错误信息会置为成功。与此同时,日志模块会创建一个新的线程,并且在线程中创建一个Kafka的消费者对象,该对象会订阅根据请求中用户、服务、版本三个唯一标识符而确定的唯一的日志主题,随后会向与客户端建立的会话中推送包含日志信息的数据包。这是由Fornax主动推送给客户端的包,其格式与客户端向Fornax发起的请求包格式一致,但字段的值会有所不同。其动作字段会被置为推送日志,而不是查看日志。而接口字段仍然与客户端的请求包中保持一致,其后的用户、服务、版本三个唯一标识符也同样与客户端的请求包中保持一致。而相比于客户端向Fornax发送的请求包,两者最大的不同在于其日志字段不再为空,而是会根据Kafka中订阅的主题获得的日志数据来进行发送。客户端在接收到Fornax发送的日志推送包时,会返回一个格式如表\ref{tab:protocol-server}所示的包,以通知Fornax该包已经被接收。 287 | 288 | 在Fornax中,日志模块是运行在一个单独的线程中的。在日志写入Kafka的部分实现中,是使用了本地与Kafka相互配合的方式来进行的。首先,关于构建的日志会写入到一个临时文件中,这是最开始Fornax的实现。而在开发中发现将日志信息存储在本地不利于Fornax的分布式部署,因此在之后的实现中引入了Kafka的依赖。在引入Kafka后,Fornax同样会先将日志信息存储在本地的文件中,而在每次构建时,会启动一个新的线程去监听日志文件的变化。目前监听的实现方式是轮询,每隔一定的时间间隔Fornax会重新访问本地的临时日志文件,将变动以消息的方式发送给Kafka。日志写入Kafka的实现是日志模块与Fornax主要功能想耦合的一部分,在进行构建时会调用该部分实现进行日志的写入。 289 | 290 | 而将日志发送给客户端是独立于Fornax主要功能的实现,是一个单独的服务器线程。在该部分实现中,日志模块会启动一个监听端口的服务器,并维护一个活跃的WebSocket连接的会话列表。该服务器只提供一个接口,即建立客户端与日志模块的连接。在连接建立后,日志模块会直接通过连接与客户端进行交互。日志模块在交互时定义了两个通信的接口,分别是查看日志与发送心跳。客户端可以对日志模块发送这两种类型的请求包,其中查看日志是前文中提到的由客户端第一次发给Fornax日志模块的请求包,而心跳是为了维持连接而由客户端定时地发送给Fornax日志模块的请求包,心跳请求会更新对应会话的最后活跃时间。 291 | 292 | 从实现来看,日志模块是一个相对独立于Fornax的模块,在后续对分布式部署实现的分析时会说明这样设计的目的。 293 | 294 | \section{数据库管理模块} 295 | 296 | 数据库管理模块,是Fornax与MongoDB进行交互的操作对象。在实现上,一共由两个管理器构成,即服务管理器与版本管理器。在Fornax被启动时,在初始化时会创建两个管理器的全局实例,随后会在API模块以及异步事件管理模块等模块中被使用。该模块的实现较为简单,是一层对于MongoDB中Collection的操作的封装。使得Fornax可以在代码中直接操作MongoDB中的对象。 297 | 298 | % 如图\ref{}所示,在Fornax的数据库设计中,一共有两个Collection,分别是服务与版本。 -------------------------------------------------------------------------------- /tex/end_english_abstract.tex: -------------------------------------------------------------------------------- 1 | %# -*- coding: utf-8-unix -*- 2 | \begin{bigabstract} 3 | Operating-system-level virtualization has been the hottest topic in Computer System and Cloud Computing. Docker is the most popular implementation of operating-system-level virtualization, it allows the programmers to build, ship and run their applications easily. Docker is hosted on Github, with 31256 stars by Mar 16th, 2016. Since Docker is now generally acceptable, there are many services and tools based on it. Kubernetes is a open-source system for automating deployment, operations, and scaling of containerized applications. The ecosystem of Docker is growing up rapidly. 4 | 5 | Fornax is a release management system, which is built on Docker. Fornax aims to provide the continuous integration, continuous deployment and version control of microservices. 6 | 7 | Continuous integration is a main feature in Fornax. Every time the programmers push their local changes to the remote repository, which is taken over by a specific version control system, such as Git or SVN, Fornax would create a continous integration task and run the customized commands. And Fornax is designed to integrate with popular CI tool like jenkins, to facilitate existing infrastructure. 8 | 9 | Continuous deployment is an important software engineering approach to agile software development. Fornax integrates with Kubernetes, to deploy microservices. When the integration test passed, Fornax would build a conatiner image from the commit, push it to registry, and deploy it to the container cluster. And Fornax allows to declare which cluster and which partition to deploy, and support to deploy on multiple cloud architectures such as public cloud, private cloud or hybrid cloud. The deployment cloud be flexible. 10 | 11 | Those two features make the Fornax a available continuous integration or continuous deployment tool, and the support for version control of microservices makes Fornax meet the demand of the modern software process. Repository in the traditional version control system is equivalent to a service in Fornax. Fornax would take over the version control of the programmers' application. So Fornax integrates with version control systems and Docker image service to make both code and runtime of the applications traceable and able to roll back. 12 | 13 | There are two concept in Fornax, service and version. Service is equivalent to a repository in the version control system. And version contains the code by a commit and a Docker image built from the code. A service would have more than one version, and the version could deploy to Kubernetes cluster. Fornax has a reasonable workflow, First The programmers should input the necessary information, including the URL of repository, the type of verson control system and the token for authorization if needed. Fornax would create a service for the repository, and check whether the information is correct. When the service is created successfully, Fornax would take over the version control of the service. When a commit is pushed to remote repository, Fornax would start a continuous integration task. If the task passes, Fornax would build a Docker image from the code, push it to the customized Docker Registry and store the information of the version. If the programmers have defined the settings about continuous deployment, Fornax would deploy the new version to user-defined cluster. From the perspective of programmers, they just need to push their commit to remote, and Fornax will take over the continuous intergation, version control and continuous deployment. 14 | 15 | Fornax has eight components: API module, async event manager, Docker manager, version control system manager(VCS manager), continuous integration manager(CI manager), Docker Daemon manager, log module, and datebase collection manager. 16 | 17 | API module wraps the Fornax as REST API. Fornax run as a HTTP server, listening a specific port. All the requests would reach the API module first and API module would filter the requests, ensure the requests are valid, then would handle the requests. It's a lot of time to create services or versions, so it is asynchronous. When API module receives the requests to create services or versions, it would send a event to async event manager. 18 | 19 | Async event manager schedules the event queue, it receives the events sent from API module, and handle these events asynchronously. There are two kinds of events: create services and create versions. Async event manager uses channels, the feature in golang, to perform a event loop. And it will integrates with Docker manager, CI manager and VCS manager to deal with the two kinds of events. 20 | 21 | Docker manager is a wrapper around Docker Client. Fornax would build and push the image to Docker Registry by Docker manager. And To push the image isolatedly, Fornax implements Docker Daemon manager to manages multiple Docker manager. When async event manager should call Docker manager to push the image, it would acquire a idle Docker manager from Docker Daemon manger, then push the image to Docker Registry. 22 | 23 | VCS manager is a wrapper around the version control systems, Continuous integration requires some VCS operations, so Fornax need to import the VCS bundle. Now VCS manager supports Git and SVN, and in the future, other version control systems would be adapted. 24 | 25 | CI manager is the most important module in Fornax. CI manager take over the life cycle of a version, from continuous integration and deployment. First, CI manager would check whether the file named caicloud.yml exists. The file is the config during creating version process. It defines the operations that should be executed when the version is created. If the file doesn't exists, the CI manager wouldn't work, and Fornax just builds and pushes docker image to Docker Registry. Then CI manager parses the config file, and run continuous integration, before-build-hook, build, push, post-build-hook and deploy one by one. 26 | 27 | At the continuous integration step, CI manager would run the dependencies and the service as containers, these containers would communicate with each other via DNS name resolution. CI manager promises that the containers in one request would discover each other, but containers in different requests could do that. 28 | 29 | At the before-build-hook and post-build-hook step, CI manager would run a single container, and execute the customized commands. Fornax supports the hooks to improve usability. 30 | 31 | Build and push are two default steps in Fornax. A version could have some optional steps to run, such as continuous integration or before-build-hook, and two default steps, build and push. In these two steps, Fornax would build the docker image, and push it to Docker Registry. 32 | 33 | CI manager is a monolithic module, and in the future, CI manager would be refactored. 34 | 35 | log module is another module, which is focuing on logs during the version creating process. At first, Fornax stores logs locally. With the increase of throughput, Fornax shuold be deployed as a distributed application. So log module imports Kafka, an open source messaging system, to store logs in the distributed architecture. And log module communicates with the clients by WebSocket, WebSocket allows Fornax to push real-time logs to client. 36 | 37 | Datebase collection manager wraps the connection to MongoDB, Fornax would store the services and versions into MongoDB by database collection manager. It's a global module exposed to all other modules. 38 | 39 | To avoid serious bugs, Fornax has many sound test cases. There are 11 test cases about services and 24 test cases about versions. The test cases are end-to-end, and covers the main workflow of Fornax and some alternative flow. These test cases help us keep the code in high quality. 40 | 41 | And with the growth of throughput, Fornax imports HAProxy, an open source load balancer to distribute. Fornax is designed to stateless, so the requests could route to an arbitrary Fornax instance. Distributed architecture improves the availability, makes Fornax production-ready. 42 | 43 | Although Fornax is production-ready, it also has a lot of problems to solve, especially in CI manager and log module. In some situation, CI manager could recycle the containers and the network, which would cause the resource leak. And log module now is not stable enough, in the future, Fornax would fix these problems to make it much more robust. 44 | \end{bigabstract} 45 | -------------------------------------------------------------------------------- /tex/example.tex: -------------------------------------------------------------------------------- 1 | %# -*- coding: utf-8-unix -*- 2 | %%================================================== 3 | %% chapter02.tex for SJTU Master Thesis 4 | %% based on CASthesis 5 | %% modified by wei.jianwen@gmail.com 6 | %% Encoding: UTF-8 7 | %%================================================== 8 | 9 | \chapter{ \LaTeX 排版例子} 10 | \label{chap:example} 11 | 12 | \section{列表环境} 13 | \label{sec:list} 14 | 15 | \subsection{无序列表} 16 | \label{sec:unorderlist} 17 | 18 | 以下是一个无序列表的例子,列表的每个条目单独分段。 19 | 20 | \begin{itemize} 21 | \item 这是一个无序列表。 22 | \item 这是一个无序列表。 23 | \item 这是一个无序列表。 24 | \end{itemize} 25 | 26 | 使用\verb+itemize*+环境可以创建行内无序列表。 27 | \begin{itemize*} 28 | \item 这是一个无序列表。 29 | \item 这是一个无序列表。 30 | \item 这是一个无序列表。 31 | \end{itemize*} 32 | 行内无序列表条目不单独分段,所有内容直接插入在原文的段落中。 33 | 34 | \subsection{有序列表} 35 | \label{sec:orderlist} 36 | 37 | 使用环境\verb+enumerate+和\verb+enumerate*+创建有序列表, 38 | 使用方法无序列表类似。 39 | 40 | \begin{enumerate} 41 | \item 这是一个有序列表。 42 | \item 这是一个有序列表。 43 | \item 这是一个有序列表。 44 | \end{enumerate} 45 | 46 | 使用\verb+enumerate*+环境可以创建行内有序列表。 47 | \begin{enumerate*} 48 | \item 这是一个默认有序列表。 49 | \item 这是一个默认有序列表。 50 | \item 这是一个默认有序列表。 51 | \end{enumerate*} 52 | 行内有序列表条目不单独分段,所有内容直接插入在原文的段落中。 53 | 54 | \subsection{描述型列表} 55 | 56 | 使用环境\verb+description+可创建带有主题词的列表,条目语法是\verb+\item[主题] 内容+。 57 | \begin{description} 58 | \item[主题一] 详细内容 59 | \item[主题二] 详细内容 60 | \item[主题三] 详细内容 \ldots 61 | \end{description} 62 | 63 | \subsection{自定义列表样式} 64 | 65 | 可以使用\verb+label+参数控制列表的样式, 66 | 详细可以参考WikiBooks\footnote{\url{https://en.wikibooks.org/wiki/LaTeX/List_Structures\#Customizing_lists}}。 67 | 比如一个自定义样式的行内有序列表 68 | \begin{enumerate*}[label=\itshape\alph*)\upshape] 69 | \item 这是一个自定义样式有序列表。 70 | \item 这是一个自定义样式有序列表。 71 | \item 这是一个自定义样式有序列表。 72 | \end{enumerate*} 73 | 74 | \section{数学排版} 75 | \label{sec:matheq} 76 | 77 | \subsection{公式排版} 78 | \label{sec:eqformat} 79 | 80 | 这里有举一个长公式排版的例子,来自\href{http://www.tex.ac.uk/tex-archive/info/math/voss/mathmode/Mathmode.pdf}{《Math mode》}: 81 | 82 | \begin {multline} 83 | \frac {1}{2}\Delta (f_{ij}f^{ij})= 84 | 2\left (\sum _{i0} C 102 | \end{displaymath} 103 | 104 | \begin{eqnarray} 105 | f(x) & \xleftrightarrow[]{A=B} & B \\ 106 | & \xleftharpoondown[below]{above} & B \nonumber \\ 107 | & \xLeftrightarrow[below]{above} & B 108 | \end{eqnarray} 109 | 110 | 又如: 111 | 112 | \begin{align} 113 | \label{eq:none} 114 | & I(X_3;X_4)-I(X_3;X_4\mid{}X_1)-I(X_3;X_4\mid{}X_2) \nonumber \\ 115 | = & [I(X_3;X_4)-I(X_3;X_4\mid{}X_1)]-I(X_3;X_4\mid{}\tilde{X}_2) \\ 116 | = & I(X_1;X_3;X_4)-I(X_3;X_4\mid{}\tilde{X}_2) 117 | \end{align} 118 | 119 | \subsection{定理环境} 120 | 121 | 模板中定义了丰富的定理环境 122 | algo(算法),thm(定理),lem(引理),prop(命题),cor(推论),defn(定义),conj(猜想),exmp(例),rem(注),case(情形), 123 | bthm(断言定理),blem(断言引理),bprop(断言命题),bcor(断言推论)。 124 | amsmath还提供了一个proof(证明)的环境。 125 | 这里举一个“定理”和“证明”的例子。 126 | \begin{thm}[留数定理] 127 | \label{thm:res} 128 | 假设$U$是复平面上的一个单连通开子集,$a_1,\ldots,a_n$是复平面上有限个点,$f$是定义在$U\backslash \{a_1,\ldots,a_n\}$上的全纯函数, 129 | 如果$\gamma$是一条把$a_1,\ldots,a_n$包围起来的可求长曲线,但不经过任何一个$a_k$,并且其起点与终点重合,那么: 130 | 131 | \begin{equation} 132 | \label{eq:res} 133 | \ointop_{\gamma}f(z)\,\mathrm{d}z = 2\uppi\mathbf{i}\sum^n_{k=1}\mathrm{I}(\gamma,a_k)\mathrm{Res}(f,a_k) 134 | \end{equation} 135 | 136 | 如果$\gamma$是若尔当曲线,那么$\mathrm{I}(\gamma, a_k)=1$,因此: 137 | 138 | \begin{equation} 139 | \label{eq:resthm} 140 | \ointop_{\gamma}f(z)\,\mathrm{d}z = 2\uppi\mathbf{i}\sum^n_{k=1}\mathrm{Res}(f,a_k) 141 | \end{equation} 142 | 143 | % \oint_\gamma f(z)\, dz = 2\pi i \sum_{k=1}^n \mathrm{Res}(f, a_k ). 144 | 145 | 在这里,$\mathrm{Res}(f, a_k)$表示$f$在点$a_k$的留数,$\mathrm{I}(\gamma,a_k)$表示$\gamma$关于点$a_k$的卷绕数。 146 | 卷绕数是一个整数,它描述了曲线$\gamma$绕过点$a_k$的次数。如果$\gamma$依逆时针方向绕着$a_k$移动,卷绕数就是一个正数, 147 | 如果$\gamma$根本不绕过$a_k$,卷绕数就是零。 148 | 149 | 定理\ref{thm:res}的证明。 150 | 151 | \begin{proof} 152 | 首先,由…… 153 | 154 | 其次,…… 155 | 156 | 所以…… 157 | \end{proof} 158 | \end{thm} 159 | 160 | 上面的公式例子中,有一些细节希望大家注意。微分号d应该使用“直立体”也就是用mathrm包围起来。 161 | 并且,微分号和被积函数之间应该有一段小间隔,可以插入\verb+\,+得到。 162 | 斜体的$d$通常只作为一般变量。 163 | i,j作为虚数单位时,也应该使用“直立体”为了明显,还加上了粗体,例如\verb+\mathbf{i}+。斜体$i,j$通常用作表示“序号”。 164 | 其他字母在表示常量时,也推荐使用“直立体”譬如,圆周率$\uppi$(需要upgreek宏包),自然对数的底$\mathrm{e}$。 165 | 不过,我个人觉得斜体的$e$和$\pi$很潇洒,在不至于引起混淆的情况下,我也用这两个字母的斜体表示对应的常量。 166 | 167 | 168 | \section{向文档中插入图像} 169 | \label{sec:insertimage} 170 | 171 | \subsection{支持的图片格式} 172 | \label{sec:imageformat} 173 | 174 | \XeTeX 可以很方便地插入PDF、PNG、JPG格式的图片。 175 | 176 | 插入PNG/JPG的例子如\ref{fig:SRR}所示。 177 | 这两个水平并列放置的图共享一个“图标题”(table caption),没有各自的小标题。 178 | 179 | \begin{figure}[!htp] 180 | \centering 181 | \includegraphics[width=0.3\textwidth]{example/sjtulogo.png} 182 | \hspace{1cm} 183 | \includegraphics[width=0.3\textwidth]{example/sjtulogo.jpg} 184 | \bicaption[fig:SRR]{这里将出现在插图索引中}{中文题图}{Fig}{English caption} 185 | \end{figure} 186 | 187 | % 这里还有插入eps图像和pdf图像的例子,如图\ref{fig:epspdf:a}和图\ref{fig:epspdf:b}。这里将EPS和PDF图片作为子图插入,每个子图有自己的小标题。并列子图的功能是使用subfigure宏包提供的。 188 | % 189 | % \begin{figure} 190 | % \centering 191 | % \subfigure[EPS Figure]{ 192 | % \label{fig:epspdf:a} %% label for first subfigure 193 | % \includegraphics[width=0.3\textwidth]{example/sjtulogo.eps}} 194 | % \hspace{1in} 195 | % \subfigure[PDF Figure]{ 196 | % \label{fig:epspdf:b} %% label for second subfigure 197 | % \includegraphics[width=0.3\textwidth]{example/sjtulogo.pdf}} 198 | % \bicaption[fig:pdfeps]{插入eps图像和pdf图像}{插入eps和pdf的例子}{Fig}{An EPS and PDF demo} 199 | % \end{figure} 200 | 201 | 更多关于 \LaTeX 插图的例子可以参考\href{http://www.cs.duke.edu/junhu/Graphics3.pdf}{《\LaTeX 插图指南》}。 202 | 203 | \subsection{长标题的换行} 204 | \label{sec:longcaption} 205 | 206 | 图\ref{fig:longcaptionbad}和图\ref{fig:longcaptiongood}都有比较长图标题,通过对比发现,图\ref{fig:longcaptiongood}的换行效果更好一些。 207 | 其中使用了minipage环境来限制整个浮动体的宽度。 208 | 209 | \begin{figure}[!htp] 210 | \centering 211 | \includegraphics[width=4cm]{example/sjtulogo.pdf} 212 | \bicaption[fig:longcaptionbad]{这里将出现在插图索引}{海交通大学是我国历史最悠久的高等学府之一,是教育部直属、教育部与上海市共建的全国重点大学.}{Fig}{Where there is a will, there is a way.} 213 | \end{figure} 214 | 215 | \begin{figure}[!htbp] 216 | \centering 217 | \begin{minipage}[b]{0.6\textwidth} 218 | \captionstyle{\centering} 219 | \centering 220 | \includegraphics[width=4cm]{example/sjtulogo.pdf} 221 | \bicaption[fig:longcaptiongood]{这里将出现在插图索引}{海交通大学是我国历史最悠久的高等学府之一,是教育部直属、教育部与上海市共建的全国重点大学.}{Fig}{Where there is a will, there is a way.} 222 | \end{minipage} 223 | \end{figure} 224 | 225 | \subsection{绘制流程图} 226 | 227 | 图\ref{fig:flow_chart}是一张流程图示意。使用tikz环境,搭配四种预定义节点(\verb+startstop+、\verb+process+、\verb+decision+和\verb+io+),可以容易地绘制出流程图。 228 | \begin{figure}[!p] 229 | \centering 230 | \resizebox{6cm}{!}{\input{figure/example/flow_chart.tex}} 231 | \bicaption[fig:flow_chart]{绘制流程图效果}{流程图}{Fig}{Flow chart} 232 | \end{figure} 233 | 234 | \clearpage 235 | 236 | \section{表格} 237 | \label{sec:tab} 238 | 239 | 这一节给出的是一些表格的例子,如表\ref{tab:firstone}所示。 240 | 241 | \begin{table}[!hpb] 242 | \centering 243 | \bicaption[tab:firstone]{指向一个表格的表目录索引}{一个颇为标准的三线表格\footnotemark[1]}{Table}{A Table} 244 | \begin{tabular}{@{}llr@{}} \toprule 245 | \multicolumn{2}{c}{Item} \\ \cmidrule(r){1-2} 246 | Animal & Description & Price (\$)\\ \midrule 247 | Gnat & per gram & 13.65 \\ 248 | & each & 0.01 \\ 249 | Gnu & stuffed & 92.50 \\ 250 | Emu & stuffed & 33.33 \\ 251 | Armadillo & frozen & 8.99 \\ \bottomrule 252 | \end{tabular} 253 | \end{table} 254 | \footnotetext[1]{这个例子来自\href{http://www.ctan.org/tex-archive/macros/latex/contrib/booktabs/booktabs.pdf}{《Publication quality tables in LATEX》}(booktabs宏包的文档)。这也是一个在表格中使用脚注的例子,请留意与threeparttable实现的效果有何不同。} 255 | 256 | 下面一个是一个更复杂的表格,用threeparttable实现带有脚注的表格,如表\ref{tab:footnote}。 257 | 258 | \begin{table}[!htpb] 259 | \bicaption[tab:footnote]{出现在表目录的标题}{一个带有脚注的表格的例子}{Table}{A Table with footnotes} 260 | \centering 261 | \begin{threeparttable}[b] 262 | \begin{tabular}{ccd{4}cccc} 263 | \toprule 264 | \multirow{2}{6mm}{total}&\multicolumn{2}{c}{20\tnote{1}} & \multicolumn{2}{c}{40} & \multicolumn{2}{c}{60}\\ 265 | \cmidrule(lr){2-3}\cmidrule(lr){4-5}\cmidrule(lr){6-7} 266 | &www & k & www & k & www & k \\ 267 | \midrule 268 | &$\underset{(2.12)}{4.22}$ & 120.0140\tnote{2} & 333.15 & 0.0411 & 444.99 & 0.1387 \\ 269 | &168.6123 & 10.86 & 255.37 & 0.0353 & 376.14 & 0.1058 \\ 270 | &6.761 & 0.007 & 235.37 & 0.0267 & 348.66 & 0.1010 \\ 271 | \bottomrule 272 | \end{tabular} 273 | \begin{tablenotes} 274 | \item [1] the first note.% or \item [a] 275 | \item [2] the second note.% or \item [b] 276 | \end{tablenotes} 277 | \end{threeparttable} 278 | \end{table} 279 | 280 | \section{参考文献管理} 281 | 282 | \LaTeX 具有将参考文献内容和表现形式分开管理的能力,涉及三个要素:参考文献数据库、参考文献引用格式、在正文中引用参考文献。 283 | 这样的流程需要多次编译: 284 | 285 | \begin{enumerate}[noitemsep,topsep=0pt,parsep=0pt,partopsep=0pt] 286 | \item 用户将论文中需要引用的参考文献条目,录入纯文本数据库文件(bib文件)。 287 | \item 调用xelatex对论文模板做第一次编译,扫描文中引用的参考文献,生成参考文献入口文件(aux)文件。 288 | \item 调用bibtex,以参考文献格式和入口文件为输入,生成格式化以后的参考文献条目文件(bib)。 289 | \item 再次调用xelatex编译模板,将格式化以后的参考文献条目插入正文。 290 | \end{enumerate} 291 | 292 | 参考文献数据库(thesis.bib)的条目,可以从Google Scholar搜索引擎\footnote{\url{https://scholar.google.com}}、CiteSeerX搜索引擎\footnote{\url{http://citeseerx.ist.psu.edu}}中查找,文献管理软件Papers\footnote{\url{http://papersapp.com}}、Mendeley\footnote{\url{http://www.mendeley.com}}、JabRef\footnote{\url{http://jabref.sourceforge.net}}也能够输出条目信息。 293 | 294 | 下面是在Google Scholar上搜索到的一条文献信息,格式是纯文本: 295 | 296 | \begin{lstlisting}[caption={从Google Scholar找到的参考文献条目}, label=googlescholar, float, escapeinside="", numbers=none] 297 | @phdthesis{"白2008信用风险传染模型和信用衍生品的定价", 298 | title={{"信用风险传染模型和信用衍生品的定价"}}, 299 | author={"白云芬"}, 300 | year={2008}, 301 | school={"上海交通大学"} 302 | } 303 | \end{lstlisting} 304 | 305 | 为了方便引用,建议将文献别名改用ASCII表示。 306 | 中文文献的处理有别于英文文献,对中文参考文献需要增加“language”域显式说明。 307 | 308 | \begin{lstlisting}[caption={修改后的参考文献条目}, label=itemok, float, escapeinside="", numbers=none] 309 | @phdthesis{bai2008, 310 | title={{"信用风险传染模型和信用衍生品的定价"}}, 311 | author={"白云芬"}, 312 | year={2008}, 313 | language={zh}, 314 | address={"上海"}, 315 | school={"上海交通大学"} 316 | } 317 | \end{lstlisting} 318 | 319 | 按照教务处的要求,参考文献外观应符合国标GBT7714的要求\footnote{\url{http://www.cces.net.cn/guild/sites/tmxb/Files/19798_2.pdf}}。 320 | 在模板中,表现形式的控制逻辑在GBT7714-2005NLang.bst中实现\footnote{\url{http://bbs.ctex.org/viewthread.php?tid=33571}},是使用{\BibTeX}特有的堆栈式语言实现的\footnote{\url{http://ftp.ctex.org/mirrors/CTAN/info/bibtex/tamethebeast/ttb_en.pdf}}。 321 | 322 | 正文中引用参考文献时,用\verb+\upcite{key1,key2,key3...}+可以产生“上标引用的参考文献”, 323 | 如\upcite{Meta_CN,chen2007act,DPMG}。 324 | 使用\verb+\cite{key1,key2,key3...}+则可以产生水平引用的参考文献,例如\cite{JohnD,zhubajie,IEEE-1363}。 325 | 请看下面的例子,将会穿插使用水平的和上标的参考文献:关于书的\cite{Meta_CN,JohnD,IEEE-1363},关于期刊的\upcite{chen2007act,chen2007ewi}, 326 | 会议论文\cite{DPMG,kocher99,cnproceed}, 327 | 硕士学位论文\cite{zhubajie,metamori2004},博士学位论文\upcite{shaheshang,FistSystem01,bai2008},标准文件\cite{IEEE-1363},技术报告\upcite{NPB2},电子文献\cite{xiaoyu2001, CHRISTINE1998},用户手册\cite{RManual}。 328 | 329 | 总结一些注意事项: 330 | \begin{itemize} 331 | \item 参考文献只有在正文中被引用了,才会在最后的参考文献列表中出现; 332 | \item 参考文献“数据库文件”bib是纯文本文件,请使用UTF-8编码,不要使用GBK编码; 333 | \item 参考文献条目中通过language域是否为空判断是否是中文文献; 334 | \end{itemize} 335 | 336 | \section{用listings插入源代码} 337 | 338 | 原先ctexbook文档类和listings宏包配合使用时,代码在换页时会出现莫名其妙的错误,后来经高人指点,顺利解决了。 339 | 感兴趣的话,可以看看\href{http://bbs.ctex.org/viewthread.php?tid=53451}{这里}。 340 | 这里给使用listings宏包插入源代码的例子,这里是一段C代码。 341 | 另外,listings宏包真可谓博大精深,可以实现各种复杂、漂亮的效果,想要进一步学习的同学,可以参考 342 | \href{http://mirror.ctan.org/macros/latex/contrib/listings/listings.pdf}{listings宏包手册}。 343 | 344 | \begin{lstlisting}[language={C}, caption={一段C源代码}] 345 | #include 346 | #include 347 | #include 348 | #include 349 | 350 | int main() { 351 | pid_t pid; 352 | 353 | switch ((pid = fork())) { 354 | case -1: 355 | printf("fork failed\n"); 356 | break; 357 | case 0: 358 | /* child calls exec */ 359 | execl("/bin/ls", "ls", "-l", (char*)0); 360 | printf("execl failed\n"); 361 | break; 362 | default: 363 | /* parent uses wait to suspend execution until child finishes */ 364 | wait((int*)0); 365 | printf("is completed\n"); 366 | break; 367 | } 368 | 369 | return 0; 370 | } 371 | \end{lstlisting} 372 | 373 | \section{用algorithm和algorithmic宏包插入算法描述} 374 | 375 | 如算法\ref{algo:sum_I_want}所示。 376 | 377 | \begin{algorithm} 378 | \caption{求和算法} 379 | \label{algo:sum_I_want} 380 | \begin{algorithmic} 381 | \REQUIRE $n \geq 1$ %输入条件 382 | \ENSURE $Sum = 1 + \cdots + n$ %输出 383 | \STATE $Sum \leftarrow 0$ %\STATE 命名演示 384 | \IF {$n < 1$} %条件语句 385 | \PRINT {Input Error} %打印语句 386 | \ENDIF 387 | \RETURN Sum 388 | \end{algorithmic} 389 | \end{algorithm} 390 | 391 | 王凡教授\footnote{\url{http://cc.ee.ntu.edu.tw/~farn/}}对algorithmic做了扩展,支持\verb+STATE+、\verb+SWITCH+和\verb+CASE+等语句。 392 | 393 | \begin{algorithm} 394 | \caption{fibonacci} 395 | \label{algo: Fibonacci Sequence} 396 | \begin{algorithmic} 397 | \REQUIRE $num$ 398 | 399 | \STATE $res \leftarrow 0$ 400 | \SWITCH {$num$} 401 | \CASE {$0$} 402 | \STATE $res \leftarrow 1$ 403 | \ENDCASE 404 | \CASE {$1$} 405 | \STATE $res \leftarrow 1$ 406 | \ENDCASE 407 | \DEFAULT 408 | \STATE $res \leftarrow fibonacci(num-1) + fibonacci(num-2)$ 409 | \ENDDEFAULT 410 | \ENDSWITCH 411 | 412 | \RETURN $res$ 413 | \end{algorithmic} 414 | \end{algorithm} 415 | -------------------------------------------------------------------------------- /tex/faq.tex: -------------------------------------------------------------------------------- 1 | %# -*- coding: utf-8-unix -*- 2 | \chapter{常见问题} 3 | \label{chap:faq} 4 | 5 | {\bfseries{}Q:我是否能够自由使用这份模板?} 6 | 7 | A:这份模板以Apache License 2.0开源许可证发布,请遵循许可证规范。 8 | 9 | {\bfseries{}Q:我的论文是Word排版的,学校图书馆是不是只收 \LaTeX 排版的论文?} 10 | 11 | A:当然不是,Word版论文肯定收。 12 | 13 | {\bfseries{}Q:我的论文是 \LaTeX 排版的,学校图书馆是不是只收Word排版的论文?} 14 | 15 | A:当然不是,PDF版的电子论文是可以上交的。是否要交Word版就看你导师的喜好了。 16 | 17 | {\bfseries{}Q:为什么屏幕上显示的左右页边距不一样?} 18 | 19 | A:模板默认是双面打印,迎面页和背面页的页边距是要交换的,多出来的那一部分是留作装订的。 20 | 21 | {\bfseries{}Q:为什么在参考文献中会有“//”符号?} 22 | 23 | A:那就是国标GBT7714参考文献风格规定的。 24 | 25 | {\bfseries{}Q:为什么参考文献中会有[s.n.],[S.l], [EB/OL]等符号?} 26 | 27 | A: 那也是国标GBT7714参考文献风格定义的。[s.n.]表示出版者不祥,[S.l]表示出版地不祥,[EB/OL]表示引用的参考文献类型为在线电子文档。 28 | 29 | {\bfseries{}Q:如何获得帮助和反馈意见?} 30 | 31 | A:你可以通过\href{https://github.com/weijianwen/sjtu-thesis-template-latex/issues}{在github上开issue} 32 | 、在\href{https://bbs.sjtu.edu.cn/bbsdoc?board=TeX_LaTeX}{水源LaTeX版}发帖反映你使用过程中遇到的问题。 33 | 34 | {\bfseries{}Q:使用文本编辑器查看tex文件时遇到乱码?} 35 | 36 | A:请确保你的文本编辑器使用UTF-8编码打开了tex源文件。 37 | 38 | {\bfseries{}Q:在CTeX编译模板遇到“rsfs10.tfm already exists”的错误提示?} 39 | 40 | A:请删除\verb+X:\CTEX\UserData\fonts\tfm\public\rsfs+下的文件再重新编译。问题讨论见\href{https://bbs.sjtu.edu.cn/bbstcon,board,TeX_LaTeX,reid,1352982719.html}{水源2023号帖}。 41 | 42 | {\bfseries{}Q:升级了TeXLive 2012,编译后的文档出现“minus”等字样?} 43 | 44 | A:这是xltxtra和fontspec宏包导致的问题。学位论文模板从0.5起使用metatlog宏包代替xltxtra生成 \XeTeX 标志,解决了这个问题。 45 | 46 | {\bfseries{}Q:为什么在bib中加入的参考文献,没有在参考文献列表中出现?} 47 | 48 | A: bib中的参考文献条目,只有通过\verb+\cite+或者\verb+\upcite+在正文中引用,才会加入到参考文献列表中。 49 | 50 | {\bfseries{}Q:在macTex中,为什么pdf图片无法插入?} 51 | 52 | A:如果报错是“pdf: image inclusion failed for "./figure/chap2/sjtulogo.pdf".”,则采取以下步骤 53 | 54 | \begin{lstlisting}[basicstyle=\small\ttfamily, caption={编译模板}, numbers=none] 55 | brew install xpdf 56 | wget http://mirrors.ctan.org/support/epstopdf.zip 57 | unzip epstopdf.zip 58 | cp epstopdf/epstopdf.pl /usr/local/bin/ 59 | cd figure/chap2 60 | pdftops sjtulogo.pdf 61 | epstopdf sjtulogo.ps 62 | pdfcrop sjtulogo.pdf 63 | mv sjtulogo.pdf backup.pdf 64 | mv sjtulogo-crop.pdf sjtulogo.pdf 65 | \end{lstlisting} 66 | 67 | {\bfseries{}Q:如何向你致谢?} 68 | 69 | A: 烦请在模板的\href{https://github.com/weijianwen/SJTUThesis}{github主页}点击“Star”,我想粗略统计一下使用学位论文模板的人数,谢谢大家。非常欢迎大家向项目贡献代码。 70 | -------------------------------------------------------------------------------- /tex/id.tex: -------------------------------------------------------------------------------- 1 | %# -*- coding: utf-8-unix -*- 2 | \title{基于容器集群的版本管理与发布系统} 3 | \author{高\quad{}策} 4 | \advisor{任锐} 5 | % \coadvisor{某某教授} 6 | \defenddate{2016年6月13日} 7 | \school{上海交通大学} 8 | \institute{软件学院} 9 | \studentnumber{5120379091} 10 | \major{软件工程专业} 11 | 12 | \englishtitle{Fornax: A Version Release System Based on Container Cluster} 13 | \englishauthor{\textsc{Ce Gao}} 14 | \englishadvisor{Prof. \textsc{Rui Ren}} 15 | % \englishcoadvisor{Prof. \textsc{Uom Uom}} 16 | \englishschool{Shanghai Jiao Tong University} 17 | \englishinstitute{\textsc{School of Software} \\ 18 | \textsc{Shanghai Jiao Tong University} \\ 19 | \textsc{Shanghai, P.R.China}} 20 | \englishmajor{Bachelor} 21 | \englishdate{Jun. 13rd 2016} 22 | -------------------------------------------------------------------------------- /tex/impl.tex: -------------------------------------------------------------------------------- 1 | %# -*- coding: utf-8-unix -*- 2 | %%================================================== 3 | %% impl.tex for SJTU Master Thesis 4 | %%================================================== 5 | 6 | %\bibliographystyle{sjtu2}%[此处用于每章都生产参考文献] 7 | \chapter{系统需求分析与架构设计} 8 | \label{chap:impl} 9 | 10 | 本章从需求角度和架构角度出发,介绍了Fornax在设计之初面临的功能性需求以及非功能性需求,并且基于这些需求,介绍了Fornax使用的架构,以及技术选型。 11 | 12 | \section{需求分析} 13 | 14 | 持续集成与持续部署,已经成为了当下软件开发的最佳实践。因此也有越来越多的开发者希望能够在自己的开发流程中引入这样的实践来提高软件过程的效率与软件产品的质量。因此,持续集成与持续部署对于Fornax而言是非常重要的特性。持续集成要求Fornax必须与各种代码版本控制系统,比如Git,Svn等等进行交互。而持续部署要求Fornax要与应用的部署平台,也就是Kubernetes进行交互。 15 | 16 | \begin{figure}[!htp] 17 | \centering 18 | \includegraphics[width=0.5\textwidth]{impl/vcs.png} 19 | \caption{代码与镜像的版本控制} 20 | \label{fig:vcs-code} 21 | \end{figure} 22 | 23 | 而除此之外,Fornax作为基于容器集群的版本管理与发布系统,与其他的持续集成与持续部署工具比较大的不同在于,Fornax还需要负责对于软件应用构建情况的版本管理。在传统的软件过程中,只有代码是被纳入版本控制的,运行时的环境,依赖,都没有版本控制的概念。这样的实践存在一些问题,比如在代码被回滚时,往往需要同时将运行时环境,包括依赖一起进行回滚,而在传统的做法中,这样往往需要重新打包依赖,过程耗时长而且自动化程度低。在引入了容器后,情况产生了一些变化。容器技术引入的镜像,可以很好地解决对于依赖和环境的版本管理问题。每当用户代码被构建完成后,可以将整个运行环境,依赖,和代码打包成一个镜像,这样当需要回滚时,只需要根据之前已经打包好的镜像重新启动一个新的容器即可。这使得软件的开发与部署有了新的实践方式,而这也是Fornax希望实现的。如图\ref{fig:vcs-code}所示,Fornax希望能够将代码的版本管理结合Docker镜像的版本管理,在每次代码产生变动时,都构建一个Docker镜像,并将其推送到Docker Registry中,当用户遇到需要回滚代码时,不需要再重新检出代码之后再次进行构建,而是通过Kubernetes集群的Rolling back的特性,直接将容器回滚到前一个版本的镜像。这样使得持续部署和应用回滚成为了更加简单的特性。除此之外,对于用户的构建日志,需要进行持久化地处理,以便用户之后便于排查问题,这也是Fornax需要解决的问题。 24 | 25 | 上述是Fornax的功能性需求,除此之外,Fornax还需要满足一些非功能性的需求,比如需要保持扩展性较强的设计,来满足以后可能遇到的新的需求。以及保证自身的无状态性,便于在需要时对Fornax进行水平扩容,采取多实例的方式来保证Fornax能够比较便捷地进行分布式地部署,提高系统的可用性。 26 | 27 | \section{系统工作流} 28 | 29 | \begin{figure}[!htp] 30 | \centering 31 | \includegraphics[width=0.7\textwidth]{impl/workflow.png} 32 | \caption{Fornax系统工作流} 33 | \label{fig:workflow} 34 | \end{figure} 35 | 36 | 在Fornax中,有两个比较重要的概念,一个是服务,一个是版本。这两个概念模型贯穿了整个Fornax的生命周期。服务,是引申自微服务概念中的服务,是指一个代码仓库对应的概念。一个服务拥有自己的版本控制系统类型,以及仓库的地址等信息。而版本则相对于服务而言要更加复杂一些,版本是指一次构建的版本,其中包含构建的版本的名字,描述,以及该版本在集群上的部署情况,比如部署在哪个集群的哪个节点上的信息之类。在Fornax的设计中,一个版本对应一个Docker镜像,当用户需要回滚版本时,只需要对已经部署的容器进行镜像的回滚即可。服务和版本的概念串联起了Fornax的工作流。 37 | 38 | 在Fornax中,如果要使用其提供的基于容器集群的版本管理与发布服务,需要先建立一个与传统的版本控制工具,如Git,Svn等的仓库概念对应的服务,在建立服务后,相关于该仓库的信息就会被Fornax记录,之后每当代码发生了变动,都会由Fornax来进行一次版本的构建,版本的构建环节中,Fornax并不是简单地把代码打包成为一个Docker的镜像,而是一个相对于传统的版本管理与发布工具而言要复杂一些的步骤。 39 | 40 | 在Fornax的设计中,所有有关在构建时的配置等信息,是记录在一个YAML格式的配置文件中的。因此Fornax在收到一个构建版本的请求时,会先确定在Clone下来的仓库中是否存在这样的配置文件,如果存在,就会根据配置文件中的配置来执行相关的步骤,否则就会如同其他的工具一样,直接进行镜像的构建和发布。以下讨论都建立在仓库中存在该配置文件的基础上而进行。 41 | 42 | Fornax的工作流如图\ref{fig:workflow}所示,首先,Fornax会判断在配置文件中,是否有关于持续集成阶段的相关配置。如果存在这样的配置,Fornax会依据该配置文件,去进行相应的持续集成。通常持续集成的步骤会是执行持续集成测试,或者进行一些其他类型的测试以保证代码的质量,并根据持续集成的结果来判断是否需要打包新的版本。在Fornax中,持续集成的概念也是如此。在持续集成结束后,Fornax会根据结果来进行相应的操作,如果持续集成失败,那么整个流程都会结束,如果成功,Fornax会继续进行下一阶段的工作。值得一提的是,为了支持与现有的持续集成平台兼容,Fornax也允许使用Jenkins来进行持续集成,而不使用原本在Fornax中的持续集成,这样的妥协是为了保证能够尽快地接入现在主流的生产系统。 43 | 44 | 下一阶段的工作是构建和发布镜像。在这一阶段中,Fornax会在仓库中寻找目录下名为Dockerfile的文件,并根据该文件,去进行版本的构建。同时,为了满足一些自定义的需求,Fornax允许通过定义构建之前和之后的钩子(Hook)来执行一些用户定义的操作。在构建成镜像之后,Fornax会先将镜像存储在本地,在构建完成后,镜像会由Fornax推送到用户定义的Docker Registry或者推送到官方的Docker Registry上。 45 | 46 | 最后一阶段的工作是部署。在Fornax中,部署是指将打包好的镜像,在用户的集群中以容器的方式运行起来的过程,与持续集成相同,这也是自动化的过程。用户需要指定要部署的版本,选择集群,就可以将之前打包好的镜像发布到集群上。 47 | 48 | 在上述的阶段中,持续集成与持续部署是可选的阶段。而版本的构建会发布是每次代码发生变动时Fornax默认的行为。 49 | 50 | \section{架构设计} 51 | 52 | \begin{figure}[!htp] 53 | \centering 54 | \includegraphics[width=0.9\textwidth]{impl/design.png} 55 | \caption{Fornax系统设计图} 56 | \label{fig:design} 57 | \end{figure} 58 | 59 | 如图\ref{fig:design}所示,Fornax大致由八个模块构成。分别是API模块、异步事件管理模块、Docker管理模块、Docker后台管理模块、持续集成管理模块、版本管理系统管理模块、日志模块和数据库管理模块。这八个模块相互协同,实现了Fornax的所有功能。 60 | 61 | 其中,API模块是将Fornax的服务以REST API的形式开放给客户端使用。这里的客户端不在Fornax的范畴内,可以是基于网页的客户端,或者是以命令行的方式来进行交互。API模块是整个Fornax系统对外交互的模块,它的职责在于接受来自客户端的请求,进行基本的认证与过滤,确保用户可信。之后,API模块会将过滤后的请求分发给相应的处理器进行处理。处理器也是API模块的一部分,他们会与异步事件管理模块交互,将请求交由其来进行调度与分配。 62 | 63 | 而异步事件管理模块,是其中比较重要的模块,也是实现难度比较大的模块。异步事件管理模块的职责是接受来自API模块发送过来的事件,然后将其加入到一个队列中,等待其被处理,并在处理后执行在API模块中定义的钩子函数,来进行自定义的收尾。异步事件管理器,是独立地运行在一个线程里的,不会阻塞主线程的运行,这也是异步操作带来的主要好处之一。目前Fornax中主要的两个事件是创建服务和创建版本,其他诸如查询服务内容,删除服务等等,因为处理起来比较快,不会过多地阻塞主线程,因此并没有进行异步化处理,而创建服务,涉及到对于代码仓库的Clone,创建版本,则不仅涉及该操作,还有持续集成任务的执行、镜像的构建、镜像的发布、容器的部署等一系列的事情,所以如果不以异步的方式去执行,会导致系统效率极低。因此Fornax对于这两种操作进行了异步的处理。 64 | 65 | 持续集成、版本管理、以及Docker构建镜像,都是在创建服务或者创建版本时需要使用的功能,所以三者对应的管理模块,会与异步事件管理模块交互,当一个事件在被处理时,异步事件管理模块会调用相应事件的处理器来进行处理,而三个模块就是在处理器中被其调用,进行相应的逻辑处理。 66 | 67 | 其中,版本管理系统管理模块负责与版本管理系统交互的功能实现。目前,版本管理系统管理模块包含Git,Svn对应的实现。当创建服务时,Fornax会将指定的代码仓库Clone下来,进行一些简单的校验。在创建版本时,为了防止代码仓库的污染,在每一步都会重新Clone代码仓库到Fornax指定的目录下。以及在发布镜像时,Fornax还会在发布的同时给构建镜像的提交打上一个标签,这同样需要版本管理系统管理模块支持。 68 | 69 | Docker管理模块,是在构建和发布镜像时使用到的模块,Docker管理模块会与Docker Host进行交互,借由此来完成镜像的构建和发布。在目前的设计中,构建版本与服务时,对于Docker的依赖只限于构建镜像,和发布镜像,在持续集成环节中,还包括为每次持续集成构建隔离的网络环境等,这会在介绍持续集成管理模块时阐述。 70 | 71 | Docker后台管理模块,是为了实现Fornax分布式的非功能性需求而实现的一个模块。在请求量比较大的时候,单个Docker Host必然没有办法满足Fornax的构建需要,因此引入了这样一个模块。该模块的职责是连接多个Docker Host进行构建,值得一提的是,该模块只有在定义了某些环境变量时才会被使用,默认情况下会使用一个Docker Host作为Docker的支持进行运行,这样设计是为了开发时的方便。 72 | 73 | 持续集成管理模块,是负责根据用户的仓库以及配置文件进行持续集成的模块。在Fornax中,持续集成是在容器内进行的。在一次持续集成中,Fornax会根据用户的配置,将用户自定义的持续集成以一个容器的方式运行起来。如果用户的代码存在运行时依赖,比如会依赖一个关系型数据库,Fornax也会支持通过容器方式先将用户在配置文件中定义好的依赖运行,再去运行用户自定义的持续集成的方式。依赖的容器和持续集成本身所在的容器通过自定义的网络环境相互连接,确保在一次持续集成任务中,容器间可以相互通信的同时,不会出现不同的持续集成任务之间容器可以相互沟通的问题,这是出于安全性的考量。持续集成管理模块,只有在存在配置文件,而且用户在配置文件中定义了相关持续集成阶段的配置时,才会被使用。 74 | 75 | 而日志模块,是相对独立的一个模块。它实现了一个基于WebSocket的协议,能够实时地将在各个阶段的日志推送给客户端。同时为了实现日志的持久化存储,引入了Kafka。具体实现的协议会在后文中进行更为详细的介绍。通过日志模块,用户可以在客户端看到每个阶段中所产生的日志。 76 | 77 | 最后,数据库模块,是对于数据库操作的封装。在API模块中,创建服务和版本都会向异步事件处理模块发送一个异步事件,而除此之外的所有操作,都只是单纯地通过对数据库的操作来完成。Fornax的数据库为MongoDB,是一个非关系型的数据库。因为服务与版本,都是非常灵活的模型。而为了满足这样的灵活性,非关系型数据库是比较好的选择,而MongoDB作为目前比较主流的生产可用的非关系型数据库,最终被采用。 78 | 79 | 上述八个模块,构成了Fornax。在第\ref{chap:detail}章中,会逐个介绍每个模块使用到的具体技术。 80 | -------------------------------------------------------------------------------- /tex/intro.tex: -------------------------------------------------------------------------------- 1 | %# -*- coding: utf-8-unix -*- 2 | %%================================================== 3 | %% intro.tex for SJTU Master Thesis 4 | %%================================================== 5 | 6 | %\bibliographystyle{sjtu2}%[此处用于每章都生产参考文献] 7 | \chapter{绪论} 8 | \label{chap:intro} 9 | 10 | 本章是课题的绪论部分。在本章节中,首先介绍了课题的实际背景,之后总结了课题的研究目的与研究意义,并对国内外对于本次课题相关的研究现状进行了分析。最后介绍了本次课题研究的主要内容。 11 | 12 | \section{课题背景} 13 | 14 | 目前,容器虚拟化的风潮正在席卷全球。容器虚拟化,又被称作操作系统级别的虚拟化。是指操作系统的内核允许多个相互隔离的用户态进程同时执行,这些用户进程会被称为容器,它们共享一个操作系统内核。这样的技术在2000年左右就出现了,比如FreeBSD jail,Virtuozzo等等都是操作系统级别的虚拟化工具。但是容器虚拟化最近才渐渐地变得广为人知,是因为Docker在2013年的发布。Docker是由PAAS服务商DotCloud实现的开源容器工具,其很好地解决了容器的构建,落地和运行的全流程,采用了很多对开发友好的技术使得容器虚拟化变得更加易用。 15 | 16 | 因为容器虚拟化技术重新进入业界的视野,整个世界的软件企业,都或多或少受到了容器技术的影响。在容器的影响下,很多经典的软件工程的概念都有了新的内涵与实现。在软件开发过程中,版本的管理与发布是一个非常值得讨论的话题。其中版本管理是指对于文件的修改可以被记录,而且可以在合适的时候进行回滚的技术,是对于文件的修改记录进行管理与控制的过程。而软件的版本发布,可以被理解为当软件的全部或者部分特性可以被交付时,进行的对软件进行发包并发布的过程。在目前的软件开发流程中,软件的过程往往是迭代的。项目组的成员会针对具体的需求规约,将软件需要实现的功能划分,迭代地去完成,而不再是如同传统的瀑布流开发过程,在软件功能全部实现后才会发布一个新版本。这样的变化就对版本管理与发布有了新的要求,要求版本的管理与发布要是持续的过程。于是持续集成与持续部署的概念就应运而生。 17 | 18 | 持续集成,是一种软件工程中的实践,是指持续性地将所有开发者的代码合并到一个主要的分支中的过程。其目的是为了防止软件中因为代码集成而可能造成的问题。其概念最早是由Grady Booch在1991年提出。\cite{Booch}后来持续集成作为一种实践被引入XP敏捷过程中,目前持续集成已经越来越被业界认为是软件工程中保证代码质量与交付可靠性的一种必要实践。持续集成带来的好处是显而易见的,它使得软件测试时间提前了,融入到了每次代码的改动中。同时为持续部署提供了可能性,同时也降低代码复查的时间。因此很多版本控制与发布的网站,诸如Github,Gitlab等都提供了对持续集成的支持。持续集成的概念也不再仅限于敏捷过程中。 19 | 20 | 而持续部署,是一个为了解决软件发布引起的问题而提出的概念。持续部署是持续集成的一种扩展,指持续性地将代码部署到生产环境中的过程。在传统的软件过程中,软件的发布是非常繁杂而且易错的事情。因为在发布的过程中,涉及到对代码的打包,运行时环境的依赖以及配置管理等等。所以在传统的发布过程中,是耗时耗力的。而持续部署,就是希望能够降低发布新版本带来的额外成本,使得发布不再是一个高成本的过程。\cite{CruiseControls} 21 | 22 | 因为持续集成与持续部署,都涉及到环境的隔离等,因此在容器虚拟化技术出现之前,持续集成与持续部署往往是采用虚拟机,或自定义的隔离手段来实现每次集成与部署之间的资源隔离。而在容器虚拟化技术走向成熟后,持续集成与持续部署也有了新的一种实现手段。 23 | 24 | 容器虚拟化技术,不仅对于持续集成与持续部署的内涵有了新的定义,也因此应运而生了基于容器的机器集群。在真实的环境中,单个服务器往往是不能保证服务的可用性的,所以往往会引入多台服务器,而这就会涉及到集群管理的技术。通过使用集群的方式,引入更多的冗余资源来保证服务的可用性,是目前比较常用的手段。而在容器虚拟化技术出现之前,业界通常会采用Mesos或者其他的集群管理工具,来调度集群上的任务,来保证在尽量不浪费集群的计算能力的同时做到高可用。而这样的集群管理工具管理的单元往往是虚拟机,相较于容器而言,虽然有着更好的隔离性,但却不如容器灵活。而随着谷歌关于其容器集群管理工具的论文发表\cite{Borg},原本的集群管理工具也开始拥抱容器。容器所具有的灵活,轻量的特点,使得它天然契合生产环境中的某些应用场景。 25 | 26 | \section{Docker容器技术} 27 | 28 | Docker是一个开源的容器虚拟化工具,它可以帮助开发者便捷地进行容器的构建,发布,与运行。本部分将从容器技术本身,Docker的核心概念,以及Docker的架构,相比于其他容器的工具而言的优势四个部分来介绍Docker这一容器虚拟化工具。 29 | 30 | \subsection{容器虚拟化技术概览} 31 | 32 | \begin{figure}[!htp] 33 | \centering 34 | \includegraphics[width=0.4\textwidth]{tech/vm.png} 35 | \caption{传统虚拟化技术示意图} 36 | \label{fig:vm} 37 | \end{figure} 38 | 39 | 容器虚拟化技术并不是一个最近才出现的新技术,而是在2000年左右就已经有不少应用的虚拟化手段。 40 | 41 | 在容器虚拟化技术之前,比较常用的虚拟化工具有Xen,VMware等等。这些虚拟化工具都是属于Application Binary Interface级别的虚拟化,这样的虚拟化技术允许多个操作系统同时运行在同一套硬件上。这样的实现方式往往需要一个Virtual Machine Monitor,或者称作VMM的系统,来将硬件资源进行虚拟化,将虚拟机运行在虚拟化后的设备上。 42 | 43 | 而容器虚拟化技术是属于Application Programming Interface级别的虚拟化,每一个虚拟机,也被称为容器,只是操作系统上的一个进程,与普通的进程不同,容器使用namespace等等方式来将资源隔离,使得进程之间互相不感知。\cite{soltesz2007container} 44 | 45 | 相比于传统的虚拟化方式,容器虚拟化更加轻量,启动和销毁的速度快,资源消耗少。但与此同时,容器虚拟化也存在一些问题,首先是使用容器虚拟化的技术虚拟出来的容器,共用操作系统的内核。因此如果容器内导致了内核崩溃,那会影响到其他的容器。而使用Xen等技术,一个虚拟机的崩溃对于其他虚拟机而言,不会有任何影响。\cite{dua2014virtualization} 46 | 47 | \subsection{Docker的核心概念} 48 | 49 | Docker是目前被广泛接受的一种容器虚拟化工具,其有着其他容器虚拟化工具所不具备的一些优势。Docker原本是DotCloud公司的一个内部项目,DotCloud是一个专注于平台即服务的创业公司。在2013年3月13日,Docker发布了它的开源版本。它使用了内核中的lxc作为其容器的支持,同时还使用了内核中的cgroups和namespace的特性,因此需要内核支持。在Docker开源后,因为其便捷和高效的特性,受到了开发者的欢迎。在最初的版本中,Docker的网络等方面还不是特别的完善,但是Docker由DotCloud公司进行积极的开发和维护,在2014年的0.9版本中,Docker移除了lxc的依赖,直接与内核中的特性进行交互。并且亚马逊、IBM、微软Azure等等国际云服务提供商纷纷表示将整合Docker技术到其云计算产品中,一时之间Docker成为了云计算领域的热词。截止至2016年5月16日,Docker在Github上收获了31256个关注(Star),成为了Github上最受欢迎的项目之一。 50 | 51 | \begin{figure}[!htp] 52 | \centering 53 | \includegraphics[width=0.4\textwidth]{tech/container.png} 54 | \caption{Docker示意图} 55 | \label{fig:container} 56 | \end{figure} 57 | 58 | 如图\ref{fig:container}所示,Docker不同于传统的虚拟化技术,每一个容器包含其运行时需要的所有依赖以及应用,但并不需要一个虚拟机来提供支持,每一个Docker容器只是一个运行在独立的namespace下的受到隔离的进程。与此同时,Docker容器不会跟下层的操作系统相耦合,它们可以运行在所有支持Docker Engine的机器或者云上。 59 | 60 | Docker中比较重要的两个概念分别是镜像和容器,这是Docker最主要的两个实体概念。镜像是Docker的一个特色,镜像是一个只读的模板,在启动容器时被加载。镜像在存储方面,采取了联合文件系统。联合文件系统允许系统的文件和目录以分层的方式存储,而对于操作系统而言,其使用的文件系统是分层叠加之后的结果。这样使得镜像的存储变得更加方便,可以将不同的文件分层并行地进行上传或下载。而且当对镜像进行修改时,只需要对修改之后的文件分层进行添加或者修改即可,而不需要替换掉整个镜像。而Docker通过定义了一系列操作,将镜像的构建进行了标准化,使得用户只需要通过简单地操作,即可构建出满足自己需要的镜像。\cite{mayue} 61 | 62 | 而容器则是镜像的运行时,镜像为容器提供了启动的环境,而容器则与常规的容器虚拟化技术中的容器概念一致,是一个隔离的进程。因为Docker的镜像是一个只读的模板,其所有的文件分层都是设置为只读的,因此当从一个镜像运行起一个容器时,Docker会在镜像的最上层添加一个可读可写的新的文件分层。在新的文件分层中对于文件系统的修改,会覆盖原本的镜像。这样就使得容器看起来运行在镜像之上,而并不会因为容器的运行修改镜像的内容。 63 | 64 | \subsection{Docker的架构} 65 | 66 | \begin{figure}[!htp] 67 | \centering 68 | \includegraphics[width=\textwidth]{tech/architecture.png} 69 | \caption{Docker架构图} 70 | \label{fig:architecture} 71 | \end{figure} 72 | 73 | 如图\ref{fig:architecture}所示,Docker采取了客户端-服务器的架构。其中比较重要的组件有Docker Daemon,Docker Client,Docker Registry三个,下面将从镜像和容器的生命周期角度,对Docker的架构进行介绍。 74 | 75 | Docker Daemon,是运行在服务器端的后台程序。其承担了基本所有的操作,包括本地镜像和容器的管理,与远端的Docker Registry的交互等等。但用户并不直接与Docker Daemon交互,而是通过Docker Client。Docker Client是一个Cli程序,为用户提供了抽象度很高的命令,通过Docker Client,用户可以与Docker的服务器进行交互,进而管理容器和镜像。而Docker Registry是管理镜像的存储组件,用户可以将构建好的镜像推送至Docker Registry中,而通过Docker Client,用户可以对Docker Registry上的镜像进行简单的搜索,寻找适合自己应用场景的镜像,并拉取使用。 76 | 77 | Docker有一系列优秀的特性。首先,作为一个容器虚拟化工具,它允许用户创建Docker容器,并且利用iptable等等特性,解决了容器与容器之间互相连接的问题。同时,Docker允许构建镜像,并且可以将镜像推送给远端的Registry,这使得一次构建,多次运行的想法成为了现实。而且Docker的Registry允许多租户,通过类似Github的方式来进行组织与构建,使得Docker在生产环境的使用成为了可能。 78 | 79 | 除此之外,Docker的成功也离不开其强大的生态环境。围绕着Docker,有一系列工具和技术覆盖了当下很多领域的难题。首先,Docker周边有非常多为了降低Docker的使用门槛的工具,比如Docker Machine等。原本因为容器虚拟化技术需要依赖Linux内核的某些特性,使得其他系统的用户不能使用Docker来构建容器,但是Docker Machine会在非Linux环境下运行一个Linux虚拟机,将Docker运行在该虚拟机上,这抹平了Docker对内核的要求,使得其他系统的用户也可以自如地使用Docker来构建容器,目前Docker正在积极基于OS X的新特性积极地进行对OS X系统的原生支持,这对于OS X系统的用户而言是一大利好。其次,Docker跨平台的特性,使得企业的混合云部署变成了现实。面对当下异构的机器和网络环境,Docker能够更好地发挥其特性。除此之外,在持续集成与持续部署方面,Docker非常用来做环境的隔离,执行构建任务。Drone等工具就是专注于该领域的,基于Docker来实现的工具。 80 | 81 | \section{国内外课题相关研究现状} 82 | 83 | 在容器虚拟化技术出现后,基于容器的持续集成工具也随之产生。Drone是一个在Github上开源的,使用golang实现的基于Docker的持续集成工具,它的目标是取代Jenkins成为新一代的持续集成工具。相比于Jenkins,Drone本身更加简洁,而且同样有丰富的插件支持。Drone更加倾向简洁,专一的设计,Drone的实现中没有调度的概念,而鼓励用户通过cron等工具的方式来实现定时触发构建任务等功能。而且Drone使用Docker容器来进行构建并执行用户定义的脚本,将进行资源隔离的方式和手段与持续集成工具本身解耦,相比Jenkins而言有着更先进的实现以及更加活跃的社区。目前Drone在Github上已经收获了六千多个关注,其受欢迎程度由此可见一斑。 84 | 85 | 而对于持续部署而言,业界采取的方式相对统一,是将继续部署与持续集成结合在一起去完成的。在持续集成完成后,如果确认代码变动没有问题,就将代码自动化地部署到服务器上。以Drone为例,它对于部署的实现方式是允许用户在持续集成后,根据集成测试的结果来决定是否将新的变动发布到生产服务器上。 86 | 87 | \section{研究的目的与内容} 88 | 89 | 本文希望能够结合容器虚拟化技术与版本管理与控制的技术,实现一个基于容器虚拟化技术和容器集群技术的版本管理与发布系统Fornax(以下统一称为Fornax),使得用户能够在容器集群上进行代码的版本管理与发布。 90 | 91 | Fornax的目的在于方便使用容器集群的开发者的开发过程,使得开发者在不感知底层容器集群的行为的情况下,完成应用的持续集成与持续部署。在遇到问题需要回滚或者升级时,也可以通过Fornax来进行相应操作。开发者只需要关注业务逻辑的开发,由Fornax完成部分冗杂的运维操作。 92 | 93 | Fornax希望能够实现三个主要特性:对于代码的持续集成,对于应用的持续部署持续发布,以及对于用户应用的版本管理。 94 | 95 | 在容器虚拟化技术出现之前,对于应用的版本管理只需要使用git等工具,保证对于代码的每次修改都被记录下来并且可回滚即可,而在容器虚拟化技术出现之后,对于一个容器化的应用而言,不仅需要对代码进行版本管理,也需要对容器的镜像进行管理。Fornax希望能够将每次可运行的代码,打包为一个容器镜像,并且对镜像如同代码一样进行版本管理。这样不仅可以保证在发布出现问题时,更好地对代码和运行环境进行回滚,而且也可以使得发布环境可追溯。 96 | 97 | 在持续集成方面,Fornax希望支持根据每次代码的变动来自动地发起一次集成。每当代码发生了变动时,Fornax会检查配置文件中关于持续集成的配置与设定,来根据用户自定义的脚本来发起一次集成,并将集成的日志和结果持久化地记录下来。在持续集成时,会使用容器技术来保证集成时的环境隔离。同时,对于在运行时的依赖,Fornax也希望通过容器的方式来给予支持。\cite{wangfei, zhangjian} 98 | 99 | 在持续部署方面,Fornax希望可以基于Kubernetes容器集群进行实现。Kubernetes是一个基于Docker的容器管理工具,由谷歌开源,因为谷歌在2015年发布的论文\cite{Borg}而被人所知。不同于其他的集群管理工具,它将一个或多个容器的组合作为基本的调度单位。Fornax希望基于Kubernetes进行对于用户的应用的持续部署与持续发布。每当用户代码的集成测试结束后,会根据持续集成的结果来进行相应的代码部署,用户可以在配置文件中关于持续部署的设定中写明代码部署对应的集群等。 100 | 101 | Fornax主要的功能是以上三点,而除此之外,还有一些非功能的要求。首先,因为Fornax面临的环境可能是异构的,可能会部署在公有云、私有云或者是混合云上,因此Fornax需要是可配置的,而且应该支持跨平台。在不同的环境上都可以为用户提供服务。除此之外,因为不同的用户对于持续集成和持续部署的要求与使用方法都是不同的,因此,在Fornax的实现上,要允许用户自定义在持续集成等环节的行为。 102 | 103 | \section{论文结构} 104 | 105 | 本文一共由五章组成。 106 | 107 | 其中第一章为绪论部分,主要介绍了本文的研究背景,有关持续集成、持续部署在工业界的情况,容器虚拟化技术的相关研究分析以及本文的研究目的与内容。 108 | 109 | 第二章对Fornax进行了总览性的介绍。首先从需求方面对Fornax进行了分析,明确了Fornax要实现的功能,接下来对Fornax的实现架构进行了阐述,并说明确定以这样的架构实现的原因。 110 | 111 | 第三章详细阐述了Fornax的具体实现。其中详细介绍了对于实现难度比较大的两个模块:持续集成模块与日志模块。并在对各个模块的实现分析中,分析了采取这样的实现方式的原因。 112 | 113 | 第四章是验证与测试部分。在该部分中介绍了Fornax的测试架构与分布式部署的探索。 114 | 115 | 第五章是总结部分,在该部分中总结了本文做的主要工作,以及在之后Fornax需要继续完善的问题。 -------------------------------------------------------------------------------- /tex/patents.tex: -------------------------------------------------------------------------------- 1 | %# -*- coding: utf-8-unix -*- 2 | \begin{patents}{99} 3 | \item 第一发明人,“永动机”,专利申请号202510149890.0 4 | \end{patents} 5 | -------------------------------------------------------------------------------- /tex/projects.tex: -------------------------------------------------------------------------------- 1 | %# -*- coding: utf-8-unix -*- 2 | %%================================================== 3 | %% projects.tex for SJTUThesis 4 | %% Encoding: UTF-8 5 | %%================================================== 6 | 7 | \begin{projects}{99} 8 | \item 973项目“XXX” 9 | \item 自然基金项目“XXX” 10 | \item 国防项目“XXX” 11 | \end{projects} 12 | -------------------------------------------------------------------------------- /tex/projectsreview.tex: -------------------------------------------------------------------------------- 1 | %# -*- coding: utf-8-unix -*- 2 | 3 | \begin{projects}{99} 4 | \item 参与973项目子课题(2007年6月--2008年5月) 5 | \item 参与自然基金项目(2005年5月--2005年8月) 6 | \item 参与国防项目(2005年8月--2005年10月) 7 | \end{projects} 8 | -------------------------------------------------------------------------------- /tex/pub.tex: -------------------------------------------------------------------------------- 1 | %# -*- coding: utf-8-unix -*- 2 | %%================================================== 3 | %% pub.tex for SJTUThesis 4 | %% Encoding: UTF-8 5 | %%================================================== 6 | 7 | \begin{publications}{99} 8 | \item\textsc{Chen H, Chan C~T}. {Acoustic cloaking in three dimensions using acoustic metamaterials}[J]. Applied Physics Letters, 2007, 91:183518. 9 | \item\textsc{Chen H, Wu B~I, Zhang B}, et al. {Electromagnetic Wave Interactions with a Metamaterial Cloak}[J]. Physical Review Letters, 2007, 99(6):63903. 10 | \end{publications} 11 | -------------------------------------------------------------------------------- /tex/pubreview.tex: -------------------------------------------------------------------------------- 1 | %# -*- coding: utf-8-unix -*- 2 | 3 | \begin{publications}{99} 4 | \item\textsc{第一作者}. {中文核心期刊论文}, 2007. 5 | \item\textsc{第一作者}. {EI国际会议论文}, 2006. 6 | \end{publications} 7 | -------------------------------------------------------------------------------- /tex/req.tex: -------------------------------------------------------------------------------- 1 | %# -*- coding: utf-8-unix -*- 2 | %%================================================== 3 | %% req.tex for SJTU Master Thesis 4 | %%================================================== 5 | 6 | %\bibliographystyle{sjtu2}%[此处用于每章都生产参考文献] 7 | \chapter{需求分析} 8 | \label{chap:req} 9 | 10 | -------------------------------------------------------------------------------- /tex/summary.tex: -------------------------------------------------------------------------------- 1 | %# -*- coding: utf-8-unix -*- 2 | %%================================================== 3 | %% conclusion.tex for SJTUThesis 4 | %% Encoding: UTF-8 5 | %%================================================== 6 | 7 | \chapter{总结与展望} 8 | 9 | 本部分总结了Fornax目前已经完成的工作,并对Fornax的未来进行了展望。 10 | 11 | \section{工作总结} 12 | 13 | 本文基于容器技术和容器集群技术,实现了一个用于版本管理与发布的系统,名为Fornax。通过Fornax,用户可以对自己的代码进行持续集成,并且在持续集成结束后,将代码打包成容器镜像的格式,上传至远端的仓库。在部署时,可以通过Fornax的持续部署,根据新打包的镜像直接在指定的集群上运行容器。同时,Fornax允许用户在构建镜像时定义自己的操作,使得可以在打包镜像的同时时完成用户定义的逻辑。 14 | 15 | 并且Fornax在实现时使用了容器虚拟化技术来进行构建任务之间的隔离。一次构建任务由一个或多个容器完成,容器间通过网络互连,而不同构建任务之间的容器之间互相不感知。同时Fornax是一个异步的、无状态的服务,因此通过第三方的负载均衡器的代理,可以实现分布式部署,提高Fornax的吞吐量以及可用性。 16 | 17 | 在最后,课题针对Fornax的功能进行了端到端的测试,测试覆盖了Fornax的全部正常工作流与一些异常流。通过测试的方式来验证Fornax的功能符合规约,同时证明功能实现的完整性。 18 | 19 | \section{未来的工作} 20 | 21 | Fornax的代码托管在Github上,而在Github的问题页面,已经积累了大大小小四十多个有关Fornax的问题,其中有优化,也有因为Bug而导致的问题。由此可见目前Fornax还不是非常完善,有很多工作需要未来一点点去完成。下面将从几个需要关注的方面着手,展望Fornax未来需要解决的问题。 22 | 23 | 首先是关于日志模块,在日志推送时,因为最开始使用了本地存储的方式,所以在后续引入Kafka来将日志推送至分布式消息中间件的实现中仍然有本地存储的依赖。目前每多一个构建请求,都要创建一个线程去监听本地日志文件的变化,然后将其推送给Kafka。后续应该调研是否仍然有必要使用本地存储,是否可以直接将日志推送至Kafka消息中间件中。这样可以节省很多的处理器资源。 24 | 25 | 其次是关于持续集成模块,在目前,虽然持续集成已经可以进行,但是还存在一些问题。比如,在构建失败时,有可能因为路径问题而没有回收构建时产生的垃圾。另外,目前对于用户所使用的硬件资源并没有作出限制。当用户在一次构建中创建出过多容器占用了整个机器的硬件资源时,会影响其他构建任务的执行。而为了解决这一问题,需要比较大的改造。对于用户占用资源的控制,可以分为三个维度,分别是对容器的资源限制,对构建任务的资源限制,和对用户的资源限制。对容器的资源限制是指要限定每个容器可以使用的硬件资源,这由内核的特性提供支持。内核中的cgroup和namespace特性使得这不需要Fornax实现。而对于构建任务的资源限制是指在一次构建中所启动的所有容器使用的硬件资源的总和应该进行限制。对于用户的资源限制,是指用户的多次构建任务所占用的硬件资源的总和也应该予以限制。三个维度的资源限制都是有必要的,而目前Fornax只能做到第一个维度的限制。对于第二个维度的限制,需要Fornax维护构建任务中所有容器的信息,并实时地进行计算。而对于第三个维度的限制,则相对比较困难,需要将用户的构建信息写入数据库,来进行判断。 26 | 27 | 类似这样的问题还有诸如在一次请求中数据库访问次数过多,以及用户校验以及鉴权等等。这些问题都是未来Fornax需要解决的问题。 -------------------------------------------------------------------------------- /tex/symbol.tex: -------------------------------------------------------------------------------- 1 | %# -*- coding: utf-8-unix -*- 2 | \chapter{主要符号对照表} 3 | \label{chap:symb} 4 | 5 | \begin{longtable}{rl} 6 | % $\epsilon$ & 介电常数 \\ 7 | % $\mu$ & 磁导率 \\ 8 | % $\epsilon$ & 介电常数 \\ 9 | % $\mu$ & 磁导率 \\ 10 | % $\epsilon$ & 介电常数 \\ 11 | % $\mu$ & 磁导率 \\ 12 | % $\epsilon$ & 介电常数 \\ 13 | % $\mu$ & 磁导率 \\ 14 | % $\epsilon$ & 介电常数 \\ 15 | % $\mu$ & 磁导率 \\ 16 | % $\epsilon$ & 介电常数 \\ 17 | % $\mu$ & 磁导率 \\ 18 | % $\epsilon$ & 介电常数 \\ 19 | % $\mu$ & 磁导率 \\ 20 | % $\epsilon$ & 介电常数 \\ 21 | % $\mu$ & 磁导率 \\ 22 | % $\epsilon$ & 介电常数 \\ 23 | % $\mu$ & 磁导率 \\ 24 | % $\epsilon$ & 介电常数 \\ 25 | % $\mu$ & 磁导率 \\ 26 | % $\epsilon$ & 介电常数 \\ 27 | % $\mu$ & 磁导率 \\ 28 | % $\epsilon$ & 介电常数 \\ 29 | % $\mu$ & 磁导率 \\ 30 | % $\epsilon$ & 介电常数 \\ 31 | % $\mu$ & 磁导率 \\ 32 | % $\epsilon$ & 介电常数 \\ 33 | % $\mu$ & 磁导率 \\ 34 | % $\epsilon$ & 介电常数 \\ 35 | % $\mu$ & 磁导率 \\ 36 | % $\epsilon$ & 介电常数 \\ 37 | % $\mu$ & 磁导率 \\ 38 | % $\epsilon$ & 介电常数 \\ 39 | % $\mu$ & 磁导率 \\ 40 | % $\epsilon$ & 介电常数 \\ 41 | % $\mu$ & 磁导率 \\ 42 | % $\epsilon$ & 介电常数 \\ 43 | % $\mu$ & 磁导率 \\ 44 | % $\epsilon$ & 介电常数 \\ 45 | % $\mu$ & 磁导率 \\ 46 | % $\epsilon$ & 介电常数 \\ 47 | % $\mu$ & 磁导率 \\ 48 | % $\epsilon$ & 介电常数 \\ 49 | % $\mu$ & 磁导率 \\ 50 | % $\epsilon$ & 介电常数 \\ 51 | % $\mu$ & 磁导率 \\ 52 | % $\epsilon$ & 介电常数 \\ 53 | % $\mu$ & 磁导率 \\ 54 | % $\epsilon$ & 介电常数 \\ 55 | % $\mu$ & 磁导率 \\ 56 | % $\epsilon$ & 介电常数 \\ 57 | % $\mu$ & 磁导率 \\ 58 | % $\epsilon$ & 介电常数 \\ 59 | % $\mu$ & 磁导率 \\ 60 | \end{longtable} 61 | -------------------------------------------------------------------------------- /tex/tech.tex: -------------------------------------------------------------------------------- 1 | %# -*- coding: utf-8-unix -*- 2 | %%================================================== 3 | %% tech.tex for SJTU Master Thesis 4 | %%================================================== 5 | 6 | %\bibliographystyle{sjtu2}%[此处用于每章都生产参考文献] 7 | \chapter{相关技术分析} 8 | \label{chap:tech} 9 | 10 | 本章主要介绍了Fornax使用到的技术与工具,其中包括但不限于Docker,Kubernetes。Docker是目前较为流行的容器虚拟化工具,相比于其他的工具,Docker解决了容器从打包,存放,与运行的全流程问题,因此被广为接受,Fornax使用Docker来进行构建环境的搭建与隔离。Kubernetes是由谷歌开源的容器集群管理工具,Fornax基于该工具来进行持续部署。 11 | 12 | \section{Docker容器技术} 13 | 14 | Docker是一个开源的容器虚拟化工具,它可以帮助开发者便捷地进行容器的构建,发布,与运行。本部分将从容器技术本身,Docker的核心概念,以及Docker的架构,相比于其他容器的工具而言的优势四个部分来介绍Docker这一容器虚拟化工具。 15 | 16 | \subsection{容器虚拟化技术概览} 17 | 18 | \begin{figure}[!htp] 19 | \centering 20 | \includegraphics[width=0.4\textwidth]{tech/vm.png} 21 | \bicaption[fig:vm]{传统虚拟化技术示意图}{传统虚拟化技术示意图}{Fig}{} 22 | \end{figure} 23 | 24 | 容器虚拟化技术并不是一个最近才出现的新技术,而是在2000年左右就已经有不少应用的虚拟化手段。 25 | 26 | 在容器虚拟化技术之前,比较常用的虚拟化工具有Xen,VMware等等。这些虚拟化工具都是属于Application Binary Interface级别的虚拟化,这样的虚拟化技术允许多个操作系统同时运行在同一套硬件上。这样的实现方式往往需要一个Virtual Machine Monitor,或者称作VMM的系统,来将硬件资源进行虚拟化,将虚拟机运行在虚拟化后的设备上。 27 | 28 | 而容器虚拟化技术是属于Application Programming Interface级别的虚拟化,每一个虚拟机,也被称为容器,只是操作系统上的一个进程,与普通的进程不同,容器使用namespace等等方式来将资源隔离,使得进程之间互相不感知。\cite{soltesz2007container} 29 | 30 | 相比于传统的虚拟化方式,容器虚拟化更加轻量,启动和销毁的速度快,资源消耗少。但与此同时,容器虚拟化也存在一些问题,首先是使用容器虚拟化的技术虚拟出来的容器,共用操作系统的内核。因此如果容器内导致了内核崩溃,那会影响到其他的容器。而使用Xen等技术,一个虚拟机的崩溃对于其他虚拟机而言,不会有任何影响。\cite{dua2014virtualization} 31 | 32 | \subsection{Docker的核心概念} 33 | 34 | Docker是目前被广泛接受的一种容器虚拟化工具,其有着其他容器虚拟化工具所不具备的一些优势。Docker原本是DotCloud公司的一个内部项目,DotCloud是一个专注于平台即服务的创业公司。在2013年3月13日,Docker发布了它的开源版本。它使用了内核中的lxc作为其容器的支持,同时还使用了内核中的cgroups和namespace的特性,因此需要内核支持。在Docker开源后,因为其便捷和高效的特性,受到了开发者的欢迎。在最初的版本中,Docker的网络等方面还不是特别的完善,但是Docker由DotCloud公司进行积极的开发和维护,在2014年的0.9版本中,Docker移除了lxc的依赖,直接与内核中的特性进行交互。并且亚马逊、IBM、微软Azure等等国际云服务提供商纷纷表示将整合Docker技术到其云计算产品中,一时之间Docker成为了云计算领域的热词。截止至2016年5月16日,Docker在Github上收获了31256个关注(Star),成为了Github上最受欢迎的项目之一。 35 | 36 | \begin{figure}[!htp] 37 | \centering 38 | \includegraphics[width=0.4\textwidth]{tech/container.png} 39 | \bicaption[fig:container]{Docker示意图}{Docker示意图}{Fig}{} 40 | \end{figure} 41 | 42 | 如图\ref{fig:container}所示,Docker不同于传统的虚拟化技术,每一个容器包含其运行时需要的所有依赖以及应用,但并不需要一个虚拟机来提供支持,每一个Docker容器只是一个运行在独立的namespace下的受到隔离的进程。与此同时,Docker容器不会跟下层的操作系统相耦合,它们可以运行在所有支持Docker Engine的机器或者云上。 43 | 44 | Docker中比较重要的两个概念分别是镜像和容器,这是Docker最主要的两个实体概念。镜像是Docker的一个特色,镜像是一个只读的模板,在启动容器时被加载。镜像在存储方面,采取了联合文件系统。联合文件系统允许系统的文件和目录以分层的方式存储,而对于操作系统而言,其使用的文件系统是分层叠加之后的结果。这样使得镜像的存储变得更加方便,可以将不同的文件分层并行地进行上传或下载。而且当对镜像进行修改时,只需要对修改之后的文件分层进行添加或者修改即可,而不需要替换掉整个镜像。而Docker通过定义了一系列操作,将镜像的构建进行了标准化,使得用户只需要通过简单地操作,即可构建出满足自己需要的镜像。 45 | 46 | 而容器则是镜像的运行时,镜像为容器提供了启动的环境,而容器则与常规的容器虚拟化技术中的容器概念一致,是一个隔离的进程。因为Docker的镜像是一个只读的模板,其所有的文件分层都是设置为只读的,因此当从一个镜像运行起一个容器时,Docker会在镜像的最上层添加一个可读可写的新的文件分层。在新的文件分层中对于文件系统的修改,会覆盖原本的镜像。这样就使得容器看起来运行在镜像之上,而并不会因为容器的运行修改镜像的内容。 47 | 48 | \subsection{Docker的架构} 49 | 50 | \begin{figure}[!htp] 51 | \centering 52 | \includegraphics[width=\textwidth]{tech/architecture.png} 53 | \bicaption[fig:architecture]{Docker架构图}{Docker架构图}{Fig}{} 54 | \end{figure} 55 | 56 | 如图\ref{fig:architecture}所示,Docker采取了客户端-服务器的架构。其中比较重要的组件有Docker Daemon,Docker Client,Docker Registry三个,下面将从镜像和容器的生命周期角度,对Docker的架构进行介绍。 57 | 58 | Docker Daemon,是运行在服务器端的后台程序。其承担了基本所有的操作,包括本地镜像和容器的管理,与远端的Docker Registry的交互等等。但用户并不直接与Docker Daemon交互,而是通过Docker Client。Docker Client是一个Cli程序,为用户提供了抽象度很高的命令,通过Docker Client,用户可以与Docker的服务器进行交互,进而管理容器和镜像。而Docker Registry是管理镜像的存储组件,用户可以将构建好的镜像推送至Docker Registry中,而通过Docker Client,用户可以对Docker Registry上的镜像进行简单的搜索,寻找适合自己应用场景的镜像,并拉取使用。 59 | 60 | \subsection{Docker的优势} 61 | 62 | Docker有一系列优秀的特性。首先,作为一个容器虚拟化工具,它允许用户创建Docker容器,并且利用iptable等等特性,解决了容器与容器之间互相连接的问题。同时,Docker允许构建镜像,并且可以将镜像推送给远端的Registry,这使得一次构建,多次运行的想法成为了现实。而且Docker的Registry允许多租户,通过类似Github的方式来进行组织与构建,使得Docker在生产环境的使用成为了可能。 63 | 64 | 除此之外,Docker的成功也离不开其强大的生态环境。围绕着Docker,有一系列工具和技术覆盖了当下很多领域的难题。首先,Docker周边有非常多为了降低Docker的使用门槛的工具,比如Docker Machine等。原本因为容器虚拟化技术需要依赖Linux内核的某些特性,使得其他系统的用户不能使用Docker来构建容器,但是Docker Machine会在非Linux环境下运行一个Linux虚拟机,将Docker运行在该虚拟机上,这抹平了Docker对内核的要求,使得其他系统的用户也可以自如地使用Docker来构建容器,目前Docker正在积极基于OS X的新特性积极地进行对OS X系统的原生支持,这对于OS X系统的用户而言是一大利好。其次,Docker跨平台的特性,使得企业的混合云部署变成了现实。面对当下异构的机器和网络环境,Docker能够更好地发挥其特性。除此之外,在持续集成与持续部署方面,Docker非常用来做环境的隔离,执行构建任务。Drone等工具就是专注于该领域的,基于Docker来实现的工具。 65 | -------------------------------------------------------------------------------- /tex/test.tex: -------------------------------------------------------------------------------- 1 | %# -*- coding: utf-8-unix -*- 2 | %%================================================== 3 | %% test.tex for SJTU Master Thesis 4 | %%================================================== 5 | 6 | %\bibliographystyle{sjtu2}%[此处用于每章都生产参考文献] 7 | \chapter{验证与测试} 8 | \label{chap:test} 9 | 10 | 本章从功能验证和测试的角度阐述了Fornax的功能与性能。并且通过对于同类型产品的比较,对Fornax的特点进行了说明。 11 | 12 | \section{功能性测试} 13 | 14 | 作为着眼于持续集成、持续发布以及版本管理的系统,Fornax对于代码的质量有严格的保证,其具有完善的测试用例,并使用Jenkins作为持续集成工具,对于每次提交进行持续集成测试,在确保不会引入问题时才会将代码合并。目前Fornax在运行时会依赖数据库组件MongoDB和消息中间件Kafka,而Kafka作为开源的消息中间件实现,本身还会依赖分布式协调一致组件Zookeeper。因此,如果要进行端到端测试,需要先将这三个服务运行,Fornax才能被正确地启动。 15 | 16 | \begin{figure}[!htp] 17 | \centering 18 | \includegraphics[width=0.55\textwidth]{test/test.png} 19 | \caption{Fornax测试架构图} 20 | \label{fig:test} 21 | \end{figure} 22 | 23 | 如图\ref{fig:test}所示,Fornax会将Kafka和Zookeeper以Docker容器的方式启动,将数据库启动在本地,除此之外,为了测试版本的推送功能,Fornax需要一个Docker Registry进行验证,而测试的应用场景对于Docker Registry有着不同于平时的需求,其要求Docker Registry的生命周期足够短,在测试结束时不能留下残余垃圾。因此使用公共的或者私有的Docker Registry都不能满足这样的要求,因此在Fornax启动之前,一个私有的Docker Registry会被启动,随之而存在的用以认证的一个服务也会随之启动。这两个服务也是以Docker容器的方式运行的。随后Fornax会被真正地运行,而测试代码是独立于Fornax实例而存在,其本质是模拟Fornax的客户端,对Fornax发起HTTP请求以测试Fornax在行为级别的表现是否满足预期,而针对Fornax的代码,有一些异常路径的测试用例被执行,因此属于端到端的测试,也可以被视为灰盒测试。 24 | 25 | \begin{table}[!hpb] 26 | \centering 27 | \caption{Fornax功能性测试用例} 28 | \label{tab:test} 29 | \begin{tabular}{llll} \toprule 30 | & 测试用例数目 & 主流程覆盖率 & 异常流程覆盖率 \\ \midrule 31 | 服务测试用例 & 11 & 100\% & 87\% \\ 32 | 版本测试用例 & 15 &100\% & 65\% \\ 33 | 持续集成测试用例 & 9 & 100\% & 67\% \\ \bottomrule 34 | \end{tabular} 35 | \end{table} 36 | 37 | 目前如表\ref{tab:test}所示,Fornax中具有35个端到端的测试用例,覆盖了Fornax的全部的主要流程和部分异常流程。Fornax使用行为驱动的测试风格维护这些测试用例,使得在新增用例时代码不会过于膨胀。在35个测试用例中,有11个用例测试有关服务的逻辑,15个用例测试有关版本中构建与发布的逻辑,还有额外的9个用例专门关于给定配置文件后构建版本时的逻辑。因为在创建版本时版本镜像的构建与发布是默认的行为,因此相比于给定配置文件后进行构建的应用场景要更常见一些,所以书写了更多的测试用例。但从代码复杂度而言,给定配置文件后进行构建要比直接构建与发布镜像要复杂许多,因此在之后Fornax会补充更多完善的关于根据配置文件进行构建的测试用例。 38 | 39 | \section{分布式部署} 40 | 41 | Fornax作为一个生产环境可用的版本管理与发布的工具,支持分布式的部署方式。Fornax本身是无状态的,因此在分布式的支持上有很多种选择,而Fornax目前采取的方法是使用了第三方的反向代理工具,对Fornax进行请求的代理。Fornax进行分布式部署的目的在于提高系统的可用性以及请求的吞吐量,使得Fornax能够真正成为一个生产环境可用的工具。 42 | 43 | \begin{figure}[!htp] 44 | \centering 45 | \includegraphics[width=0.55\textwidth]{test/distributed.png} 46 | \caption{Fornax分布式部署} 47 | \label{fig:distributed} 48 | \end{figure} 49 | 50 | 如图\ref{fig:distributed}所示,Fornax在分布式部署中使用到了HAProxy作为反向代理的工具。在结构上主要分为Fornax集群,Kafka集群和Mongo集群。Fornax集群中每个实例的关系是完全对等的,都是无状态的。而Mongo集群和Kafka集群是使用其默认的分布式部署的支持方式进行部署的,它们为多个Fornax的实例提供服务。每当有请求路由到HAProxy时,HAProxy会根据自身的负载均衡策略将请求分发至一个具体的Fornax实例,该实例收到由其路由过来的请求后,会对其进行处理,并将服务,版本等信息存储到数据库集群中,而有关日志的信息会存储到消息中间件集群中。 51 | 52 | 在最开始的设计中,Fornax对于日志的处理上是使用本地文件,而不是消息中间件的方式来实现的。这样的实现方式在将Fornax进行分布式部署的尝试时遇到了问题。使用本地文件来存储日志信息使得Fornax本身不是完全无状态的,这要求对于同一个构建,其相关的请求都要路由到同一个Fornax实例上,因为对于构建的日志是存储在实例所在机器的本地的,而这样的分布式部署并不能真正起到提高可用性的目的。因此在后期的实现中Fornax引入了Kafka的依赖,讲日志也持久化在分布式的消息中间件中,所有的Fornax实例都连接该分布式的消息中间件,因此无论客户端请求在哪个Fornax实例上进行构建任务的日志,任意一个Fornax实例都可以订阅Kafka中的主题,来将日志推送给客户端。这样的实现是的Fornax成为了无状态的服务器,所有需要持久化的数据都下沉到了数据库与消息中间件中。而因为Fornax是无状态的,而且所有的实例都使用同一个数据库集群和消息中间件集群,所以连续的请求不需要路由到同一个实例上,这也是Fornax可以采取这样的分布式架构的主要原因。因为Fornax是无服务的,所以在部署时,Fornax实例是以Docker容器的方式运行的。而反向代理工具HAProxy也是以这样的方式进行部署,这使得Fornax的弹性扩容能力与可用性都相比于传统的部署方式有很大的提高,可以面对未来复杂多变的应用环境。 53 | 54 | 与此同时,Fornax的可配置性好,允许对所有的依赖进行配置,使得依赖由静态变成了动态的过程。同时Docker容器化的部署使得Fornax不感知真实的环境,因此无论是在公有云、私有云亦或是混合云,Fornax都可以进行部署。 55 | 56 | % \section{性能测试} 57 | 58 | \section{代码统计} 59 | 60 | Fornax代码情况使用cloc\cite{cloc}统计,去除了Fornax中对于其他模块的代码依赖。情况如表\ref{tab:code}所示,Fornax的主要功能由go语言实现,其中包括八个核心的模块,以及所有的测试用例,因此go语言的代码占代码总量的大部分。除此之外,Fornax在启动时有很多的运行时依赖,这些依赖的运行以及Fornax的启动都是通过Bourne Shell脚本来完成的,其中包括启动本地的短生命周期的Docker Registry,启动Fornax,执行端到端的测试等内容。 61 | 62 | \begin{table}[!hpb] 63 | \centering 64 | \caption{Fornax代码统计} 65 | \label{tab:code} 66 | \begin{tabular}{lllll} \toprule 67 | 语言 & 文件数 & 注释 & 代码 \\ \midrule 68 | Go & 62 & 1129 & 6671 \\ 69 | Bourne Shell & 15 & 96 & 375 \\ 70 | YAML & 11 & 4 & 249 \\ 71 | HTML & 1 & 0 & 31 \\ 72 | make & 1 & 8 & 12 \\ 73 | 总计 & 90 & 1237 & 7338 \\ \bottomrule 74 | \end{tabular} 75 | \end{table} 76 | 77 | \section{相较于其他工具的优势} 78 | 79 | Fornax关注持续集成与持续部署,版本的管理与发布,是两者的结合。在业界,有不少与Fornax具有类似功能的工具,比如Jenkins、Drone、Travis CI等。而这些工具跟Fonnax之间存在着一些功能的差异,以及思想的不同。本节将从这些工具的差别的角度出发介绍Fornax的优势。 80 | 81 | Jenkins,Drone,Travis CI都是关注持续集成的工具。它们在实现上各有不同。Jenkins是三个工具当中最早,也是最流行的持续集成工具。其实现并没有借助容器虚拟化的技术,而只是通过操作系统的进程,目录等等进行了简单的隔离。不过Jenkins支持主从结构的分布式部署,经历过真实使用的考验。Jenkins采用Java实现,代码简洁易懂,插件众多,扩展性好。同时,Jenkins提供了网页和API两种方式进行构建,API使用XML格式作为传输格式。因此在配置的可读性上,比以YAML格式的配置文件难以阅读。但这并不影响Jenkins是目前市场份额最大的开源持续集成工具。在Fornax的实现过程中,也是使用Jenkins来对Fornax进行持续集成,保证Fornax的代码质量的。 82 | 83 | Drone是一个新兴的持续集成工具,与Fornax一样,是使用go语言实现的,其在持续集成过程的工作流与Fornax类似,都是采取了YAML格式的配置文件来控制整个持续集成流程的方法。Drone本身的目的是取代Jenkins成为持续集成工具的下一代主流,因此就功能而言与Jenkins相差无几。而从实现角度而言,Drone与Fornax相同,使用了Docker来进行构建时的隔离,其同样支持插件,并且有命令行工具支持,可以通过命令行直接与Drone进行交互,完成构建,对于开发者而言更加友好。相比于Jenkins,Drone使用了更多的新技术与新工具,使得代码实现更加简洁的同时,拥有更好地隔离性。Drone也支持分布式的部署,它允许接入多个Docker Host来进行分布式的构建。 84 | 85 | Travis CI是另外一款开源的持续集成工具,主要使用Ruby语言实现。Travis CI的功能与前两者并无区别,只是另一种的实现思路。Travis CI对于隔离的方式有更多的选择,并且其在日志传输等方面更加成熟。在其开源的版本中,有使用容器来进行构建隔离的实现。 86 | 87 | \begin{table}[!hpb] 88 | \centering 89 | \caption{Fornax与其他工具对比} 90 | \label{tab:advantage} 91 | \begin{tabular}{llllll} \toprule 92 | & 实现语言 & 持续集成 & 分布式 & 容器隔离 & 版本管理 \\ \midrule 93 | Jenkins & Java & 支持 & 支持 & 不支持 & 不支持 \\ 94 | Drone & Golang & 支持 & 支持 & 支持 & 不支持 \\ 95 | Travis CI & Ruby & 支持 & 支持 & 支持 & 不支持 \\ 96 | Fornax & Golang & 支持 & 支持 & 支持 & 支持 \\ \bottomrule 97 | \end{tabular} 98 | \end{table} 99 | 100 | Fornax与其他工具的对比如表\ref{tab:advantage}所示,Fornax也如其他工具一样,具有持续集成的功能,并且使用了容器虚拟化技术对构建进行隔离,保证构建之间互相不感知。Fornax可以通过HAProxy来进行分布式的部署,以满足更高的吞吐量要求。而Fornax不仅是一个专注于持续集成的工具,同样是一个版本管理与发布的平台。对于其他的持续集成工具,每次构建只会留下日志。而对于Fornax而言,不仅日志会保留,每次构建在成功时还会构建并且发布一个版本镜像,这也是Fornax与其他的持续集成工具最大不同所在。而且Fornax在解决发布的问题上与其他的工具也存在不同。Fornax目前是一个专用性的工具,只关注将应用部署到Kubernetes集群上。这意味着Fornax可以根据这样的应用场景做适配与优化。 101 | 102 | 因此,Fornax在定位上与现有的持续集成工具存在一定的差异,持续集成不是Fornax唯一的功能,相比于其他的持续集成工具,Fornax更加关注对于版本的管理,以及将应用部署到容器集群上的过程。这也是Fornax的优势所在。 -------------------------------------------------------------------------------- /tex/test_result.tex: -------------------------------------------------------------------------------- 1 | %# -*- coding: utf-8-unix -*- 2 | %%================================================== 3 | %% impl.tex for SJTU Master Thesis 4 | %%================================================== 5 | 6 | \chapter{Fornax功能性测试输出结果} 7 | \label{chap:test-result} 8 | 9 | 测试日志如下所示。 10 | 11 | \begin{lstlisting}[caption={Fornax功能性测试日志}] 12 | GitHub pull request #237 of commit 99d351b6a8c0c0e0f014bbfd0db09af42f57daf2, no merge conflicts. 13 | Setting status of 99d351b6a8c0c0e0f014bbfd0db09af42f57daf2 to PENDING with url http://43.254.54.241:8080/ and message: 'Build started sha1 is merged.' 14 | Using context: e2e-test 15 | Building remotely on slave-anchnet-2 in workspace /home/ubuntu/jenkins/workspace/fornax 16 | > git rev-parse --is-inside-work-tree # timeout=10 17 | Fetching changes from the remote Git repository 18 | > git config remote.origin.url https://github.com/caicloud/fornax.git # timeout=10 19 | Fetching upstream changes from https://github.com/caicloud/fornax.git 20 | > git --version # timeout=10 21 | using .gitcredentials to set credentials 22 | > git config --local credential.username caicloud-bot # timeout=10 23 | > git config --local credential.helper store --file=/tmp/git775915477012440165.credentials # timeout=10 24 | > git -c core.askpass=true fetch --tags --progress https://github.com/caicloud/fornax.git +refs/pull/*:refs/remotes/origin/pr/* 25 | > git config --local --remove-section credential # timeout=10 26 | > git rev-parse refs/remotes/origin/pr/237/merge^{commit} # timeout=10 27 | > git rev-parse refs/remotes/origin/origin/pr/237/merge^{commit} # timeout=10 28 | Checking out Revision 5b1e1faadcf870910ae019482ab5330636447852 (refs/remotes/origin/pr/237/merge) 29 | > git config core.sparsecheckout # timeout=10 30 | > git checkout -f 5b1e1faadcf870910ae019482ab5330636447852 31 | First time build. Skipping changelog. 32 | [fornax] /bin/bash /tmp/hudson6251074946529632248.sh 33 | [Sat Jun 4 20:38:59 CST 2016] The related service running in docker, the registry, mongo and fornax running in local. 34 | Creating fornax\_zookeeper\_1 35 | Creating fornax\_kafka\_1 36 | Start registry 37 | Start docker-auth 38 | -> repositories cloned to: /tmp/fornax.Zz6jLZA7Wj/workdir 39 | -> registry location: localhost:5000 40 | -> registry data for auth log: /tmp/fornax.Zz6jLZA7Wj/auth-log 41 | -> registry data for local registry: /tmp/fornax.Zz6jLZA7Wj/registry 42 | -> registry username: admin 43 | -> registry password: admin\_password 44 | === RUN TestService 45 | Running Suite: Service Suite 46 | ============================ 47 | Random Seed: 1465043956 48 | Will run 11 of 11 specs 49 | time="2016-06-04T20:39:16+08:00" level=info msg="Waiting for fornax to start, please wait. If things went wrong, this may loop forever" \_file\_="setup.go:122" 50 | time="2016-06-04T20:39:22+08:00" level=info msg="Env variant MONGO\_DB\_IP found, using env value: localhost:28017" \_file\_="osutil.go:28" 51 | time="2016-06-04T20:39:23+08:00" level=info msg="Env variant DOCKER\_HOST found, using env value: unix:///var/run/docker.sock" \_file\_="osutil.go:28" 52 | time="2016-06-04T20:39:23+08:00" level=info msg="Env variant DOCKER\_CERT\_PATH not found, using default value: " \_file\_="osutil.go:25" 53 | time="2016-06-04T20:39:23+08:00" level=info msg="Env variant REGISTRY\_LOCATION found, using env value: localhost:5000" \_file\_="osutil.go:28" 54 | time="2016-06-04T20:39:23+08:00" level=info msg="Env variant REGISTRY\_USERNAME found, using env value: admin" \_file\_="osutil.go:28" 55 | time="2016-06-04T20:39:23+08:00" level=info msg="Env variant REGISTRY\_PASSWORD found, using env value: admin\_password" \_file\_="osutil.go:28" 56 | time="2016-06-04T20:39:23+08:00" level=info msg="Env variant ENABLE\_CAICLOUD\_AUTH found, using env value: false" \_file\_="osutil.go:28" 57 | time="2016-06-04T20:39:23+08:00" level=info msg="Env variant DOCKER\_HOST\_DIR not found, using default value: " \_file\_="osutil.go:25" 58 | time="2016-06-04T20:39:23+08:00" level=info msg="Env variant UI\_SERVER\_PATH not found, using default value: http://127.0.0.1:3000" \_file\_="osutil.go:25" 59 | time="2016-06-04T20:39:23+08:00" level=info msg="Env variant MEMORYFORUSER not found, using default value: 1073741824" \_file\_="osutil.go:25" 60 | time="2016-06-04T20:39:23+08:00" level=info msg="Env variant CPUFORUSER not found, using default value: 1024" \_file\_="osutil.go:25" 61 | time="2016-06-04T20:39:23+08:00" level=info msg="Env variant MEMORYFORCONTAINER not found, using default value: 134217728" \_file\_="osutil.go:25" 62 | time="2016-06-04T20:39:23+08:00" level=info msg="Env variant CPUFORCONTAINER not found, using default value: 128" \_file\_="osutil.go:25" 63 | time="2016-06-04T20:39:23+08:00" level=warning msg="Unable to create daemon manager: dir is empty!" \_file\_="init.go:105" 64 | time="2016-06-04T20:39:23+08:00" level=info msg="AsyncManager background processing started" \_file\_="manager.go:118" 65 | [restful] 2016/06/04 20:39:23 log.go:30: [restful/swagger] listing is available at http://localhost:7099/apidocs.json 66 | [restful] 2016/06/04 20:39:23 log.go:30: [restful/swagger] http://localhost:7099/apidocs/ is mapped to folder ./node\_modules/swagger-ui/dist 67 | time="2016-06-04T20:39:23+08:00" level=info msg="fornax server listening on 7099" \_file\_="main.go:155" 68 | time="2016-06-04T20:39:23+08:00" level=info msg="Env variant KAFKA\_SERVER\_IP found, using env value: localhost:9092" \_file\_="osutil.go:28" 69 | time="2016-06-04T20:39:23+08:00" level=info msg="Start Websocket Server at Port:8000" \_file\_="server.go:18" 70 | time="2016-06-04T20:39:24+08:00" level=info msg="fornax started" \_file\_="setup.go:130" 71 | time="2016-06-04T20:39:24+08:00" level=info msg="Env variant DOCKER\_HOST found, using env value: unix:///var/run/docker.sock" \_file\_="osutil.go:28" 72 | time="2016-06-04T20:39:24+08:00" level=info msg="Env variant DOCKER\_CERT\_PATH not found, using default value: " \_file\_="osutil.go:25" 73 | time="2016-06-04T20:39:24+08:00" level=info msg="Env variant REGISTRY\_LOCATION found, using env value: localhost:5000" \_file\_="osutil.go:28" 74 | time="2016-06-04T20:39:24+08:00" level=info msg="Env variant REGISTRY\_USERNAME found, using env value: admin" \_file\_="osutil.go:28" 75 | time="2016-06-04T20:39:24+08:00" level=info msg="Env variant REGISTRY\_PASSWORD found, using env value: admin\_password" \_file\_="osutil.go:28" 76 | •time="2016-06-04T20:39:24+08:00" level=info msg="fornax receives creating service request" \_file\_="service.go:74" service\_name=test-basic-rest-service user\_id=listUID 77 | time="2016-06-04T20:39:24+08:00" level=error \_file\_="manager.go:93" error="not found" user\_id=listUID 78 | time="2016-06-04T20:39:24+08:00" level=info msg="About to clone git repository." \_file\_="git.go:24" destPath="/tmp/fornax.Zz6jLZA7Wj/workdir/listUID/bda3b9a4-baab-49ad-bd9a-70f37b34f61b" url="https://github.com/caicloud/toy-dockerfile" 79 | •time="2016-06-04T20:39:27+08:00" level=info msg="Successfully cloned git repository." \_file\_="git.go:36" destPath="/tmp/fornax.Zz6jLZA7Wj/workdir/listUID/bda3b9a4-baab-49ad-bd9a-70f37b34f61b" url="https://github.com/caicloud/toy-dockerfile" 80 | time="2016-06-04T20:39:27+08:00" level=info msg="About to remove repository." \_file\_="manager.go:213" destPath="/tmp/fornax.Zz6jLZA7Wj/workdir/listUID/bda3b9a4-baab-49ad-bd9a-70f37b34f61b" 81 | time="2016-06-04T20:39:27+08:00" level=info msg="Successfully removed repository with path" \_file\_="manager.go:229" destPath="/tmp/fornax.Zz6jLZA7Wj/workdir/listUID/bda3b9a4-baab-49ad-bd9a-70f37b34f61b" 82 | time="2016-06-04T20:39:27+08:00" level=info msg="Event finished, close file" \_file\_="manager.go:146" file="/tmp/fornax.Zz6jLZA7Wj/workdir/listUID/logs/bda3b9a4-baab-49ad-bd9a-70f37b34f61b" 83 | ••time="2016-06-04T20:39:28+08:00" level=info msg="fornax receives creating service request" \_file\_="service.go:74" service\_name=test-basic-rest-service user\_id=aliceUID 84 | time="2016-06-04T20:39:28+08:00" level=error \_file\_="manager.go:93" error="not found" user\_id=aliceUID 85 | time="2016-06-04T20:39:28+08:00" level=info msg="About to clone git repository." \_file\_="git.go:24" destPath="/tmp/fornax.Zz6jLZA7Wj/workdir/aliceUID/914d2db0-4a18-484d-804d-02eedca74b7d" url=123456 86 | time="2016-06-04T20:39:28+08:00" level=error msg="Error when clone" \_file\_="git.go:34" error="exit status 128" 87 | time="2016-06-04T20:39:28+08:00" level=error msg="Operation failed" \_file\_="manager.go:134" event=&{914d2db0-4a18-484d-804d-02eedca74b7d create-service 0xc8201fb440 map[] 0x5237c0 0xc8201bb980 {false Unable to clone repository for service &api.Service{ServiceID:"914d2db0-4a18-484d-804d-02eedca74b7d", UserID:"aliceUID", Name:"test-basic-rest-service", Username:"alice", Description:"A service just for test", BuildPath:"", Versions:[]string(nil), Repository:api.ServiceRepository{URL:"123456", Vcs:"git", Status:"missing", Username:"", Password:""}, Jconfig:api.JenkinsConfig{Address:"", Username:"", Password:""}, LastVersionCreateTIme:time.Time{sec:0, nsec:0, loc:(*time.Location)(0x111d180)}, LastVersionName:""}: exit status 128 88 | false 0xc8201fc7e0} {1 0} } 89 | time="2016-06-04T20:39:28+08:00" level=info msg="About to remove repository." \_file\_="manager.go:213" destPath="/tmp/fornax.Zz6jLZA7Wj/workdir/aliceUID/914d2db0-4a18-484d-804d-02eedca74b7d" 90 | time="2016-06-04T20:39:28+08:00" level=info msg="Event finished, close file" \_file\_="manager.go:146" file="/tmp/fornax.Zz6jLZA7Wj/workdir/aliceUID/logs/914d2db0-4a18-484d-804d-02eedca74b7d" 91 | •time="2016-06-04T20:39:30+08:00" level=info msg="fornax receives creating service request" \_file\_="service.go:74" service\_name=test-basic-rest-service user\_id=aliceUID 92 | time="2016-06-04T20:39:30+08:00" level=error msg="Unknown version control system gaocegege" \_file\_="manager.go:200" 93 | time="2016-06-04T20:39:30+08:00" level=info msg="About to remove repository." \_file\_="manager.go:213" destPath="/tmp/fornax.Zz6jLZA7Wj/workdir/aliceUID/237b543b-694e-4de3-b0a0-877cbb982bc9" 94 | time="2016-06-04T20:39:30+08:00" level=info msg="Event finished, close file" \_file\_="manager.go:146" file="/tmp/fornax.Zz6jLZA7Wj/workdir/aliceUID/logs/237b543b-694e-4de3-b0a0-877cbb982bc9" 95 | •time="2016-06-04T20:39:33+08:00" level=info msg="fornax receives creating service request" \_file\_="service.go:74" service\_name=test-basic-rest-service user\_id=bobUID 96 | time="2016-06-04T20:39:33+08:00" level=error \_file\_="manager.go:93" error="not found" user\_id=bobUID 97 | time="2016-06-04T20:39:33+08:00" level=info msg="About to clone git repository." \_file\_="git.go:24" destPath="/tmp/fornax.Zz6jLZA7Wj/workdir/bobUID/c7e3c3bc-26f5-4aba-be9b-3cb1bb868656" url="https://github.com/caicloud/toy-dockerfile" 98 | •time="2016-06-04T20:39:34+08:00" level=info msg="fornax receives creating service request" \_file\_="service.go:74" service\_name=test-basic-rest-service user\_id=aliceUID 99 | time="2016-06-04T20:39:34+08:00" level=error \_file\_="manager.go:93" error="not found" user\_id=aliceUID 100 | time="2016-06-04T20:39:34+08:00" level=info msg="About to clone git repository." \_file\_="git.go:24" destPath="/tmp/fornax.Zz6jLZA7Wj/workdir/aliceUID/e5d4416b-6e5e-40fc-a94b-8050f0bfb234" url="https://github.com/caicloud/toy-dockerfile" 101 | time="2016-06-04T20:39:36+08:00" level=info msg="Successfully cloned git repository." \_file\_="git.go:36" destPath="/tmp/fornax.Zz6jLZA7Wj/workdir/aliceUID/e5d4416b-6e5e-40fc-a94b-8050f0bfb234" url="https://github.com/caicloud/toy-dockerfile" 102 | time="2016-06-04T20:39:36+08:00" level=info msg="About to remove repository." \_file\_="manager.go:213" destPath="/tmp/fornax.Zz6jLZA7Wj/workdir/aliceUID/e5d4416b-6e5e-40fc-a94b-8050f0bfb234" 103 | time="2016-06-04T20:39:36+08:00" level=info msg="Successfully removed repository with path" \_file\_="manager.go:229" destPath="/tmp/fornax.Zz6jLZA7Wj/workdir/aliceUID/e5d4416b-6e5e-40fc-a94b-8050f0bfb234" 104 | time="2016-06-04T20:39:36+08:00" level=info msg="Event finished, close file" \_file\_="manager.go:146" file="/tmp/fornax.Zz6jLZA7Wj/workdir/aliceUID/logs/e5d4416b-6e5e-40fc-a94b-8050f0bfb234" 105 | time="2016-06-04T20:39:36+08:00" level=info msg="Successfully cloned git repository." \_file\_="git.go:36" destPath="/tmp/fornax.Zz6jLZA7Wj/workdir/bobUID/c7e3c3bc-26f5-4aba-be9b-3cb1bb868656" url="https://github.com/caicloud/toy-dockerfile" 106 | time="2016-06-04T20:39:36+08:00" level=info msg="About to remove repository." \_file\_="manager.go:213" destPath="/tmp/fornax.Zz6jLZA7Wj/workdir/bobUID/c7e3c3bc-26f5-4aba-be9b-3cb1bb868656" 107 | time="2016-06-04T20:39:36+08:00" level=info msg="Successfully removed repository with path" \_file\_="manager.go:229" destPath="/tmp/fornax.Zz6jLZA7Wj/workdir/bobUID/c7e3c3bc-26f5-4aba-be9b-3cb1bb868656" 108 | time="2016-06-04T20:39:36+08:00" level=info msg="Event finished, close file" \_file\_="manager.go:146" file="/tmp/fornax.Zz6jLZA7Wj/workdir/bobUID/logs/c7e3c3bc-26f5-4aba-be9b-3cb1bb868656" 109 | •time="2016-06-04T20:39:37+08:00" level=error msg="have no access to service e5d4416b-6e5e-40fc-a94b-8050f0bfb234" \_file\_="filter.go:112" user\_id=bobUID 110 | •time="2016-06-04T20:39:37+08:00" level=error msg="have no access to service e5d4416b-6e5e-40fc-a94b-8050f0bfb234" \_file\_="filter.go:112" user\_id=bobUID 111 | •time="2016-06-04T20:39:37+08:00" level=error msg="Unable to find service e5d4416b-6e5e-40fc-a94b-8050f0bfb234" \_file\_="filter.go:107" error="not found" user\_id=aliceUID 112 | • 113 | Ran 11 of 11 Specs in 20.548 seconds 114 | SUCCESS! -- 11 Passed | 0 Failed | 0 Pending | 0 Skipped --- PASS: TestService (20.55s) 115 | PASS 116 | ok github.com/caicloud/fornax/tests/service 20.620s 117 | === RUN TestVersion 118 | Running Suite: Version Suite 119 | ============================ 120 | Random Seed: 1465043984 121 | Will run 20 of 20 specs 122 | time="2016-06-04T20:39:44+08:00" level=info msg="Waiting for fornax to start, please wait. If things went wrong, this may loop forever" \_file\_="setup.go:122" 123 | time="2016-06-04T20:39:45+08:00" level=info msg="fornax started" \_file\_="setup.go:130" 124 | time="2016-06-04T20:39:45+08:00" level=info msg="Env variant DOCKER\_HOST found, using env value: unix:///var/run/docker.sock" \_file\_="osutil.go:28" 125 | time="2016-06-04T20:39:45+08:00" level=info msg="Env variant DOCKER\_CERT\_PATH not found, using default value: " \_file\_="osutil.go:25" 126 | time="2016-06-04T20:39:45+08:00" level=info msg="Env variant REGISTRY\_LOCATION found, using env value: localhost:5000" \_file\_="osutil.go:28" 127 | time="2016-06-04T20:39:45+08:00" level=info msg="Env variant REGISTRY\_USERNAME found, using env value: admin" \_file\_="osutil.go:28" 128 | time="2016-06-04T20:39:45+08:00" level=info msg="Env variant REGISTRY\_PASSWORD found, using env value: admin\_password" \_file\_="osutil.go:28" 129 | time="2016-06-04T20:39:45+08:00" level=info msg="fornax receives creating service request" \_file\_="service.go:74" service\_name=test-basic-rest-version user\_id=aliceUID 130 | time="2016-06-04T20:39:45+08:00" level=error \_file\_="manager.go:93" error="not found" user\_id=aliceUID 131 | time="2016-06-04T20:39:45+08:00" level=info msg="About to clone git repository." \_file\_="git.go:24" destPath="/tmp/fornax.Zz6jLZA7Wj/workdir/aliceUID/0bdcf049-36cb-4d2d-ae4a-70134c0788e8" url="https://github.com/caicloud/toy-dockerfile" 132 | time="2016-06-04T20:39:48+08:00" level=info msg="Successfully cloned git repository." \_file\_="git.go:36" destPath="/tmp/fornax.Zz6jLZA7Wj/workdir/aliceUID/0bdcf049-36cb-4d2d-ae4a-70134c0788e8" url="https://github.com/caicloud/toy-dockerfile" 133 | time="2016-06-04T20:39:48+08:00" level=info msg="About to remove repository." \_file\_="manager.go:213" destPath="/tmp/fornax.Zz6jLZA7Wj/workdir/aliceUID/0bdcf049-36cb-4d2d-ae4a-70134c0788e8" 134 | time="2016-06-04T20:39:48+08:00" level=info msg="Successfully removed repository with path" \_file\_="manager.go:229" destPath="/tmp/fornax.Zz6jLZA7Wj/workdir/aliceUID/0bdcf049-36cb-4d2d-ae4a-70134c0788e8" 135 | time="2016-06-04T20:39:48+08:00" level=info msg="Event finished, close file" \_file\_="manager.go:146" file="/tmp/fornax.Zz6jLZA7Wj/workdir/aliceUID/logs/0bdcf049-36cb-4d2d-ae4a-70134c0788e8" 136 | time="2016-06-04T20:39:49+08:00" level=info msg="fornax receives creating service request" \_file\_="service.go:74" service\_name=test-basic-rest-version user\_id=aliceUID 137 | time="2016-06-04T20:39:49+08:00" level=error \_file\_="manager.go:93" error="not found" user\_id=aliceUID 138 | time="2016-06-04T20:39:49+08:00" level=info msg="About to svn checkout repository." \_file\_="svn.go:20" destPath="/tmp/fornax.Zz6jLZA7Wj/workdir/aliceUID/50383984-ab3e-4946-b087-eafc3d23645b" url="https://github.com/caicloud/toy-dockerfile/trunk" 139 | time="2016-06-04T20:39:55+08:00" level=info msg="Successfully svn checkout repository." \_file\_="svn.go:29" destPath="/tmp/fornax.Zz6jLZA7Wj/workdir/aliceUID/50383984-ab3e-4946-b087-eafc3d23645b" url="https://github.com/caicloud/toy-dockerfile/trunk" 140 | time="2016-06-04T20:39:55+08:00" level=info msg="About to remove repository." \_file\_="manager.go:213" destPath="/tmp/fornax.Zz6jLZA7Wj/workdir/aliceUID/50383984-ab3e-4946-b087-eafc3d23645b" 141 | time="2016-06-04T20:39:55+08:00" level=info msg="Successfully removed repository with path" \_file\_="manager.go:229" destPath="/tmp/fornax.Zz6jLZA7Wj/workdir/aliceUID/50383984-ab3e-4946-b087-eafc3d23645b" 142 | time="2016-06-04T20:39:55+08:00" level=info msg="Event finished, close file" \_file\_="manager.go:146" file="/tmp/fornax.Zz6jLZA7Wj/workdir/aliceUID/logs/50383984-ab3e-4946-b087-eafc3d23645b" 143 | time="2016-06-04T20:39:55+08:00" level=info msg="fornax receives creating version request" \_file\_="version.go:56" user\_id=aliceUID version={ 0bdcf049-36cb-4d2d-ae4a-70134c0788e8 v0.1.0 A version just for test [] [] [] 0001-01-01 00:00:00 +0000 UTC } 144 | time="2016-06-04T20:39:55+08:00" level=error \_file\_="manager.go:93" error="not found" user\_id=aliceUID 145 | time="2016-06-04T20:39:55+08:00" level=info msg="About to clone git repository." \_file\_="git.go:24" destPath="/tmp/fornax.Zz6jLZA7Wj/workdir/aliceUID/c9cb3341-e9b6-45c1-93f2-9f74534995a7" url="https://github.com/caicloud/toy-dockerfile" 146 | •time="2016-06-04T20:39:58+08:00" level=info msg="Successfully cloned git repository." \_file\_="git.go:36" destPath="/tmp/fornax.Zz6jLZA7Wj/workdir/aliceUID/c9cb3341-e9b6-45c1-93f2-9f74534995a7" url="https://github.com/caicloud/toy-dockerfile" 147 | time="2016-06-04T20:39:58+08:00" level=info msg="After apply, the userid aliceUID'sleft resource memory 939524096 cpu 896 numberContainers 1\n" \_file\_="resource.go:55" 148 | time="2016-06-04T20:39:58+08:00" level=info msg="About to build docker image." \_file\_="manager.go:125" image="localhost:5000/alice/test-basic-rest-version:v0.1.0" 149 | time="2016-06-04T20:40:03+08:00" level=info msg="Successfully built docker image." \_file\_="manager.go:153" image="localhost:5000/alice/test-basic-rest-version:v0.1.0" 150 | time="2016-06-04T20:40:03+08:00" level=info msg="About to push docker image." \_file\_="manager.go:172" image="localhost:5000/alice/test-basic-rest-version" tag=v0.1.0 151 | time="2016-06-04T20:40:03+08:00" level=info msg="Successfully pushed docker image." \_file\_="manager.go:188" image="localhost:5000/alice/test-basic-rest-version" 152 | time="2016-06-04T20:40:03+08:00" level=info msg="Successfully remove docker image." \_file\_="manager.go:239" image="localhost:5000/alice/test-basic-rest-version:v0.1.0" 153 | time="2016-06-04T20:40:03+08:00" level=info msg="Successfully remove docker image." \_file\_="operations.go:91" image=busybox 154 | time="2016-06-04T20:40:03+08:00" level=info msg="Afer release, the userid aliceUID's left resource memory 1073741824 cpu 1024 numberContainers 1\n" \_file\_="resource.go:75" 155 | time="2016-06-04T20:40:03+08:00" level=error msg="Unable to get tag commit" \_file\_="operations.go:299" commit= err="exit status 128" version=&{c9cb3341-e9b6-45c1-93f2-9f74534995a7 0bdcf049-36cb-4d2d-ae4a-70134c0788e8 v0.1.0 A version just for test [] [latest] [] 2016-06-04 20:39:55.855022706 +0800 CST healthy } 156 | time="2016-06-04T20:40:03+08:00" level=info msg="About to remove repository." \_file\_="manager.go:213" destPath="/tmp/fornax.Zz6jLZA7Wj/workdir/aliceUID/c9cb3341-e9b6-45c1-93f2-9f74534995a7" 157 | time="2016-06-04T20:40:03+08:00" level=info msg="Successfully removed repository with path" \_file\_="manager.go:229" destPath="/tmp/fornax.Zz6jLZA7Wj/workdir/aliceUID/c9cb3341-e9b6-45c1-93f2-9f74534995a7" 158 | time="2016-06-04T20:40:03+08:00" level=info msg="Event finished, close file" \_file\_="manager.go:146" file="/tmp/fornax.Zz6jLZA7Wj/workdir/aliceUID/logs/c9cb3341-e9b6-45c1-93f2-9f74534995a7" 159 | time="2016-06-04T20:40:03+08:00" level=info msg="Successfully removed log file" \_file\_="log.go:71" filename=c9cb3341-e9b6-45c1-93f2-9f74534995a7 160 | ------------------------------ 161 | • [SLOW TEST:9.003 seconds] 162 | Version 163 | /home/ubuntu/jenkins/workspace/fornax/src/github.com/caicloud/fornax/tests/version/version\_test.go:374 164 | with right service id 165 | /home/ubuntu/jenkins/workspace/fornax/src/github.com/caicloud/fornax/tests/version/version\_test.go:206 166 | with right version information 167 | /home/ubuntu/jenkins/workspace/fornax/src/github.com/caicloud/fornax/tests/version/version\_test.go:197 168 | should be able to get version via HTTP GET method. 169 | /home/ubuntu/jenkins/workspace/fornax/src/github.com/caicloud/fornax/tests/version/version\_test.go:156 170 | ------------------------------ 171 | •time="2016-06-04T20:40:05+08:00" level=info msg="Successfully pull docker image." \_file\_="manager.go:285" image="localhost:5000/alice/test-basic-rest-version:v0.1.0" 172 | •time="2016-06-04T20:40:05+08:00" level=info msg="receive watch\_log packet" \_file\_="application.go:70" 173 | time="2016-06-04T20:40:05+08:00" level=info msg="set topic create\_version\_\_aliceUID\_\_0bdcf049\_36cb\_4d2d\_ae4a\_70134c0788e8\_\_c9cb3341\_e9b6\_45c1\_93f2\_9f74534995a7 true" \_file\_="ws\_session.go:86" 174 | time="2016-06-04T20:40:05+08:00" level=info msg="start push create\_version\_\_aliceUID\_\_0bdcf049\_36cb\_4d2d\_ae4a\_70134c0788e8\_\_c9cb3341\_e9b6\_45c1\_93f2\_9f74534995a7 to d298823d-5924-4c9c-8df8-e2fa12e87e56" \_file\_="application.go:124" 175 | time="2016-06-04T20:40:16+08:00" level=info msg="receive watch\_log packet" \_file\_="application.go:70" 176 | time="2016-06-04T20:40:16+08:00" level=info msg="set topic create\_version\_\_aliceUID\_\_0bdcf049\_36cb\_4d2d\_ae4a\_70134c0788e8\_\_c9cb3341\_e9b6\_45c1\_93f2\_9f74534995a7 false" \_file\_="ws\_session.go:86" 177 | ------------------------------ 178 | • [SLOW TEST:11.772 seconds] 179 | Version 180 | /home/ubuntu/jenkins/workspace/fornax/src/github.com/caicloud/fornax/tests/version/version\_test.go:374 181 | with right service id 182 | /home/ubuntu/jenkins/workspace/fornax/src/github.com/caicloud/fornax/tests/version/version\_test.go:206 183 | with right version information 184 | /home/ubuntu/jenkins/workspace/fornax/src/github.com/caicloud/fornax/tests/version/version\_test.go:197 185 | should push the log 186 | /home/ubuntu/jenkins/workspace/fornax/src/github.com/caicloud/fornax/tests/version/version\_test.go:178 187 | ------------------------------ 188 | ••time="2016-06-04T20:40:16+08:00" level=info msg="receive watch\_log packet" \_file\_="application.go:70" 189 | time="2016-06-04T20:40:16+08:00" level=info msg="set topic create\_version\_\_aliceUID\_\_0bdcf049\_36cb\_4d2d\_ae4a\_70134c0788e8\_\_\_1 true" \_file\_="ws\_session.go:86" 190 | time="2016-06-04T20:40:16+08:00" level=info msg="start push create\_version\_\_aliceUID\_\_0bdcf049\_36cb\_4d2d\_ae4a\_70134c0788e8\_\_\_1 to d298823d-5924-4c9c-8df8-e2fa12e87e56" \_file\_="application.go:124" 191 | time="2016-06-04T20:40:17+08:00" level=info msg="stop push create\_version\_\_aliceUID\_\_0bdcf049\_36cb\_4d2d\_ae4a\_70134c0788e8\_\_c9cb3341\_e9b6\_45c1\_93f2\_9f74534995a7 to d298823d-5924-4c9c-8df8-e2fa12e87e56" \_file\_="application.go:162" 192 | •time="2016-06-04T20:40:19+08:00" level=info msg="fornax receives creating version request" \_file\_="version.go:56" user\_id=aliceUID version={ -1 v0.1.0 A version just for test [] [] [] 0001-01-01 00:00:00 +0000 UTC } 193 | time="2016-06-04T20:40:19+08:00" level=error msg="Unable to find service -1" \_file\_="version.go:63" error="not found" user\_id=aliceUID 194 | •time="2016-06-04T20:40:19+08:00" level=info msg="fornax receives creating version request" \_file\_="version.go:56" user\_id=aliceUID version={ 0bdcf049-36cb-4d2d-ae4a-70134c0788e8 v0.1.0 A version just for test [] [] [] 0001-01-01 00:00:00 +0000 UTC } 195 | time="2016-06-04T20:40:19+08:00" level=error \_file\_="manager.go:93" error="not found" user\_id=aliceUID 196 | time="2016-06-04T20:40:19+08:00" level=info msg="About to clone git repository." \_file\_="git.go:24" destPath="/tmp/fornax.Zz6jLZA7Wj/workdir/aliceUID/4d1ddff9-e571-49ce-bb68-afbf94c5e4b1" url="https://github.com/caicloud/toy-dockerfile" 197 | •time="2016-06-04T20:40:22+08:00" level=info msg="Successfully cloned git repository." \_file\_="git.go:36" destPath="/tmp/fornax.Zz6jLZA7Wj/workdir/aliceUID/4d1ddff9-e571-49ce-bb68-afbf94c5e4b1" url="https://github.com/caicloud/toy-dockerfile" 198 | time="2016-06-04T20:40:22+08:00" level=info msg="After apply, the userid aliceUID'sleft resource memory 939524096 cpu 896 numberContainers 1\n" \_file\_="resource.go:55" 199 | time="2016-06-04T20:40:22+08:00" level=info msg="About to build docker image." \_file\_="manager.go:125" image="localhost:5000/alice/test-basic-rest-version:v0.1.0" 200 | time="2016-06-04T20:40:26+08:00" level=info msg="Successfully built docker image." \_file\_="manager.go:153" image="localhost:5000/alice/test-basic-rest-version:v0.1.0" 201 | time="2016-06-04T20:40:26+08:00" level=info msg="About to push docker image." \_file\_="manager.go:172" image="localhost:5000/alice/test-basic-rest-version" tag=v0.1.0 202 | time="2016-06-04T20:40:26+08:00" level=info msg="Successfully pushed docker image." \_file\_="manager.go:188" image="localhost:5000/alice/test-basic-rest-version" 203 | time="2016-06-04T20:40:26+08:00" level=info msg="Successfully remove docker image." \_file\_="manager.go:239" image="localhost:5000/alice/test-basic-rest-version:v0.1.0" 204 | time="2016-06-04T20:40:26+08:00" level=info msg="Successfully remove docker image." \_file\_="operations.go:91" image=busybox 205 | time="2016-06-04T20:40:26+08:00" level=info msg="Afer release, the userid aliceUID's left resource memory 1073741824 cpu 1024 numberContainers 1\n" \_file\_="resource.go:75" 206 | time="2016-06-04T20:40:26+08:00" level=error msg="Unable to get tag commit" \_file\_="operations.go:299" commit= err="exit status 128" version=&{4d1ddff9-e571-49ce-bb68-afbf94c5e4b1 0bdcf049-36cb-4d2d-ae4a-70134c0788e8 v0.1.0 A version just for test [] [latest] [] 2016-06-04 20:40:19.841414039 +0800 CST healthy } 207 | time="2016-06-04T20:40:26+08:00" level=info msg="About to remove repository." \_file\_="manager.go:213" destPath="/tmp/fornax.Zz6jLZA7Wj/workdir/aliceUID/4d1ddff9-e571-49ce-bb68-afbf94c5e4b1" 208 | time="2016-06-04T20:40:26+08:00" level=info msg="Successfully removed repository with path" \_file\_="manager.go:229" destPath="/tmp/fornax.Zz6jLZA7Wj/workdir/aliceUID/4d1ddff9-e571-49ce-bb68-afbf94c5e4b1" 209 | time="2016-06-04T20:40:26+08:00" level=info msg="Event finished, close file" \_file\_="manager.go:146" file="/tmp/fornax.Zz6jLZA7Wj/workdir/aliceUID/logs/4d1ddff9-e571-49ce-bb68-afbf94c5e4b1" 210 | time="2016-06-04T20:40:26+08:00" level=info msg="Successfully removed log file" \_file\_="log.go:71" filename=4d1ddff9-e571-49ce-bb68-afbf94c5e4b1 211 | time="2016-06-04T20:40:29+08:00" level=info msg="Successfully pull docker image." \_file\_="manager.go:285" image="localhost:5000/alice/test-basic-rest-version:v0.1.0" 212 | ------------------------------ 213 | • [SLOW TEST:9.094 seconds] 214 | Version 215 | /home/ubuntu/jenkins/workspace/fornax/src/github.com/caicloud/fornax/tests/version/version\_test.go:374 216 | with different user ID 217 | /home/ubuntu/jenkins/workspace/fornax/src/github.com/caicloud/fornax/tests/version/version\_test.go:284 218 | should build a docker image. 219 | /home/ubuntu/jenkins/workspace/fornax/src/github.com/caicloud/fornax/tests/version/version\_test.go:267 220 | ------------------------------ 221 | time="2016-06-04T20:40:29+08:00" level=error msg="have no access to version 4d1ddff9-e571-49ce-bb68-afbf94c5e4b1" \_file\_="filter.go:137" user\_id=bobUID 222 | •time="2016-06-04T20:40:29+08:00" level=error msg="have no access to service 0bdcf049-36cb-4d2d-ae4a-70134c0788e8" \_file\_="filter.go:112" user\_id=bobUID 223 | •time="2016-06-04T20:40:29+08:00" level=info msg="receive watch\_log packet" \_file\_="application.go:70" 224 | time="2016-06-04T20:40:29+08:00" level=info msg="set topic create\_version\_\_bobUID\_\_0bdcf049\_36cb\_4d2d\_ae4a\_70134c0788e8\_\_4d1ddff9\_e571\_49ce\_bb68\_afbf94c5e4b1 true" \_file\_="ws\_session.go:86" 225 | time="2016-06-04T20:40:29+08:00" level=info msg="start push create\_version\_\_bobUID\_\_0bdcf049\_36cb\_4d2d\_ae4a\_70134c0788e8\_\_4d1ddff9\_e571\_49ce\_bb68\_afbf94c5e4b1 to d298823d-5924-4c9c-8df8-e2fa12e87e56" \_file\_="application.go:124" 226 | •time="2016-06-04T20:40:32+08:00" level=error msg="Unable to find service 0bdcf049-36cb-4d2d-ae4a-70134c0788e8" \_file\_="filter.go:107" error="not found" user\_id=aliceUID 227 | time="2016-06-04T20:40:32+08:00" level=error msg="Unable to find version c9cb3341-e9b6-45c1-93f2-9f74534995a7" \_file\_="filter.go:132" error="not found" user\_id=aliceUID 228 | time="2016-06-04T20:40:32+08:00" level=error msg="Unable to find version 4d1ddff9-e571-49ce-bb68-afbf94c5e4b1" \_file\_="filter.go:132" error="not found" user\_id=aliceUID 229 | time="2016-06-04T20:40:32+08:00" level=error msg="Unable to find version c9cb3341-e9b6-45c1-93f2-9f74534995a7" \_file\_="filter.go:132" error="not found" user\_id=aliceUID 230 | time="2016-06-04T20:40:32+08:00" level=error msg="Unable to find version 4d1ddff9-e571-49ce-bb68-afbf94c5e4b1" \_file\_="filter.go:132" error="not found" user\_id=aliceUID 231 | •time="2016-06-04T20:40:32+08:00" level=info msg="fornax receives creating version request" \_file\_="version.go:56" user\_id=aliceUID version={ 50383984-ab3e-4946-b087-eafc3d23645b v0.1.0\_svn A version just for svn test [] [] [] 0001-01-01 00:00:00 +0000 UTC } 232 | time="2016-06-04T20:40:32+08:00" level=error \_file\_="manager.go:93" error="not found" user\_id=aliceUID 233 | time="2016-06-04T20:40:32+08:00" level=info msg="About to svn checkout repository." \_file\_="svn.go:20" destPath="/tmp/fornax.Zz6jLZA7Wj/workdir/aliceUID/b13e4ffa-55ea-4c32-898a-2eb7f5d263e7" url="https://github.com/caicloud/toy-dockerfile/trunk" 234 | •time="2016-06-04T20:40:37+08:00" level=info msg="Successfully svn checkout repository." \_file\_="svn.go:29" destPath="/tmp/fornax.Zz6jLZA7Wj/workdir/aliceUID/b13e4ffa-55ea-4c32-898a-2eb7f5d263e7" url="https://github.com/caicloud/toy-dockerfile/trunk" 235 | time="2016-06-04T20:40:37+08:00" level=info msg="After apply, the userid aliceUID'sleft resource memory 939524096 cpu 896 numberContainers 1\n" \_file\_="resource.go:55" 236 | time="2016-06-04T20:40:37+08:00" level=info msg="About to build docker image." \_file\_="manager.go:125" image="localhost:5000/alice/test-basic-rest-version:v0.1.0\_svn" 237 | time="2016-06-04T20:40:41+08:00" level=info msg="Successfully built docker image." \_file\_="manager.go:153" image="localhost:5000/alice/test-basic-rest-version:v0.1.0\_svn" 238 | time="2016-06-04T20:40:41+08:00" level=info msg="About to push docker image." \_file\_="manager.go:172" image="localhost:5000/alice/test-basic-rest-version" tag="v0.1.0\_svn" 239 | time="2016-06-04T20:40:41+08:00" level=info msg="Successfully pushed docker image." \_file\_="manager.go:188" image="localhost:5000/alice/test-basic-rest-version" 240 | time="2016-06-04T20:40:41+08:00" level=info msg="Successfully remove docker image." \_file\_="manager.go:239" image="localhost:5000/alice/test-basic-rest-version:v0.1.0\_svn" 241 | time="2016-06-04T20:40:41+08:00" level=info msg="Successfully remove docker image." \_file\_="operations.go:91" image=busybox 242 | time="2016-06-04T20:40:41+08:00" level=info msg="Afer release, the userid aliceUID's left resource memory 1073741824 cpu 1024 numberContainers 1\n" \_file\_="resource.go:75" 243 | time="2016-06-04T20:40:41+08:00" level=info msg="failed checked out to svn tag." \_file\_="svn.go:76" repoPath="/tmp/fornax.Zz6jLZA7Wj/workdir/aliceUID/b13e4ffa-55ea-4c32-898a-2eb7f5d263e7" tag="v0.1.0\_svn" 244 | time="2016-06-04T20:40:41+08:00" level=error msg="Unable to get tag commit" \_file\_="operations.go:299" commit= err="chdir /tmp/fornax.Zz6jLZA7Wj/workdir/aliceUID/b13e4ffa-55ea-4c32-898a-2eb7f5d263e7/tags: no such file or directory" version=&{b13e4ffa-55ea-4c32-898a-2eb7f5d263e7 50383984-ab3e-4946-b087-eafc3d23645b v0.1.0\_svn A version just for svn test [] [latest] [] 2016-06-04 20:40:32.060096079 +0800 CST healthy } 245 | time="2016-06-04T20:40:41+08:00" level=info msg="About to remove repository." \_file\_="manager.go:213" destPath="/tmp/fornax.Zz6jLZA7Wj/workdir/aliceUID/b13e4ffa-55ea-4c32-898a-2eb7f5d263e7" 246 | time="2016-06-04T20:40:41+08:00" level=info msg="Successfully removed repository with path" \_file\_="manager.go:229" destPath="/tmp/fornax.Zz6jLZA7Wj/workdir/aliceUID/b13e4ffa-55ea-4c32-898a-2eb7f5d263e7" 247 | time="2016-06-04T20:40:41+08:00" level=info msg="Event finished, close file" \_file\_="manager.go:146" file="/tmp/fornax.Zz6jLZA7Wj/workdir/aliceUID/logs/b13e4ffa-55ea-4c32-898a-2eb7f5d263e7" 248 | time="2016-06-04T20:40:41+08:00" level=info msg="Successfully removed log file" \_file\_="log.go:71" filename=b13e4ffa-55ea-4c32-898a-2eb7f5d263e7 249 | ------------------------------ 250 | • [SLOW TEST:12.002 seconds] 251 | Version 252 | /home/ubuntu/jenkins/workspace/fornax/src/github.com/caicloud/fornax/tests/version/version\_test.go:374 253 | test svn vcs 254 | /home/ubuntu/jenkins/workspace/fornax/src/github.com/caicloud/fornax/tests/version/version\_test.go:373 255 | should be able to get version via HTTP GET method. 256 | /home/ubuntu/jenkins/workspace/fornax/src/github.com/caicloud/fornax/tests/version/version\_test.go:349 257 | ------------------------------ 258 | •time="2016-06-04T20:40:44+08:00" level=info msg="Successfully pull docker image." \_file\_="manager.go:285" image="localhost:5000/alice/test-basic-rest-version:v0.1.0\_svn" 259 | •• 260 | Ran 20 of 20 Specs in 59.612 seconds 261 | SUCCESS! -- 20 Passed | 0 Failed | 0 Pending | 0 Skipped --- PASS: TestVersion (59.61s) 262 | PASS 263 | time="2016-06-04T20:40:44+08:00" level=error msg=EOF \_file\_="server.go:59" 264 | ok github.com/caicloud/fornax/tests/version 59.645s 265 | time="2016-06-04T20:40:44+08:00" level=info msg="stop push create\_version\_\_bobUID\_\_0bdcf049\_36cb\_4d2d\_ae4a\_70134c0788e8\_\_4d1ddff9\_e571\_49ce\_bb68\_afbf94c5e4b1 to " \_file\_="application.go:162" 266 | time="2016-06-04T20:40:44+08:00" level=info msg="stop push create\_version\_\_aliceUID\_\_0bdcf049\_36cb\_4d2d\_ae4a\_70134c0788e8\_\_\_1 to " \_file\_="application.go:162" 267 | === RUN TestYaml 268 | Running Suite: Yaml Suite 269 | ========================= 270 | Random Seed: 1465044051 271 | Will run 8 of 8 specs 272 | time="2016-06-04T20:40:51+08:00" level=info msg="Waiting for fornax to start, please wait. If things went wrong, this may loop forever" \_file\_="setup.go:122" 273 | time="2016-06-04T20:40:52+08:00" level=info msg="fornax started" \_file\_="setup.go:130" 274 | time="2016-06-04T20:40:52+08:00" level=info msg="Env variant DOCKER\_HOST found, using env value: unix:///var/run/docker.sock" \_file\_="osutil.go:28" 275 | time="2016-06-04T20:40:52+08:00" level=info msg="Env variant DOCKER\_CERT\_PATH not found, using default value: " \_file\_="osutil.go:25" 276 | time="2016-06-04T20:40:52+08:00" level=info msg="Env variant REGISTRY\_LOCATION found, using env value: localhost:5000" \_file\_="osutil.go:28" 277 | time="2016-06-04T20:40:52+08:00" level=info msg="Env variant REGISTRY\_USERNAME found, using env value: admin" \_file\_="osutil.go:28" 278 | time="2016-06-04T20:40:52+08:00" level=info msg="Env variant REGISTRY\_PASSWORD found, using env value: admin\_password" \_file\_="osutil.go:28" 279 | time="2016-06-04T20:41:15+08:00" level=info msg="fornax receives creating service request" \_file\_="service.go:74" service\_name=test-basic-rest-version user\_id=aliceUID 280 | time="2016-06-04T20:41:15+08:00" level=error \_file\_="manager.go:93" error="not found" user\_id=aliceUID 281 | time="2016-06-04T20:41:15+08:00" level=info msg="About to clone fake repository." \_file\_="fake.go:34" destPath="/tmp/fornax.Zz6jLZA7Wj/workdir/aliceUID/97858e8f-b5bd-40e1-a025-ac67057107e0" url="./tests/fake\_repo\_for\_test/Integration" 282 | time="2016-06-04T20:41:15+08:00" level=info msg="Successfully cloned fake repository." \_file\_="fake.go:41" destPath="/tmp/fornax.Zz6jLZA7Wj/workdir/aliceUID/97858e8f-b5bd-40e1-a025-ac67057107e0" url="./tests/fake\_repo\_for\_test/Integration" 283 | time="2016-06-04T20:41:15+08:00" level=info msg="About to remove repository." \_file\_="manager.go:213" destPath="/tmp/fornax.Zz6jLZA7Wj/workdir/aliceUID/97858e8f-b5bd-40e1-a025-ac67057107e0" 284 | time="2016-06-04T20:41:15+08:00" level=info msg="Successfully removed repository with path" \_file\_="manager.go:229" destPath="/tmp/fornax.Zz6jLZA7Wj/workdir/aliceUID/97858e8f-b5bd-40e1-a025-ac67057107e0" 285 | time="2016-06-04T20:41:15+08:00" level=info msg="Event finished, close file" \_file\_="manager.go:146" file="/tmp/fornax.Zz6jLZA7Wj/workdir/aliceUID/logs/97858e8f-b5bd-40e1-a025-ac67057107e0" 286 | time="2016-06-04T20:41:18+08:00" level=info msg="fornax receives creating service request" \_file\_="service.go:74" service\_name=test-deploy-service user\_id=aliceUID 287 | time="2016-06-04T20:41:18+08:00" level=error \_file\_="manager.go:93" error="not found" user\_id=aliceUID 288 | time="2016-06-04T20:41:18+08:00" level=info msg="About to clone fake repository." \_file\_="fake.go:34" destPath="/tmp/fornax.Zz6jLZA7Wj/workdir/aliceUID/09fb9eb9-646d-46b4-97b7-c6cf1862b301" url="./tests/fake\_repo\_for\_test/deploy" 289 | time="2016-06-04T20:41:18+08:00" level=info msg="Successfully cloned fake repository." \_file\_="fake.go:41" destPath="/tmp/fornax.Zz6jLZA7Wj/workdir/aliceUID/09fb9eb9-646d-46b4-97b7-c6cf1862b301" url="./tests/fake\_repo\_for\_test/deploy" 290 | time="2016-06-04T20:41:18+08:00" level=info msg="About to remove repository." \_file\_="manager.go:213" destPath="/tmp/fornax.Zz6jLZA7Wj/workdir/aliceUID/09fb9eb9-646d-46b4-97b7-c6cf1862b301" 291 | time="2016-06-04T20:41:18+08:00" level=info msg="Successfully removed repository with path" \_file\_="manager.go:229" destPath="/tmp/fornax.Zz6jLZA7Wj/workdir/aliceUID/09fb9eb9-646d-46b4-97b7-c6cf1862b301" 292 | time="2016-06-04T20:41:18+08:00" level=info msg="Event finished, close file" \_file\_="manager.go:146" file="/tmp/fornax.Zz6jLZA7Wj/workdir/aliceUID/logs/09fb9eb9-646d-46b4-97b7-c6cf1862b301" 293 | time="2016-06-04T20:41:21+08:00" level=info msg="fornax receives creating version request" \_file\_="version.go:56" user\_id=aliceUID version={ 97858e8f-b5bd-40e1-a025-ac67057107e0 v0.1.0 A version just for Integration test [] [] [] 0001-01-01 00:00:00 +0000 UTC } 294 | time="2016-06-04T20:41:21+08:00" level=error \_file\_="manager.go:93" error="not found" user\_id=aliceUID 295 | time="2016-06-04T20:41:21+08:00" level=info msg="About to clone fake repository." \_file\_="fake.go:34" destPath="/tmp/fornax.Zz6jLZA7Wj/workdir/aliceUID/a600d5f3-88c2-4d1e-95da-6004b08aa1ad" url="./tests/fake\_repo\_for\_test/Integration" 296 | time="2016-06-04T20:41:21+08:00" level=info msg="Successfully cloned fake repository." \_file\_="fake.go:41" destPath="/tmp/fornax.Zz6jLZA7Wj/workdir/aliceUID/a600d5f3-88c2-4d1e-95da-6004b08aa1ad" url="./tests/fake\_repo\_for\_test/Integration" 297 | time="2016-06-04T20:41:21+08:00" level=info msg="the maximum number is 2\n" \_file\_="parser.go:99" 298 | time="2016-06-04T20:41:21+08:00" level=info msg="After apply, the userid aliceUID'sleft resource memory 805306368 cpu 768 numberContainers 2\n" \_file\_="resource.go:55" 299 | •time="2016-06-04T20:41:21+08:00" level=info msg="About to run integration event." \_file\_="manager.go:57" 300 | time="2016-06-04T20:41:21+08:00" level=info msg="About to pull the image." \_file\_="docker.go:202" image="localhost:5000/mongo:3.0.5" 301 | time="2016-06-04T20:41:21+08:00" level=info msg="Successfully pull docker image." \_file\_="manager.go:285" image="localhost:5000/mongo:3.0.5" 302 | time="2016-06-04T20:41:21+08:00" level=info msg="Successfully pull the image." \_file\_="docker.go:207" image="localhost:5000/mongo:3.0.5" 303 | time="2016-06-04T20:41:21+08:00" level=info msg="About to create the container." \_file\_="docker.go:209" config={mongo 0xc8201341c0 0xc82014a000} 304 | time="2016-06-04T20:41:22+08:00" level=info msg="Successfully create the container." \_file\_="docker.go:223" config={mongo 0xc8201341c0 0xc82014a000} 305 | time="2016-06-04T20:41:22+08:00" level=info msg="About to pull the image." \_file\_="docker.go:202" image="localhost:5000/alice/test-basic-rest-version:v0.1.0" 306 | time="2016-06-04T20:41:22+08:00" level=info msg="Successfully pull docker image." \_file\_="manager.go:285" image="localhost:5000/alice/test-basic-rest-version:v0.1.0" 307 | time="2016-06-04T20:41:22+08:00" level=info msg="Successfully pull the image." \_file\_="docker.go:207" image="localhost:5000/alice/test-basic-rest-version:v0.1.0" 308 | time="2016-06-04T20:41:22+08:00" level=info msg="About to create the container." \_file\_="docker.go:209" config={ 0xc820134380 0xc82014b180} 309 | time="2016-06-04T20:41:22+08:00" level=info msg="Successfully create the container." \_file\_="docker.go:223" config={ 0xc820134380 0xc82014b180} 310 | time="2016-06-04T20:41:32+08:00" level=info msg="Afer release, the userid aliceUID's left resource memory 939524096 cpu 896 numberContainers 1\n" \_file\_="resource.go:75" 311 | time="2016-06-04T20:41:32+08:00" level=info msg="About to run prebuild event." \_file\_="manager.go:73" 312 | time="2016-06-04T20:41:32+08:00" level=info msg="About to pull the image." \_file\_="docker.go:202" image="localhost:5000/alice/test-basic-rest-version:v0.1.0" 313 | time="2016-06-04T20:41:32+08:00" level=info msg="Successfully pull docker image." \_file\_="manager.go:285" image="localhost:5000/alice/test-basic-rest-version:v0.1.0" 314 | time="2016-06-04T20:41:32+08:00" level=info msg="Successfully pull the image." \_file\_="docker.go:207" image="localhost:5000/alice/test-basic-rest-version:v0.1.0" 315 | time="2016-06-04T20:41:32+08:00" level=info msg="About to create the container." \_file\_="docker.go:209" config={ 0xc8201348c0 0xc82014b500} 316 | time="2016-06-04T20:41:32+08:00" level=info msg="Successfully create the container." \_file\_="docker.go:223" config={ 0xc8201348c0 0xc82014b500} 317 | time="2016-06-04T20:41:32+08:00" level=info msg="copy file(/root/newfile) to /tmp/fornax.Zz6jLZA7Wj/workdir/aliceUID/a600d5f3-88c2-4d1e-95da-6004b08aa1ad/\n" \_file\_="docker.go:330" 318 | time="2016-06-04T20:41:32+08:00" level=info msg="docker copy file finished" \_file\_="docker.go:361" 319 | time="2016-06-04T20:41:32+08:00" level=info msg="About to build docker image." \_file\_="manager.go:125" image="localhost:5000/alice/test-basic-rest-version:v0.1.0" 320 | time="2016-06-04T20:41:36+08:00" level=info msg="Successfully built docker image." \_file\_="manager.go:153" image="localhost:5000/alice/test-basic-rest-version:v0.1.0" 321 | time="2016-06-04T20:41:36+08:00" level=info msg="About to push docker image." \_file\_="manager.go:172" image="localhost:5000/alice/test-basic-rest-version" tag=v0.1.0 322 | time="2016-06-04T20:41:36+08:00" level=info msg="Successfully pushed docker image." \_file\_="manager.go:188" image="localhost:5000/alice/test-basic-rest-version" 323 | time="2016-06-04T20:41:36+08:00" level=info msg="Successfully remove docker image." \_file\_="manager.go:239" image="localhost:5000/alice/test-basic-rest-version:v0.1.0" 324 | time="2016-06-04T20:41:36+08:00" level=info msg="About to run post build event." \_file\_="manager.go:84" 325 | time="2016-06-04T20:41:36+08:00" level=info msg="Successfully remove docker image." \_file\_="operations.go:91" image="localhost:5000/mongo:3.0.5" 326 | time="2016-06-04T20:41:36+08:00" level=info msg="remove docker image failed." \_file\_="operations.go:93" image="localhost:5000/alice/test-basic-rest-version:v0.1.0" 327 | time="2016-06-04T20:41:36+08:00" level=info msg="remove docker image failed." \_file\_="operations.go:93" image="localhost:5000/alice/test-basic-rest-version:v0.1.0" 328 | time="2016-06-04T20:41:36+08:00" level=info msg="Successfully remove docker image." \_file\_="operations.go:91" image=busybox 329 | time="2016-06-04T20:41:36+08:00" level=info msg="Afer release, the userid aliceUID's left resource memory 1073741824 cpu 1024 numberContainers 1\n" \_file\_="resource.go:75" 330 | time="2016-06-04T20:41:36+08:00" level=info msg="About to remove repository." \_file\_="manager.go:213" destPath="/tmp/fornax.Zz6jLZA7Wj/workdir/aliceUID/a600d5f3-88c2-4d1e-95da-6004b08aa1ad" 331 | time="2016-06-04T20:41:36+08:00" level=info msg="Successfully removed repository with path" \_file\_="manager.go:229" destPath="/tmp/fornax.Zz6jLZA7Wj/workdir/aliceUID/a600d5f3-88c2-4d1e-95da-6004b08aa1ad" 332 | time="2016-06-04T20:41:36+08:00" level=info msg="Event finished, close file" \_file\_="manager.go:146" file="/tmp/fornax.Zz6jLZA7Wj/workdir/aliceUID/logs/a600d5f3-88c2-4d1e-95da-6004b08aa1ad" 333 | time="2016-06-04T20:41:36+08:00" level=info msg="Successfully removed log file" \_file\_="log.go:71" filename=a600d5f3-88c2-4d1e-95da-6004b08aa1ad 334 | ------------------------------ 335 | • [SLOW TEST:16.003 seconds] 336 | Yaml 337 | /home/ubuntu/jenkins/workspace/fornax/src/github.com/caicloud/fornax/tests/yaml/yaml\_test.go:243 338 | with right version information 339 | /home/ubuntu/jenkins/workspace/fornax/src/github.com/caicloud/fornax/tests/yaml/yaml\_test.go:242 340 | with the default operation 341 | /home/ubuntu/jenkins/workspace/fornax/src/github.com/caicloud/fornax/tests/yaml/yaml\_test.go:152 342 | should be able to get version via HTTP GET method. 343 | /home/ubuntu/jenkins/workspace/fornax/src/github.com/caicloud/fornax/tests/yaml/yaml\_test.go:151 344 | ------------------------------ 345 | time="2016-06-04T20:41:37+08:00" level=info msg="fornax receives creating version request" \_file\_="version.go:56" user\_id=aliceUID version={ 97858e8f-b5bd-40e1-a025-ac67057107e0 v0.1.0-integration A version just for test [] [] [] 0001-01-01 00:00:00 +0000 UTC integration } 346 | time="2016-06-04T20:41:37+08:00" level=error \_file\_="manager.go:93" error="not found" user\_id=aliceUID 347 | time="2016-06-04T20:41:37+08:00" level=info msg="About to clone fake repository." \_file\_="fake.go:34" destPath="/tmp/fornax.Zz6jLZA7Wj/workdir/aliceUID/f93e8f3c-b9a9-4413-8f2c-8b0f4b110adf" url="./tests/fake\_repo\_for\_test/Integration" 348 | time="2016-06-04T20:41:37+08:00" level=info msg="Successfully cloned fake repository." \_file\_="fake.go:41" destPath="/tmp/fornax.Zz6jLZA7Wj/workdir/aliceUID/f93e8f3c-b9a9-4413-8f2c-8b0f4b110adf" url="./tests/fake\_repo\_for\_test/Integration" 349 | time="2016-06-04T20:41:37+08:00" level=info msg="the maximum number is 2\n" \_file\_="parser.go:99" 350 | time="2016-06-04T20:41:37+08:00" level=info msg="After apply, the userid aliceUID'sleft resource memory 805306368 cpu 768 numberContainers 2\n" \_file\_="resource.go:55" 351 | •time="2016-06-04T20:41:37+08:00" level=info msg="About to run integration event." \_file\_="manager.go:57" 352 | time="2016-06-04T20:41:37+08:00" level=info msg="About to pull the image." \_file\_="docker.go:202" image="localhost:5000/mongo:3.0.5" 353 | time="2016-06-04T20:41:37+08:00" level=info msg="Successfully pull docker image." \_file\_="manager.go:285" image="localhost:5000/mongo:3.0.5" 354 | time="2016-06-04T20:41:37+08:00" level=info msg="Successfully pull the image." \_file\_="docker.go:207" image="localhost:5000/mongo:3.0.5" 355 | time="2016-06-04T20:41:37+08:00" level=info msg="About to create the container." \_file\_="docker.go:209" config={mongo 0xc820135500 0xc820408380} 356 | time="2016-06-04T20:41:38+08:00" level=info msg="Successfully create the container." \_file\_="docker.go:223" config={mongo 0xc820135500 0xc820408380} 357 | time="2016-06-04T20:41:38+08:00" level=info msg="About to pull the image." \_file\_="docker.go:202" image="localhost:5000/alice/test-basic-rest-version:v0.1.0" 358 | time="2016-06-04T20:41:38+08:00" level=info msg="Successfully pull docker image." \_file\_="manager.go:285" image="localhost:5000/alice/test-basic-rest-version:v0.1.0" 359 | time="2016-06-04T20:41:38+08:00" level=info msg="Successfully pull the image." \_file\_="docker.go:207" image="localhost:5000/alice/test-basic-rest-version:v0.1.0" 360 | time="2016-06-04T20:41:38+08:00" level=info msg="About to create the container." \_file\_="docker.go:209" config={ 0xc820135a40 0xc820408700} 361 | time="2016-06-04T20:41:38+08:00" level=info msg="Successfully create the container." \_file\_="docker.go:223" config={ 0xc820135a40 0xc820408700} 362 | time="2016-06-04T20:41:48+08:00" level=info msg="Afer release, the userid aliceUID's left resource memory 939524096 cpu 896 numberContainers 1\n" \_file\_="resource.go:75" 363 | time="2016-06-04T20:41:48+08:00" level=info msg="Successfully remove docker image." \_file\_="operations.go:91" image="localhost:5000/mongo:3.0.5" 364 | time="2016-06-04T20:41:48+08:00" level=info msg="Successfully remove docker image." \_file\_="operations.go:91" image="localhost:5000/alice/test-basic-rest-version:v0.1.0" 365 | time="2016-06-04T20:41:48+08:00" level=info msg="Afer release, the userid aliceUID's left resource memory 1073741824 cpu 1024 numberContainers 1\n" \_file\_="resource.go:75" 366 | time="2016-06-04T20:41:48+08:00" level=info msg="About to remove repository." \_file\_="manager.go:213" destPath="/tmp/fornax.Zz6jLZA7Wj/workdir/aliceUID/f93e8f3c-b9a9-4413-8f2c-8b0f4b110adf" 367 | time="2016-06-04T20:41:48+08:00" level=info msg="Successfully removed repository with path" \_file\_="manager.go:229" destPath="/tmp/fornax.Zz6jLZA7Wj/workdir/aliceUID/f93e8f3c-b9a9-4413-8f2c-8b0f4b110adf" 368 | time="2016-06-04T20:41:48+08:00" level=info msg="Event finished, close file" \_file\_="manager.go:146" file="/tmp/fornax.Zz6jLZA7Wj/workdir/aliceUID/logs/f93e8f3c-b9a9-4413-8f2c-8b0f4b110adf" 369 | time="2016-06-04T20:41:48+08:00" level=info msg="Successfully removed log file" \_file\_="log.go:71" filename=f93e8f3c-b9a9-4413-8f2c-8b0f4b110adf 370 | ------------------------------ 371 | • [SLOW TEST:12.003 seconds] 372 | Yaml 373 | /home/ubuntu/jenkins/workspace/fornax/src/github.com/caicloud/fornax/tests/yaml/yaml\_test.go:243 374 | with right version information 375 | /home/ubuntu/jenkins/workspace/fornax/src/github.com/caicloud/fornax/tests/yaml/yaml\_test.go:242 376 | with the integration operation 377 | /home/ubuntu/jenkins/workspace/fornax/src/github.com/caicloud/fornax/tests/yaml/yaml\_test.go:194 378 | should be able to get version via HTTP GET method. 379 | /home/ubuntu/jenkins/workspace/fornax/src/github.com/caicloud/fornax/tests/yaml/yaml\_test.go:188 380 | ------------------------------ 381 | •time="2016-06-04T20:41:49+08:00" level=info msg="fornax receives creating version request" \_file\_="version.go:56" user\_id=aliceUID version={ 09fb9eb9-646d-46b4-97b7-c6cf1862b301 v0.1.0-deploy A version just for test deploy [] [] [] 0001-01-01 00:00:00 +0000 UTC publish } 382 | time="2016-06-04T20:41:49+08:00" level=error \_file\_="manager.go:93" error="not found" user\_id=aliceUID 383 | time="2016-06-04T20:41:49+08:00" level=info msg="About to clone fake repository." \_file\_="fake.go:34" destPath="/tmp/fornax.Zz6jLZA7Wj/workdir/aliceUID/05672924-024b-403f-a007-4cf4bb3b2948" url="./tests/fake\_repo\_for\_test/deploy" 384 | time="2016-06-04T20:41:49+08:00" level=info msg="Successfully cloned fake repository." \_file\_="fake.go:41" destPath="/tmp/fornax.Zz6jLZA7Wj/workdir/aliceUID/05672924-024b-403f-a007-4cf4bb3b2948" url="./tests/fake\_repo\_for\_test/deploy" 385 | time="2016-06-04T20:41:49+08:00" level=info msg="the maximum number is 0\n" \_file\_="parser.go:99" 386 | time="2016-06-04T20:41:49+08:00" level=info msg="After apply, the userid aliceUID'sleft resource memory 1073741824 cpu 1024 numberContainers 0\n" \_file\_="resource.go:55" 387 | time="2016-06-04T20:41:50+08:00" level=info msg="About to run prebuild event." \_file\_="manager.go:73" 388 | time="2016-06-04T20:41:50+08:00" level=info msg="About to build docker image." \_file\_="manager.go:125" image="localhost:5000/alice/test-deploy-service:v0.1.0-deploy" 389 | •time="2016-06-04T20:41:53+08:00" level=info msg="Successfully built docker image." \_file\_="manager.go:153" image="localhost:5000/alice/test-deploy-service:v0.1.0-deploy" 390 | time="2016-06-04T20:41:53+08:00" level=info msg="About to push docker image." \_file\_="manager.go:172" image="localhost:5000/alice/test-deploy-service" tag=v0.1.0-deploy 391 | time="2016-06-04T20:41:54+08:00" level=info msg="Successfully pushed docker image." \_file\_="manager.go:188" image="localhost:5000/alice/test-deploy-service" 392 | time="2016-06-04T20:41:54+08:00" level=info msg="Successfully remove docker image." \_file\_="manager.go:239" image="localhost:5000/alice/test-deploy-service:v0.1.0-deploy" 393 | time="2016-06-04T20:41:54+08:00" level=info msg="About to run post build event." \_file\_="manager.go:84" 394 | time="2016-06-04T20:41:54+08:00" level=error msg="Failed to deploy version" \_file\_="operations.go:162" err="Post http://127.0.0.1:3000/api/application/updateImage: malformed HTTP response \"\\x15\\x03\\x01\\x00\\x02\\x02\\x16\"" 395 | time="2016-06-04T20:41:54+08:00" level=info msg="Successfully remove docker image." \_file\_="operations.go:91" image=busybox 396 | time="2016-06-04T20:41:54+08:00" level=error msg="Operation failed" \_file\_="manager.go:134" event=&{05672924-024b-403f-a007-4cf4bb3b2948 create-version 0xc820260120 0xc8204ec690 0xc8204a4c00 map[service-name:test-deploy-service version-name:v0.1.0-deploy username:alice context-dir:/tmp/fornax.Zz6jLZA7Wj/workdir/aliceUID/05672924-024b-403f-a007-4cf4bb3b2948] 0x523be0 0xc82052be80 {false Post http://127.0.0.1:3000/api/application/updateImage: malformed HTTP response "\x15\x03\x01\x00\x02\x02\x16" false 0xc8204a4c60} {1 0} } 397 | time="2016-06-04T20:41:54+08:00" level=info msg="no container can release resource\n" \_file\_="resource.go:61" 398 | time="2016-06-04T20:41:54+08:00" level=info msg="About to remove repository." \_file\_="manager.go:213" destPath="/tmp/fornax.Zz6jLZA7Wj/workdir/aliceUID/05672924-024b-403f-a007-4cf4bb3b2948" 399 | time="2016-06-04T20:41:54+08:00" level=info msg="Successfully removed repository with path" \_file\_="manager.go:229" destPath="/tmp/fornax.Zz6jLZA7Wj/workdir/aliceUID/05672924-024b-403f-a007-4cf4bb3b2948" 400 | time="2016-06-04T20:41:54+08:00" level=info msg="Event finished, close file" \_file\_="manager.go:146" file="/tmp/fornax.Zz6jLZA7Wj/workdir/aliceUID/logs/05672924-024b-403f-a007-4cf4bb3b2948" 401 | time="2016-06-04T20:41:54+08:00" level=info msg="Successfully removed log file" \_file\_="log.go:71" filename=05672924-024b-403f-a007-4cf4bb3b2948 402 | time="2016-06-04T20:41:56+08:00" level=info msg="Error Message: Post http://127.0.0.1:3000/api/application/updateImage: malformed HTTP response \"\\x15\\x03\\x01\\x00\\x02\\x02\\x16\"\n" \_file\_="yaml\_test.go:226" 403 | ------------------------------ 404 | • [SLOW TEST:6.003 seconds] 405 | Yaml 406 | /home/ubuntu/jenkins/workspace/fornax/src/github.com/caicloud/fornax/tests/yaml/yaml\_test.go:243 407 | with right version information 408 | /home/ubuntu/jenkins/workspace/fornax/src/github.com/caicloud/fornax/tests/yaml/yaml\_test.go:242 409 | with the deploy operation 410 | /home/ubuntu/jenkins/workspace/fornax/src/github.com/caicloud/fornax/tests/yaml/yaml\_test.go:240 411 | should be able to get version via HTTP GET method. 412 | /home/ubuntu/jenkins/workspace/fornax/src/github.com/caicloud/fornax/tests/yaml/yaml\_test.go:228 413 | ------------------------------ 414 | • 415 | Ran 8 of 8 Specs in 66.912 seconds 416 | SUCCESS! -- 8 Passed | 0 Failed | 0 Pending | 0 Skipped --- PASS: TestYaml (66.91s) 417 | PASS 418 | ok github.com/caicloud/fornax/tests/yaml 66.945s 419 | Stopping fornax\_kafka\_1 ... 420 | Stopping fornax\_zookeeper\_1 ... 421 | ./tests/../scripts/local-up.sh: line 23: 15270 Aborted (core dumped) mongod -dbpath {TMPDIR}/db" --port 28017 >{MONGO\_LOG} 2>&1 422 | Stopping fornax\_kafka\_1 ... done 423 | Stopping fornax\_zookeeper\_1 ... done 424 | ./tests/run-e2e.sh: line 52: 15244 Terminated DOCKER\_HOST{DOCKER\_HOST:-"unix:///var/run/docker.sock"} ENABLE\_CAICLOUD\_AUTH="false" REGISTRY\_LOCATION="localhost:5000" REGISTRY\_USERNAME="admin" REGISTRY\_PASSWORD="admin\_password" KAFKA\_SERVER\_IP="localhost:9092" {FORNAX\_ROOT}"/scripts/local-up.sh @" 425 | Not including one-off containers created by `docker-compose run`. 426 | To include them, use `docker-compose rm --all`. 427 | This will be the default behavior in the next version of Compose. 428 | Removing fornax\_kafka\_1 ... 429 | Removing fornax\_zookeeper\_1 ... 430 | Removing fornax\_kafka\_1 ... done 431 | Removing fornax\_zookeeper\_1 ... done 432 | Going to remove fornax\_kafka\_1, fornax\_zookeeper\_1 433 | [Sat Jun 4 20:42:19 CST 2016] e2e test cleanup complete 434 | Started calculate disk usage of build 435 | Finished Calculation of disk usage of build in 0 seconds 436 | Started calculate disk usage of workspace 437 | Finished Calculation of disk usage of workspace in 0 seconds 438 | Setting status of 99d351b6a8c0c0e0f014bbfd0db09af42f57daf2 to SUCCESS with url http://43.254.54.241:8080/ and message: 'Build finished. No test results found.' 439 | Using context: e2e-test 440 | Finished: SUCCESS 441 | \end{lstlisting} -------------------------------------------------------------------------------- /thesis.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gaocegege/bachelor-paper-2016/29030d0abb9a84f698551c842ea1198d8d0b1b55/thesis.pdf -------------------------------------------------------------------------------- /thesis.tex: -------------------------------------------------------------------------------- 1 | %# -*- coding: utf-8-unix -*- 2 | %%================================================== 3 | %% thesis.tex 4 | %%================================================== 5 | 6 | % 双面打印 7 | % \documentclass[doctor, fontset=adobe, openright, twoside, zihao=-4]{sjtuthesis} 8 | \documentclass[bachelor, fontset=fandol, openany, oneside, zihao=5]{sjtuthesis} 9 | % \documentclass[master, adobefonts, review]{sjtuthesis} 10 | % \documentclass[% 11 | % bachelor|master|doctor, % 必选项 12 | % fontset=adobe|windows, % 只测试了adobe 13 | % oneside|twoside, % 单面打印,双面打印(奇偶页交换页边距,默认) 14 | % openany|openright, % 可以在奇数或者偶数页开新章|只在奇数页开新章(默认) 15 | % zihao=-4|5,, % 正文字号:小四、五号(默认) 16 | % review, % 盲审论文,隐去作者姓名、学号、导师姓名、致谢、发表论文和参与的项目 17 | % submit % 定稿提交的论文,插入签名扫描版的原创性声明、授权声明 18 | % ] 19 | 20 | \begin{document} 21 | 22 | %% 无编号内容:中英文论文封面、授权页 23 | \include{tex/id} 24 | \maketitle 25 | 26 | % \makeenglishtitle 27 | 28 | \makeatletter 29 | \ifsjtu@submit\relax 30 | \includepdf{pdf/original.pdf} 31 | \cleardoublepage 32 | \includepdf{pdf/authorization.pdf} 33 | \cleardoublepage 34 | \else 35 | \makeDeclareOriginal 36 | \makeDeclareAuthorization 37 | \fi 38 | \makeatother 39 | 40 | 41 | \frontmatter % 使用罗马数字对前言编号 42 | 43 | %% 摘要 44 | \pagestyle{front} 45 | \include{tex/abstract} 46 | 47 | %% 目录、插图目录、表格目录 48 | \tableofcontents 49 | % \listoffigures 50 | % \addcontentsline{toc}{chapter}{\listfigurename} %将插图目录加入全文目录 51 | % \listoftables 52 | % \addcontentsline{toc}{chapter}{\listtablename} %将表格目录加入全文目录 53 | % \listofalgorithms 54 | % \addcontentsline{toc}{chapter}{算法索引} %将算法目录加入全文目录 55 | 56 | % \include{tex/symbol} % 主要符号、缩略词对照表 57 | 58 | \mainmatter % 使用阿拉伯数字对正文编号 59 | 60 | %% 正文内容 61 | \pagestyle{main} 62 | \include{tex/intro} 63 | % \include{tex/tech} 64 | \include{tex/impl} 65 | \include{tex/detail} 66 | \include{tex/test} 67 | \include{tex/summary} 68 | 69 | \appendix % 使用英文字母对附录编号,重新定义附录中的公式、图图表编号样式 70 | \renewcommand\theequation{\Alph{chapter}--\arabic{equation}} 71 | \renewcommand\thefigure{\Alph{chapter}--\arabic{figure}} 72 | \renewcommand\thetable{\Alph{chapter}--\arabic{table}} 73 | \renewcommand\thealgorithm{\Alph{chapter}--\arabic{algorithm}} 74 | 75 | %% 附录内容,本科学位论文可以用翻译的文献替代。 76 | \include{tex/test_result} 77 | \include{tex/config} 78 | % \include{tex/app_cjk} 79 | % \include{tex/app_log} 80 | 81 | \backmatter % 文后无编号部分 82 | 83 | %% 参考资料 84 | % \phantomsection 85 | % \addcontentsline{toc}{chapter}{参考文献} 86 | \bibliography{bib/thesis.bib} 87 | 88 | %% 致谢、发表论文、申请专利、参与项目、简历 89 | %% 用于盲审的论文需隐去致谢、发表论文、申请专利、参与的项目 90 | \makeatletter 91 | 92 | %% 93 | % "研究生学位论文送盲审印刷格式的统一要求" 94 | % http://www.gs.sjtu.edu.cn/inform/3/2015/20151120_123928_738.htm 95 | 96 | % 盲审删去删去致谢页 97 | \ifsjtu@review\relax\else 98 | \include{tex/ack} %% 致谢 99 | \fi 100 | 101 | \ifsjtu@bachelor 102 | % 学士学位论文要求在最后有一个英文大摘要,单独编页码 103 | \pagestyle{biglast} 104 | \include{tex/end_english_abstract} 105 | \else 106 | % 盲审论文中,发表学术论文及参与科研情况等仅以第几作者注明即可,不要出现作者或他人姓名 107 | \ifsjtu@review\relax 108 | \include{tex/pubreview} 109 | \include{tex/projectsreview} 110 | \else 111 | \include{tex/pub} %% 发表论文 112 | \include{tex/projects} %% 参与的项目 113 | \fi 114 | \fi 115 | 116 | % \include{tex/patents} %% 申请专利 117 | % \include{tex/resume} %% 个人简历 118 | % \makeatother 119 | 120 | \end{document} 121 | --------------------------------------------------------------------------------