UNPKG

5.88 kBJavaScriptView Raw
1'use strict';
2
3const _ = require('lodash');
4
5const debug = require('debug')('fun:nas');
6
7const { red } = require('colors');
8const { getProfile } = require('./profile');
9const { getFcClient, getNasPopClient } = require('./client');
10const { promptForConfirmContinue } = require('./init/prompt');
11
12var requestOption = {
13 method: 'POST'
14};
15
16async function createDefaultVSwitch(vpcClient, region, vpcId, vswitchName) {
17 const vswitchZoneId = await selectAllowedVSwitchZone(vpcClient, region);
18
19 var vswitchId;
20 try {
21 // 创建 vswitch
22 vswitchId = await createVSwitch(vpcClient, {
23 region,
24 vpcId,
25 zoneId: vswitchZoneId,
26 vswitchName: vswitchName
27 });
28 } catch (ex) {
29 throw ex;
30 }
31 return vswitchId;
32}
33
34async function describeVSwitchAttributes(vpcClient, region, vswitchId) {
35 const params = {
36 'RegionId': region,
37 'VSwitchId': vswitchId
38 };
39 return await vpcClient.request('DescribeVSwitchAttributes', params, requestOption);
40}
41
42async function getVSwitchZoneId(vpcClient, region, vswitchId) {
43 const describeRs = await describeVSwitchAttributes(vpcClient, region, vswitchId);
44 return (describeRs || {}).ZoneId;
45}
46
47async function getVSwitchName(vpcClient, region, vswitchId) {
48 const describeRs = await describeVSwitchAttributes(vpcClient, region, vswitchId);
49 return (describeRs || {}).VSwitchName;
50}
51
52async function findVswitchExistByName(vpcClient, region, vswitchIds, searchVSwtichName) {
53
54 if (!_.isEmpty(vswitchIds)) {
55 for (let vswitchId of vswitchIds) {
56
57 const vswitchName = await getVSwitchName(vpcClient, region, vswitchId);
58
59 if (_.isEqual(searchVSwtichName, vswitchName)) {
60 debug('found default vswitchId: ' + vswitchId);
61
62 return vswitchId;
63 }
64 }
65 }
66
67 debug('could not find %s from %j for region %s', searchVSwtichName, vswitchIds, region);
68
69 return null;
70}
71
72async function createVSwitch(vpcClient, {
73 region,
74 vpcId,
75 zoneId,
76 vswitchName
77}) {
78 var params = {
79 'RegionId': region,
80 'VpcId': vpcId,
81 'ZoneId': zoneId,
82 'CidrBlock': '10.20.0.0/16',
83 'VSwitchName': vswitchName,
84 'Description': 'default vswitch created by fc fun'
85 };
86
87 debug('createVSwitch params is %j', params);
88
89 const createRs = await vpcClient.request('CreateVSwitch', params, requestOption);
90
91 return createRs.VSwitchId;
92}
93
94async function selectVSwitchZoneId(fcAllowedZones, vpcZones, nasZones) {
95
96 const allowedZones = _.filter(vpcZones, z => {
97 return _.includes(fcAllowedZones, z.ZoneId) && _.includes(nasZones.map(zone => { return zone.ZoneId; }), z.ZoneId);
98 });
99
100 const sortedZones = _.sortBy(allowedZones, ['ZoneId']);
101
102 return (_.head(sortedZones) || {}).ZoneId;
103}
104
105async function getFcAllowedZones() {
106 const fc = await getFcClient();
107
108 const fcRs = await fc.getAccountSettings();
109
110 const fcAllowedZones = fcRs.data.availableAZs;
111
112 debug('fc allowed zones: %j', fcAllowedZones);
113
114 if (_.isEqual(fcAllowedZones, [''])) {
115
116 const profile = await getProfile();
117
118 throw new Error(red(`No fc vswitch zones allowed, you may need login to fc console to apply for VPC feature: https://fc.console.aliyun.com/overview/${profile.defaultRegion}`));
119 }
120
121 return fcAllowedZones;
122}
123
124async function selectAllowedVSwitchZone(vpcClient, region) {
125 const nasClient = await getNasPopClient();
126
127 const fcAllowedZones = await getFcAllowedZones();
128 const vpcZones = await describeVpcZones(vpcClient, region);
129 const nasZones = await require('./nas').describeNasZones(nasClient, region);
130
131 const usedZoneId = await selectVSwitchZoneId(fcAllowedZones, vpcZones, nasZones);
132
133 if (!usedZoneId) {
134 throw new Error('no availiable zone for vswitch');
135 }
136
137 debug('select allowed switch zone: ', usedZoneId);
138
139 return usedZoneId;
140}
141
142async function describeVpcZones(vpcClient, region) {
143 const params = {
144 'RegionId': region
145 };
146
147 const zones = await vpcClient.request('DescribeZones', params, requestOption);
148 return zones.Zones.Zone;
149}
150
151async function convertToFcAllowedZoneMap(vpcClient, region, vswitchIds) {
152 const fcAllowedZones = await getFcAllowedZones();
153 const zoneMap = new Map();
154
155 for (const vswitchId of vswitchIds) {
156 const zoneId = await getVSwitchZoneId(vpcClient, region, vswitchId);
157 if (_.includes(fcAllowedZones, zoneId)) {
158 zoneMap.set(zoneId, vswitchId);
159 }
160 }
161 if (_.isEmpty(zoneMap)) {
162 throw new Error(`
163Only zoneId ${fcAllowedZones} of vswitch is allowed by VpcConfig.
164Check your vswitch zoneId please.`);
165 }
166
167 return zoneMap;
168}
169
170function convertZones(zones, zoneMap, storageType = 'Performance') {
171 const zoneId = zones.ZoneId;
172 return {
173 zoneId,
174 vswitchId: zoneMap.get(zoneId),
175 storageType
176 };
177}
178
179async function getAvailableVSwitchId(vpcClient, region, vswitchIds, nasZones) {
180
181 const zoneMap = await convertToFcAllowedZoneMap(vpcClient, region, vswitchIds);
182
183 for (const zoneId of zoneMap.keys()) {
184 if (!_.includes(nasZones.map(m => { return m.ZoneId; }), zoneId)) {
185 zoneMap.delete(zoneId);
186 }
187 }
188 const performances = [];
189 const capacities = [];
190
191 _.forEach(nasZones, nasZone => {
192 if (_.includes([...zoneMap.keys()], nasZone.ZoneId)) {
193 if (!_.isEmpty(nasZone.Performance.Protocol)) { performances.push(nasZone); }
194 if (!_.isEmpty(nasZone.Capacity.Protocol)) { capacities.push(nasZone); }
195 }
196 });
197
198 if (!_.isEmpty(performances)) {
199 return convertZones(_.head(performances), zoneMap);
200 }
201
202 if (!_.isEmpty(capacities)) {
203 const yes = await promptForConfirmContinue(`Region ${region} only supports capacity NAS. Do you want to create it automatically?`);
204 if (yes) { return convertZones(_.head(capacities), zoneMap, 'Capacity'); }
205 }
206
207 throw new Error(`No NAS service available under region ${region}.`);
208}
209
210module.exports = {
211 findVswitchExistByName,
212 selectVSwitchZoneId,
213 createVSwitch,
214 createDefaultVSwitch,
215 getAvailableVSwitchId
216};
\No newline at end of file