OpenStack三个节点icehouse-gre模式部署一文部署了一套OpenStack环境,接下来使用命令测试一遍。
一、查看nova和neutron服务,确保都是笑脸
#Nova-manage service list
Binary Host Zone Status State Updated_At
nova-cert controller internal enabled :-) 2015-01-12 00:39:05
nova-consoleauth controller internal enabled :-) 2015-01-12 00:38:59
nova-scheduler controller internal enabled :-) 2015-01-12 00:39:00
nova-conductor controller internal enabled :-) 2015-01-12 00:39:03
nova-compute compute1 nova enabled :-) 2015-01-12 00:39:03
#neutron agent-list
+--------------------------------------+--------------------+----------+-------+----------------+
| id | agent_type | host | alive | admin_state_up |
+--------------------------------------+--------------------+----------+-------+----------------+
| 7a1f9910-62d8-4461-b31d-1a562bd0b76e | DHCP agent | network | :-) | True |
| 86d1c916-8b05-4840-965c-e9152388e0c2 | Open vSwitch agent | compute1 | :-) | True |
| 8809b0e3-010d-4d2f-b552-10be24002684 | Open vSwitch agent | network | :-) | True |
| aca01734-7522-427a-b3f2-45400d22121c | Metadata agent | network | :-) | True |
| e964a21a-4b8d-403b-9c81-2a95f387285e | L3 agent | network | :-) | True |
+--------------------------------------+--------------------+----------+-------+----------------+
二、创建租户和用户
创建租户
# keystone tenant-create --name TenantA
WARNING: Bypassing authentication using a token & endpoint (authentication credentials are being ignored).
+-------------+----------------------------------+
| Property | Value |
+-------------+----------------------------------+
| description | |
| enabled | True |
| id | 60a10cd7a61b493d910eabd353c07567 |
| name | TenantA |
+-------------+----------------------------------+
创建用户
# keystone user-create --name=UserA --pass=password --tenant-id TenantA --email=usera@test.com
WARNING: Bypassing authentication using a token & endpoint (authentication credentials are being ignored).
+----------+----------------------------------+
| Property | Value |
+----------+----------------------------------+
| email | usera@test.com |
| enabled | True |
| id | be1db0d2fd134025accd2654cfc66056 |
| name | UserA |
| tenantId | 60a10cd7a61b493d910eabd353c07567 |
| username | UserA |
+----------+----------------------------------+
为租户添加用户
#keystone user-role-add --tenant TenantA --user UserA --role Member
WARNING: Bypassing authentication using a token & endpoint (authentication credentials are being ignored).
三、准备neutron网络
创建外网
# neutron net-create Ext-Net --provider:network_type gre --provider:segmentation_id 1 --router:external true
Created a new network:
+---------------------------+--------------------------------------+
| Field | Value |
+---------------------------+--------------------------------------+
| admin_state_up | True |
| id | c8699820-7c6d-4441-9602-3425f2c630ec |
| name | Ext-Net |
| provider:network_type | gre |
| provider:physical_network | |
| provider:segmentation_id | 1 |
| router:external | True |
| shared | False |
| status | ACTIVE |
| subnets | |
| tenant_id | c91d0723aaea4985a77801a15ef66438 |
+---------------------------+--------------------------------------+
创建外网的子网
# neutron subnet-create --allocation-pool start=10.1.101.80,end=10.1.101.100 --gateway 10.1.101.254 Ext-Net 10.1.101.0/24 --enable_dhcp=False
Created a new subnet:
+------------------+-------------------------------------------------+
| Field | Value |
+------------------+-------------------------------------------------+
| allocation_pools | {"start": "10.1.101.80", "end": "10.1.101.100"} |
| cidr | 10.1.101.0/24 |
| dns_nameservers | |
| enable_dhcp | False |
| gateway_ip | 10.1.101.254 |
| host_routes | |
| id | 2c4155c9-5a2e-471c-a4d8-40a86b45ab0a |
| ip_version | 4 |
| name | |
| network_id | c8699820-7c6d-4441-9602-3425f2c630ec |
| tenant_id | c91d0723aaea4985a77801a15ef66438
本文由 CYJB 译自 Type Design Guidelines(.NET Framework 4.5)。
对 CLR 来说,只存在两种类型——引用类型和值类型。但是为了讨论框架设计,我们将类型细分为更多的逻辑组,每组有其特定的设计准则。
类是通用的引用类型,框架中的大部分类型都是类。类因其支持面向对象的大部分特性和普遍适应性而大受欢迎。基类和抽象类是与扩展性相关的特殊逻辑组。
接口是可以由引用类型和值类型实现的类型。它们可以作为引用类型和值类型的层次结构的根,或者模拟多重继承(CLR 本身并不支持多重继承)。
结构体是通用的值类型,用于表示小的简单类型,类似于语言的基本类型。
枚举是特殊的值类型,用于定义值的集合,例如星期、控制台颜色等等。
静态类是设计用来包含静态成员的类型,通常用于提供其它操作的快捷方式。
委托、异常、特性、数组和集合都是针对特定用途的特殊引用类型,它们的设计和使用准则会在本书的其它位置讨论。
√ 要确保每个类型都是相关成员的良好定义的集合,而不仅仅是无关函数的随机集合。
选择类或结构体
每个框架设计师都会面对的基本决定之一,就是将一个类型设计为类(引用类型)还是结构体(值类型),因此很有必要了解引用类型和值类型之间的行为区别。
引用类型和值类型的第一个区别,是引用类型分配在堆(heap)上,会被垃圾回收;而值类型分配在栈(stack)上,或被�联入包含类型中,在栈展开或包含类型被释放时回收。所以值类型的分配和回收通常比引用类型的开销更小。
其次,引用类型的数组并不连续分配,也就是说数组元素仅仅是对位于堆上的引用类型实例的引用。值类型的数组则是连续分配的,意味着数组元素实际上就是值类型的实例。所以,值类型数组的分配和回收也比引用类型数组的开销更少。另外,大多数情况下值类型数组比引用类型数组表现出更好的局部性。
然后是与内存使用相关的区别。值类型在被转换为引用类型或实现的接口时会被装箱,在转换回值类型时会被拆箱。由于装箱的结果是分配在堆上的对象,会被垃圾回收,太多的装箱和拆箱会对堆和垃圾回收器造成负面影响,最终会影响到应用的性能。相比之下,引用类型被转换时不会发生装箱。
接下来,引用类型赋值时会复制引用,而值类型赋值时会复制完整的值。所以,巨大的引用类型的赋值,比巨大的值类型的赋值开销更少。
最后,引用类型会按引用传递,而值类型会按值传递。对引用类型实例的改变,会影响到所有指向该实例的引用。值类型的实例会在按值传递时复制,当值类型的实例被改变时,显然不会影响到它的其它副本。由于值类型的副本不是由用户显式创建的,而是在参数传递或返回值返回时隐式创建的,可变的值类型可能会使许多用户迷惑,因此,值类型应当是不可变的。
根据经验,框架中的大部分类型应该是类。然而,还有一些情况,值类型的特性使得其更适合使用结构体。
√ 考虑定义结构体而不是类,如果类型的实例很小,而且通常生命周期短或嵌入在其它对象中。
X 不要定义结构体,除非该类型具备以下所有特点:
- 它在逻辑上表示单个值,与基元类型(int、double 等)类似。
- 它的实例大小小于 16 字节。
- 它是不可变的。
- 它不会需要频繁的被装箱。
在其它所有情况下,您都应当把您的类型定义为类。
抽象类设计
X 不要在抽象类中定义 public 或 protected internal 构造函数。
只有用户需要创建类型的实例时才需要公共构造函数。由于您不能创建抽象类型的实例,具有公共构造函数的抽象类型是错误的设计,而且会误导用户。
√ 要为抽象类定义 protected 或 internal 构造函数。
一个 protected 构造函数更加常见,而且允许基类在子类创建时完成它自己的初始化。
一个 internal 构造函数可以用来将抽象类的具体实现限制在定义该类的程序集中。
√ 要为您提供的每个抽象类,提供至少一个具体的继承类型。
这样做有助于验证抽象类的设计。例如,System.IO.FileStream 是 System.IO.Stream 抽象类的一个实现。
静态类设计
一个静态类是只包含静态成员的类(当然除了继承自 System.Object 的实例成员和可能的 private 构造函数)。一些语言提供内建的静态类支持。在 C# 2.0 以及更高版本,当一个类被定义为 static,它就是密封的、抽象的,而且没有可以声明或重写的实例成员。
静态类是在纯面向对象设计和简洁性之间的妥协,它们一般用于提供其它操作的快捷方式(例如 System.IO.File),储存扩展方法或不适合使用完全面向对象包装的功能(例如 System.Environment)。
√ 要谨慎使用静态类。
静态类应当仅用于支持框架中的面向对象核心类。
X 不要认为静态类可以无所不包。
X 不要在静态类中声明或重写实例成员。
√ 要将静态类声明为密封的、抽象的,并且添加一个私有成员构造函数,如果您使用的编程语言没有内建的静态类支持。
接口设计
尽管大部分 API 最适合使用类和结构体建模,有些情况下接口是更合适的或者是唯一的选择。
CLR 并不支持多继承(即 CLR 的类不能继承自多于一个的基类),但它允许类型在继承自一个基类之外实现一个或多个接口。因此,接口经常用于实现多重继承的效果。例如,IDisposable 是一个允许类型支持资源释放的接口,它独立于其它任何继承层次结构。
另一个适合定义接口的情形是创建可以由多个类型(包括值类型)支持的公共接口。值类型不能继承自 ValueType 以外的其它类型,但它们可以实现接口,因此使用接口就成为了能够提供公共基本类型的唯一选项。
√ 要定义接口,如果您需要一些由包含值类型的多个类型支持的公共 API。
√ 考虑定义接口,如果您在已经从其它类型继承的类型上支持其功能。
X 避免使用标记接口(没有任何成员的接口)。
如果您需要将一个类标为具有特殊的特性(标记),一般而言,使用自定义特性(Attribute)而不是接口。
√ 要为接口提供至少一个实现的类型。
这样会有助于验证接口的实现。例如,List<T> 是 IList<T> 接口的一个实现。
√ 要为您定义的每个接口,都提供至少一个用到它的 API(将接口作为参数的方法,或类型为该接口的属性)。
这样会有助于验证接口的设计。例如,List<T>.Sort 会用到 System.Collections.Generic.IComparer<T> 接口。
X 不要向已被公开的接口添加成员。
这样可能会破坏接口的现有实现。您应当创建一个新接口来避免版本问题。
在设计可重用的托管代码库时,除了上面所述的情况,一般您都应当选择使用类而不是接口。
结构体设计
通用值类型常被称作 struct(结构体),这个一个 C# 关键字。这节提供了一般的结构体设计准则。
X 不要为结构体提供默认构造函数。
遵循这一准则,允许创建结构体数组而无需为每个数组元素调用构造函数。请注意 C# 并不允许为结构体提供默认构造函数。
X 不要定义可变的结构体。
可变的结构体存在一些问题。例如,当属性的 get 访问器返回了一个值类型,调用者会得到返回值的副本。因为副本是隐式创建的,因此开发者可能并未意识到他们在修改副本,而不是原始值。此外,一些语言(特别是动态语言)在使用可变的值类型时会有问题,因为即使是局部变量,在取消引用时也会产生副本。
√ 要确保所有实例数据被设置为 0、false 或者 null(适用时)的状态是有效的。
这是为了防止在创建结构体数组的时候意外的创建了无效的实例。
√ 要在值类型上实现 IEquatable<T>。
值类型的 Object.Equals 方法会导致装箱操作,而且它的默认实现由于使用了反射,因而并不非常高效。实现 IEquatable<T>.Equals 方法可以具有更高的性能,而且不会导致装箱。
X 不要显示扩展 ValueType。事实上,大部分语言会阻止这样做。
通常,结构体可以非常有用,但仅应当被用于小的(译注:如上文所述,小于 16 字节)、单一的、不可变的且不会被频繁装箱的值。
枚举设计
枚举是特殊的值类型,分为简单枚举和标志枚举两种。
简单枚举表示了选择的小的闭集。一个常见的简单枚举的例子是一组颜色。
标志枚举是为使枚举值支持位运算而设计的。一个常见的标志枚举的例子是一个选项列表。
√ 要使用枚举强类型化表示值的集合的参数、属性和返回值。
√ 要优先使用枚举而不是静态常量。
X 不要对开放集(如操作系统版本,您朋友的名字等)使用枚举。
X 不要提供计划将来使用的保留枚举值。
您总是可以简单地在后期为现有枚举添加值。请参见向枚举添加值,获取向枚举添加值的更多信息。保留值只会污染了真实的值,并往往导致用户错误。
X 避免公开暴露只包含一个值的枚举。
确保 C API 的未来可扩展性的一个常见做法是为方法签名添加保留参数。这样的保留参数可以被表示含有单个默认值的枚举。在托管 API 中不应该这样做,方法重载允许在未来的版本中添加参数。
X 不要在枚举中包含哨兵值。
尽管哨兵值有时能帮助到框架开发者,但会混淆框架的用户。它们被用于跟踪枚举的状态,而不是枚举表示的集合中的一个值。
√ 要在简单枚举中提供一个零值。
考虑将零值命名为 "None"。如果 "None" 不适于这个枚举,应当将基础值零分配给枚举最常见的默认值。
√ 考虑使用 Int32(大多数编程语言的默认数据类型)作为枚举的基础类型,除非出现了以下任何一种情况:
没有评论:
发表评论